diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..7a4b3b349e0 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,21 @@ +# .git-blame-ignore-revs +# Auto-formatted Java +730eae952139209fe9fdf598541d608f4c0c0c84 +# Auto-formatted C# +5ad7ed49dd3de03ec6dcfcb6848758a6a987e11c +# Auto-formatted C/C++ +ef97e539ec1971494d4bba5cafe82e00bc8217ac +# Auto-formatted Python +21d5fa836b3a7d020ba45e8b8168b145a9772131 +# Auto-formatted JavaScript +8d97fe9ed327a9546ff2eaf515cf0f5214deddd9 +# Auto-formatted Ruby +a5d229903d2f12d45f2c2c38822f1d0e7504ae7f +# Auto-formatted Go +08c658e66bf867090033ea096e244a93d46c0aa7 +# Auto-formatted Swift +711d7057f79fb7d72fc3b35e010bd018f9009169 +# Auto-formatted shared ql packs +3640b6d3a8ce9edf8e1d3ed106fe8526cf255bc0 +# Auto-formatted taint tracking files +159d8e978c51959b380838c080d891b66e763b19 diff --git a/.github/workflows/go-tests-other-os.yml b/.github/workflows/go-tests-other-os.yml index 97207f573c0..5660b2cc3fa 100644 --- a/.github/workflows/go-tests-other-os.yml +++ b/.github/workflows/go-tests-other-os.yml @@ -13,7 +13,7 @@ jobs: runs-on: macos-latest steps: - name: Set up Go 1.20 - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.20.0 id: go @@ -48,7 +48,7 @@ jobs: runs-on: windows-latest-xl steps: - name: Set up Go 1.20 - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.20.0 id: go diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index 4cf299e5e44..064c0896e14 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-latest-xl steps: - name: Set up Go 1.20 - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: 1.20.0 id: go diff --git a/.github/workflows/ruby-build.yml b/.github/workflows/ruby-build.yml index bdb09bc9c7e..6fdd497a802 100644 --- a/.github/workflows/ruby-build.yml +++ b/.github/workflows/ruby-build.yml @@ -55,12 +55,12 @@ jobs: id: cache-extractor with: path: | - ruby/target/release/ruby-autobuilder - ruby/target/release/ruby-autobuilder.exe - ruby/target/release/ruby-extractor - ruby/target/release/ruby-extractor.exe - ruby/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll - key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }}--${{ hashFiles('ruby/**/*.rs') }} + ruby/extractor/target/release/autobuilder + ruby/extractor/target/release/autobuilder.exe + ruby/extractor/target/release/extractor + ruby/extractor/target/release/extractor.exe + ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll + key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}--${{ hashFiles('ruby/extractor/**/*.rs') }} - uses: actions/cache@v3 if: steps.cache-extractor.outputs.cache-hit != 'true' with: @@ -68,22 +68,22 @@ jobs: ~/.cargo/registry ~/.cargo/git ruby/target - key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/rust-toolchain.toml', 'ruby/**/Cargo.lock') }} + key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-rust-cargo-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/**/Cargo.lock') }} - name: Check formatting if: steps.cache-extractor.outputs.cache-hit != 'true' - run: cargo fmt --all -- --check + run: cd extractor && cargo fmt --all -- --check - name: Build if: steps.cache-extractor.outputs.cache-hit != 'true' - run: cargo build --verbose + run: cd extractor && cargo build --verbose - name: Run tests if: steps.cache-extractor.outputs.cache-hit != 'true' - run: cargo test --verbose + run: cd extractor && cargo test --verbose - name: Release build if: steps.cache-extractor.outputs.cache-hit != 'true' - run: cargo build --release + run: cd extractor && cargo build --release - name: Generate dbscheme if: ${{ matrix.os == 'ubuntu-latest' && steps.cache-extractor.outputs.cache-hit != 'true'}} - run: target/release/ruby-generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll + run: extractor/target/release/generator --dbscheme ql/lib/ruby.dbscheme --library ql/lib/codeql/ruby/ast/internal/TreeSitter.qll - uses: actions/upload-artifact@v3 if: ${{ matrix.os == 'ubuntu-latest' }} with: @@ -98,10 +98,10 @@ jobs: with: name: extractor-${{ matrix.os }} path: | - ruby/target/release/ruby-autobuilder - ruby/target/release/ruby-autobuilder.exe - ruby/target/release/ruby-extractor - ruby/target/release/ruby-extractor.exe + ruby/extractor/target/release/autobuilder + ruby/extractor/target/release/autobuilder.exe + ruby/extractor/target/release/extractor + ruby/extractor/target/release/extractor.exe retention-days: 1 compile-queries: runs-on: ubuntu-latest-xl @@ -116,21 +116,22 @@ jobs: key: ruby-build - name: Build Query Pack run: | - rm -rf target/packs - codeql pack create ../misc/suite-helpers --output target/packs - codeql pack create ../shared/regex --output target/packs - codeql pack create ../shared/ssa --output target/packs - codeql pack create ../shared/tutorial --output target/packs - codeql pack create ql/lib --output target/packs - codeql pack create -j0 ql/src --output target/packs --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" - PACK_FOLDER=$(readlink -f target/packs/codeql/ruby-queries/*) + PACKS=${{ runner.temp }}/query-packs + rm -rf $PACKS + codeql pack create ../misc/suite-helpers --output "$PACKS" + codeql pack create ../shared/regex --output "$PACKS" + codeql pack create ../shared/ssa --output "$PACKS" + codeql pack create ../shared/tutorial --output "$PACKS" + codeql pack create ql/lib --output "$PACKS" + codeql pack create -j0 ql/src --output "$PACKS" --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" + PACK_FOLDER=$(readlink -f "$PACKS"/codeql/ruby-queries/*) codeql generate query-help --format=sarifv2.1.0 --output="${PACK_FOLDER}/rules.sarif" ql/src (cd ql/src; find queries \( -name '*.qhelp' -o -name '*.rb' -o -name '*.erb' \) -exec bash -c 'mkdir -p "'"${PACK_FOLDER}"'/$(dirname "{}")"' \; -exec cp "{}" "${PACK_FOLDER}/{}" \;) - uses: actions/upload-artifact@v3 with: name: codeql-ruby-queries path: | - ruby/target/packs/* + ${{ runner.temp }}/query-packs/* retention-days: 1 package: @@ -158,12 +159,12 @@ jobs: mkdir -p ruby cp -r codeql-extractor.yml tools ql/lib/ruby.dbscheme.stats ruby/ mkdir -p ruby/tools/{linux64,osx64,win64} - cp linux64/ruby-autobuilder ruby/tools/linux64/autobuilder - cp osx64/ruby-autobuilder ruby/tools/osx64/autobuilder - cp win64/ruby-autobuilder.exe ruby/tools/win64/autobuilder.exe - cp linux64/ruby-extractor ruby/tools/linux64/extractor - cp osx64/ruby-extractor ruby/tools/osx64/extractor - cp win64/ruby-extractor.exe ruby/tools/win64/extractor.exe + cp linux64/autobuilder ruby/tools/linux64/autobuilder + cp osx64/autobuilder ruby/tools/osx64/autobuilder + cp win64/autobuilder.exe ruby/tools/win64/autobuilder.exe + cp linux64/extractor ruby/tools/linux64/extractor + cp osx64/extractor ruby/tools/osx64/extractor + cp win64/extractor.exe ruby/tools/win64/extractor.exe chmod +x ruby/tools/{linux64,osx64}/{autobuilder,extractor} zip -rq codeql-ruby.zip ruby - uses: actions/upload-artifact@v3 diff --git a/CODEOWNERS b/CODEOWNERS index 8371dd768cd..856d325b487 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -2,9 +2,9 @@ /csharp/ @github/codeql-csharp /go/ @github/codeql-go /java/ @github/codeql-java -/javascript/ @github/codeql-dynamic -/python/ @github/codeql-dynamic -/ruby/ @github/codeql-dynamic +/javascript/ @github/codeql-javascript +/python/ @github/codeql-python +/ruby/ @github/codeql-ruby /swift/ @github/codeql-swift /misc/codegen/ @github/codeql-swift /java/kotlin-extractor/ @github/codeql-kotlin diff --git a/config/identical-files.json b/config/identical-files.json index c32bad48362..a9c73bf1690 100644 --- a/config/identical-files.json +++ b/config/identical-files.json @@ -1,66 +1,86 @@ { "DataFlow Java/C++/C#/Go/Python/Ruby/Swift": [ + "java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll", + "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll", + "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll", + "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll", + "go/ql/lib/semmle/go/dataflow/internal/DataFlow.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlow.qll", + "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlow.qll", + "swift/ql/lib/codeql/swift/dataflow/internal/DataFlow.qll" + ], + "DataFlowImpl Java/C++/C#/Go/Python/Ruby/Swift": [ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll", + "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll", + "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll", + "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll", + "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll", + "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll", + "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll" + ], + "DataFlow Java/C++/C#/Go/Python/Ruby/Swift Legacy Configuration": [ + "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll", "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll", - "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll", - "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll", - "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll", + "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll", - "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll", + "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll", - "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll", + "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll", - "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll", + "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll", - "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl1.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll", - "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll", + "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll", - "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll" + "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl1.qll" ], "DataFlow Java/C++/C#/Go/Python/Ruby/Swift Common": [ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll", "go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplCommon.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplCommon.qll", "swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImplCommon.qll" ], - "TaintTracking::Configuration Java/C++/C#/Go/Python/Ruby/Swift": [ + "TaintTracking Java/C++/C#/Go/Python/Ruby/Swift": [ + "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll", + "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll", + "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll", + "go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll", + "java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll", + "python/ql/lib/semmle/python/dataflow/new/internal/tainttracking1/TaintTracking.qll", + "ruby/ql/lib/codeql/ruby/dataflow/internal/tainttracking1/TaintTracking.qll", + "swift/ql/lib/codeql/swift/dataflow/internal/tainttracking1/TaintTracking.qll" + ], + "TaintTracking Legacy Configuration Java/C++/C#/Go/Python/Ruby/Swift": [ "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking2/TaintTrackingImpl.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking3/TaintTrackingImpl.qll", @@ -82,7 +102,6 @@ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll", "cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", - "cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll", "csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll", "python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplConsistency.qll", "ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplConsistency.qll", @@ -260,6 +279,11 @@ "cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRBlockImports.qll", "cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRBlockImports.qll" ], + "C++ IR IRConsistencyImports": [ + "cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConsistencyImports.qll", + "cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll", + "cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRConsistencyImports.qll" + ], "C++ IR IRFunctionImports": [ "cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRFunctionImports.qll", "cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRFunctionImports.qll", diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs index 846d8333030..06057b971b5 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/BuildScripts.cs @@ -1,5 +1,6 @@ using Xunit; using Semmle.Autobuild.Shared; +using Semmle.Util; using System.Collections.Generic; using System; using System.Linq; @@ -75,6 +76,15 @@ namespace Semmle.Autobuild.Cpp.Tests throw new ArgumentException("Missing RunProcess " + pattern); } + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? env, BuildOutputHandler onOutput, BuildOutputHandler onError) + { + var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout); + + stdout.ForEach(line => onOutput(line)); + + return ret; + } + public IList DirectoryDeleteIn = new List(); void IBuildActions.DirectoryDelete(string dir, bool recursive) @@ -184,6 +194,15 @@ namespace Semmle.Autobuild.Cpp.Tests if (!DownloadFiles.Contains((address, fileName))) throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}"); } + + public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new TestDiagnosticWriter(); + } + + internal class TestDiagnosticWriter : IDiagnosticsWriter + { + public IList Diagnostics { get; } = new List(); + + public void AddEntry(DiagnosticMessage message) => this.Diagnostics.Add(message); } /// @@ -243,6 +262,7 @@ namespace Semmle.Autobuild.Cpp.Tests Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = ""; Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = ""; Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}"; + Actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_DIAGNOSTIC_DIR"] = ""; Actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; Actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = "win64"; Actions.GetEnvironmentVariable["SEMMLE_DIST"] = @"C:\odasa"; diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/CppAutobuilder.cs b/cpp/autobuilder/Semmle.Autobuild.Cpp/CppAutobuilder.cs index 1503dedb376..e3853b44a0c 100644 --- a/cpp/autobuilder/Semmle.Autobuild.Cpp/CppAutobuilder.cs +++ b/cpp/autobuilder/Semmle.Autobuild.Cpp/CppAutobuilder.cs @@ -1,4 +1,5 @@ using Semmle.Autobuild.Shared; +using Semmle.Util; namespace Semmle.Autobuild.Cpp { @@ -21,7 +22,7 @@ namespace Semmle.Autobuild.Cpp public class CppAutobuilder : Autobuilder { - public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options) { } + public CppAutobuilder(IBuildActions actions, CppAutobuildOptions options) : base(actions, options, new DiagnosticClassifier()) { } public override BuildScript GetBuildScript() { diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md index 319e78ac20b..42a379734a1 100644 --- a/cpp/ql/lib/CHANGELOG.md +++ b/cpp/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.4 + +No user-facing changes. + ## 0.5.3 No user-facing changes. diff --git a/cpp/ql/lib/change-notes/2013-03-20-ssa-consistency.md b/cpp/ql/lib/change-notes/2013-03-20-ssa-consistency.md new file mode 100644 index 00000000000..151d29c6a9a --- /dev/null +++ b/cpp/ql/lib/change-notes/2013-03-20-ssa-consistency.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* The internal `SsaConsistency` module has been moved from `SSAConstruction` to `SSAConsitency`, and the deprecated `SSAConsistency` module has been removed. diff --git a/cpp/ql/lib/change-notes/2023-02-10-buffer-and-nill-termination-dataflow.md b/cpp/ql/lib/change-notes/2023-02-10-buffer-and-nill-termination-dataflow.md new file mode 100644 index 00000000000..adc00f952f9 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-02-10-buffer-and-nill-termination-dataflow.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* The `semmle.code.cpp.commons.Buffer` and `semmle.code.cpp.commons.NullTermination` libraries no longer expose `semmle.code.cpp.dataflow.DataFlow`. Please import `semmle.code.cpp.dataflow.DataFlow` directly. diff --git a/cpp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md b/cpp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md new file mode 100644 index 00000000000..89190af399f --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md @@ -0,0 +1,9 @@ +--- +category: majorAnalysis +--- +* The main data flow and taint tracking APIs have been changed. The old APIs + remain in place for now and translate to the new through a + backwards-compatible wrapper. If multiple configurations are in scope + simultaneously, then this may affect results slightly. The new API is quite + similar to the old, but makes use of a configuration module instead of a + configuration class. diff --git a/cpp/ql/lib/change-notes/2023-03-03-delete-deps.md b/cpp/ql/lib/change-notes/2023-03-03-delete-deps.md new file mode 100644 index 00000000000..03efda07926 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-03-delete-deps.md @@ -0,0 +1,12 @@ +--- +category: minorAnalysis +--- +* Deleted the deprecated `hasGeneratedCopyConstructor` and `hasGeneratedCopyAssignmentOperator` predicates from the `Folder` class. +* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class. +* Deleted the deprecated `getMustlockFunction`, `getTrylockFunction`, `getLockFunction`, and `getUnlockFunction` predicates from the `MutexType` class. +* Deleted the deprecated `getPosInBasicBlock` predicate from the `SubBasicBlock` class. +* Deleted the deprecated `getExpr` predicate from the `PointerDereferenceExpr` class. +* Deleted the deprecated `getUseInstruction` and `getDefinitionInstruction` predicates from the `Operand` class. +* Deleted the deprecated `isInParameter`, `isInParameterPointer`, and `isInQualifier` predicates from the `FunctionInput` class. +* Deleted the deprecated `isOutParameterPointer`, `isOutQualifier`, `isOutReturnValue`, and `isOutReturnPointer` predicate from the `FunctionOutput` class. +* Deleted the deprecated 3-argument `isGuardPhi` predicate from the `RangeSsaDefinition` class. diff --git a/cpp/ql/lib/change-notes/2023-03-08-deprecated-dataflow-configurations.md b/cpp/ql/lib/change-notes/2023-03-08-deprecated-dataflow-configurations.md new file mode 100644 index 00000000000..124dc73213a --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-08-deprecated-dataflow-configurations.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `WriteConfig` taint tracking configuration has been deprecated. Please use `WriteFlow`. diff --git a/cpp/ql/lib/change-notes/2023-03-13-mergepathgraph.md b/cpp/ql/lib/change-notes/2023-03-13-mergepathgraph.md new file mode 100644 index 00000000000..63bfade2f10 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-13-mergepathgraph.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query. diff --git a/cpp/ql/lib/change-notes/2023-03-16-use-use-flow.md b/cpp/ql/lib/change-notes/2023-03-16-use-use-flow.md new file mode 100644 index 00000000000..a643fd50b7d --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-16-use-use-flow.md @@ -0,0 +1,11 @@ +--- +category: majorAnalysis +--- +* A new C/C++ dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) has been added. + The new library behaves much more like the dataflow library of other CodeQL supported + languages by following use-use dataflow paths instead of def-use dataflow paths. + The new library also better supports dataflow through indirections, and new predicates + such as `Node::asIndirectExpr` have been added to facilitate working with indirections. + + The `semmle.code.cpp.ir.dataflow.DataFlow` library is now identical to the new + `semmle.code.cpp.dataflow.new.DataFlow` library. diff --git a/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md b/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md new file mode 100644 index 00000000000..b4389ba5b59 --- /dev/null +++ b/cpp/ql/lib/change-notes/2023-03-20-boost-deprecated-dataflow-configurations.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `SslContextCallAbstractConfig`, `SslContextCallConfig`, `SslContextCallBannedProtocolConfig`, `SslContextCallTls12ProtocolConfig`, `SslContextCallTls13ProtocolConfig`, `SslContextCallTlsProtocolConfig`, `SslContextFlowsToSetOptionConfig`, `SslOptionConfig` dataflow configurations from `BoostorgAsio` have been deprecated. Please use `SslContextCallConfigSig`, `SslContextCallMake`, `SslContextCallFlow`, `SslContextCallBannedProtocolFlow`, `SslContextCallTls12ProtocolFlow`, `SslContextCallTls13ProtocolFlow`, `SslContextCallTlsProtocolFlow`, `SslContextFlowsToSetOptionFlow`. diff --git a/cpp/ql/lib/change-notes/released/0.5.4.md b/cpp/ql/lib/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..1686ab4354d --- /dev/null +++ b/cpp/ql/lib/change-notes/released/0.5.4.md @@ -0,0 +1,3 @@ +## 0.5.4 + +No user-facing changes. diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/cpp/ql/lib/codeql-pack.release.yml +++ b/cpp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll index 6b74d61feea..e6e9eeeca58 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/dataflow/ProductFlow.qll @@ -1,5 +1,5 @@ -import experimental.semmle.code.cpp.ir.dataflow.DataFlow -import experimental.semmle.code.cpp.ir.dataflow.DataFlow2 +import semmle.code.cpp.ir.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow2 module ProductFlow { abstract class Configuration extends string { diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/ResolveCall.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/ResolveCall.qll deleted file mode 100644 index bcf2fa8c7db..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/ResolveCall.qll +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Provides a predicate for non-contextual virtual dispatch and function - * pointer resolution. - */ - -import cpp -private import semmle.code.cpp.ir.ValueNumbering -private import internal.DataFlowDispatch -private import semmle.code.cpp.ir.IR - -/** - * Resolve potential target function(s) for `call`. - * - * If `call` is a call through a function pointer (`ExprCall`) or its target is - * a virtual member function, simple data flow analysis is performed in order - * to identify the possible target(s). - */ -Function resolveCall(Call call) { - exists(CallInstruction callInstruction | - callInstruction.getAst() = call and - result = viableCallable(callInstruction) - ) -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll deleted file mode 100644 index f92612e77af..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ /dev/null @@ -1,273 +0,0 @@ -private import cpp -private import semmle.code.cpp.ir.IR -private import experimental.semmle.code.cpp.ir.dataflow.DataFlow -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import DataFlowImplCommon as DataFlowImplCommon - -/** - * Gets a function that might be called by `call`. - */ -cached -Function viableCallable(CallInstruction call) { - DataFlowImplCommon::forceCachingInSameStage() and - result = call.getStaticCallTarget() - or - // If the target of the call does not have a body in the snapshot, it might - // be because the target is just a header declaration, and the real target - // will be determined at run time when the caller and callee are linked - // together by the operating system's dynamic linker. In case a _unique_ - // function with the right signature is present in the database, we return - // that as a potential callee. - exists(string qualifiedName, int nparams | - callSignatureWithoutBody(qualifiedName, nparams, call) and - functionSignatureWithBody(qualifiedName, nparams, result) and - strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 - ) - or - // Virtual dispatch - result = call.(VirtualDispatch::DataSensitiveCall).resolve() -} - -/** - * Provides virtual dispatch support compatible with the original - * implementation of `semmle.code.cpp.security.TaintTracking`. - */ -private module VirtualDispatch { - /** A call that may dispatch differently depending on the qualifier value. */ - abstract class DataSensitiveCall extends DataFlowCall { - /** - * Gets the node whose value determines the target of this call. This node - * could be the qualifier of a virtual dispatch or the function-pointer - * expression in a call to a function pointer. What they have in common is - * that we need to find out which data flows there, and then it's up to the - * `resolve` predicate to stitch that information together and resolve the - * call. - */ - abstract DataFlow::Node getDispatchValue(); - - /** Gets a candidate target for this call. */ - abstract Function resolve(); - - /** - * Whether `src` can flow to this call. - * - * Searches backwards from `getDispatchValue()` to `src`. The `allowFromArg` - * parameter is true when the search is allowed to continue backwards into - * a parameter; non-recursive callers should pass `_` for `allowFromArg`. - */ - predicate flowsFrom(DataFlow::Node src, boolean allowFromArg) { - src = this.getDispatchValue() and allowFromArg = true - or - exists(DataFlow::Node other, boolean allowOtherFromArg | - this.flowsFrom(other, allowOtherFromArg) - | - // Call argument - exists(DataFlowCall call, Position i | - other - .(DataFlow::ParameterNode) - .isParameterOf(pragma[only_bind_into](call).getStaticCallTarget(), i) and - src.(ArgumentNode).argumentOf(call, pragma[only_bind_into](pragma[only_bind_out](i))) - ) and - allowOtherFromArg = true and - allowFromArg = true - or - // Call return - exists(DataFlowCall call, ReturnKind returnKind | - other = getAnOutNode(call, returnKind) and - returnNodeWithKindAndEnclosingCallable(src, returnKind, call.getStaticCallTarget()) - ) and - allowFromArg = false - or - // Local flow - DataFlow::localFlowStep(src, other) and - allowFromArg = allowOtherFromArg - or - // Flow from global variable to load. - exists(LoadInstruction load, GlobalOrNamespaceVariable var | - var = src.asVariable() and - other.asInstruction() = load and - addressOfGlobal(load.getSourceAddress(), var) and - // The `allowFromArg` concept doesn't play a role when `src` is a - // global variable, so we just set it to a single arbitrary value for - // performance. - allowFromArg = true - ) - or - // Flow from store to global variable. - exists(StoreInstruction store, GlobalOrNamespaceVariable var | - var = other.asVariable() and - store = src.asInstruction() and - storeIntoGlobal(store, var) and - // Setting `allowFromArg` to `true` like in the base case means we - // treat a store to a global variable like the dispatch itself: flow - // may come from anywhere. - allowFromArg = true - ) - ) - } - } - - pragma[noinline] - private predicate storeIntoGlobal(StoreInstruction store, GlobalOrNamespaceVariable var) { - addressOfGlobal(store.getDestinationAddress(), var) - } - - /** Holds if `addressInstr` is an instruction that produces the address of `var`. */ - private predicate addressOfGlobal(Instruction addressInstr, GlobalOrNamespaceVariable var) { - // Access directly to the global variable - addressInstr.(VariableAddressInstruction).getAstVariable() = var - or - // Access to a field on a global union - exists(FieldAddressInstruction fa | - fa = addressInstr and - fa.getObjectAddress().(VariableAddressInstruction).getAstVariable() = var and - fa.getField().getDeclaringType() instanceof Union - ) - } - - /** - * A ReturnNode with its ReturnKind and its enclosing callable. - * - * Used to fix a join ordering issue in flowsFrom. - */ - pragma[noinline] - private predicate returnNodeWithKindAndEnclosingCallable( - ReturnNode node, ReturnKind kind, DataFlowCallable callable - ) { - node.getKind() = kind and - node.getEnclosingCallable() = callable - } - - /** Call through a function pointer. */ - private class DataSensitiveExprCall extends DataSensitiveCall { - DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) } - - override DataFlow::Node getDispatchValue() { result.asInstruction() = this.getCallTarget() } - - override Function resolve() { - exists(FunctionInstruction fi | - this.flowsFrom(DataFlow::instructionNode(fi), _) and - result = fi.getFunctionSymbol() - ) and - ( - this.getNumberOfArguments() <= result.getEffectiveNumberOfParameters() and - this.getNumberOfArguments() >= result.getEffectiveNumberOfParameters() - or - result.isVarargs() - ) - } - } - - /** Call to a virtual function. */ - private class DataSensitiveOverriddenFunctionCall extends DataSensitiveCall { - DataSensitiveOverriddenFunctionCall() { - exists(this.getStaticCallTarget().(VirtualFunction).getAnOverridingFunction()) - } - - override DataFlow::Node getDispatchValue() { result.asInstruction() = this.getThisArgument() } - - override MemberFunction resolve() { - exists(Class overridingClass | - this.overrideMayAffectCall(overridingClass, result) and - this.hasFlowFromCastFrom(overridingClass) - ) - } - - /** - * Holds if `this` is a virtual function call whose static target is - * overridden by `overridingFunction` in `overridingClass`. - */ - pragma[noinline] - private predicate overrideMayAffectCall(Class overridingClass, MemberFunction overridingFunction) { - overridingFunction.getAnOverriddenFunction+() = this.getStaticCallTarget().(VirtualFunction) and - overridingFunction.getDeclaringType() = overridingClass - } - - /** - * Holds if the qualifier of `this` has flow from an upcast from - * `derivedClass`. - */ - pragma[noinline] - private predicate hasFlowFromCastFrom(Class derivedClass) { - exists(ConvertToBaseInstruction toBase | - this.flowsFrom(DataFlow::instructionNode(toBase), _) and - derivedClass = toBase.getDerivedClass() - ) - } - } -} - -/** - * Holds if `f` is a function with a body that has name `qualifiedName` and - * `nparams` parameter count. See `functionSignature`. - */ -private predicate functionSignatureWithBody(string qualifiedName, int nparams, Function f) { - functionSignature(f, qualifiedName, nparams) and - exists(f.getBlock()) -} - -/** - * Holds if the target of `call` is a function _with no definition_ that has - * name `qualifiedName` and `nparams` parameter count. See `functionSignature`. - */ -pragma[noinline] -private predicate callSignatureWithoutBody(string qualifiedName, int nparams, CallInstruction call) { - exists(Function target | - target = call.getStaticCallTarget() and - not exists(target.getBlock()) and - functionSignature(target, qualifiedName, nparams) - ) -} - -/** - * Holds if `f` has name `qualifiedName` and `nparams` parameter count. This is - * an approximation of its signature for the purpose of matching functions that - * might be the same across link targets. - */ -private predicate functionSignature(Function f, string qualifiedName, int nparams) { - qualifiedName = f.getQualifiedName() and - nparams = f.getNumberOfParameters() and - not f.isStatic() -} - -/** - * Holds if the set of viable implementations that can be called by `call` - * might be improved by knowing the call context. - */ -predicate mayBenefitFromCallContext(CallInstruction call, Function f) { - mayBenefitFromCallContext(call, f, _) -} - -/** - * Holds if `call` is a call through a function pointer, and the pointer - * value is given as the `arg`'th argument to `f`. - */ -private predicate mayBenefitFromCallContext( - VirtualDispatch::DataSensitiveCall call, Function f, int arg -) { - f = pragma[only_bind_out](call).getEnclosingCallable() and - exists(InitializeParameterInstruction init | - not exists(call.getStaticCallTarget()) and - init.getEnclosingFunction() = f and - call.flowsFrom(DataFlow::instructionNode(init), _) and - init.getParameter().getIndex() = arg - ) -} - -/** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference. - */ -Function viableImplInCallContext(CallInstruction call, CallInstruction ctx) { - result = viableCallable(call) and - exists(int i, Function f | - mayBenefitFromCallContext(pragma[only_bind_into](call), f, i) and - f = ctx.getStaticCallTarget() and - result = ctx.getArgument(i).getUnconvertedResultExpression().(FunctionAccess).getTarget() - ) -} - -/** Holds if arguments at position `apos` match parameters at position `ppos`. */ -pragma[inline] -predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll deleted file mode 100644 index 5d3becc8078..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ /dev/null @@ -1,1526 +0,0 @@ -private import DataFlowImplSpecific::Private -private import DataFlowImplSpecific::Public -import Cached - -module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; - - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } - } - - private newtype TFlowFeature = - TFeatureHasSourceCallContext() or - TFeatureHasSinkCallContext() or - TFeatureEqualSourceSinkCallContext() - - /** A flow configuration feature for use in `Configuration::getAFeature()`. */ - class FlowFeature extends TFlowFeature { - string toString() { none() } - } - - /** - * A flow configuration feature that implies that sources have some existing - * call context. - */ - class FeatureHasSourceCallContext extends FlowFeature, TFeatureHasSourceCallContext { - override string toString() { result = "FeatureHasSourceCallContext" } - } - - /** - * A flow configuration feature that implies that sinks have some existing - * call context. - */ - class FeatureHasSinkCallContext extends FlowFeature, TFeatureHasSinkCallContext { - override string toString() { result = "FeatureHasSinkCallContext" } - } - - /** - * A flow configuration feature that implies that source-sink pairs have some - * shared existing call context. - */ - class FeatureEqualSourceSinkCallContext extends FlowFeature, TFeatureEqualSourceSinkCallContext { - override string toString() { result = "FeatureEqualSourceSinkCallContext" } - } -} - -/** - * The cost limits for the `AccessPathFront` to `AccessPathApprox` expansion. - * - * `apLimit` bounds the acceptable fan-out, and `tupleLimit` bounds the - * estimated per-`AccessPathFront` tuple cost. Access paths exceeding both of - * these limits are represented with lower precision during pruning. - */ -predicate accessPathApproxCostLimits(int apLimit, int tupleLimit) { - apLimit = 10 and - tupleLimit = 10000 -} - -/** - * The cost limits for the `AccessPathApprox` to `AccessPath` expansion. - * - * `apLimit` bounds the acceptable fan-out, and `tupleLimit` bounds the - * estimated per-`AccessPathApprox` tuple cost. Access paths exceeding both of - * these limits are represented with lower precision. - */ -predicate accessPathCostLimits(int apLimit, int tupleLimit) { - apLimit = 5 and - tupleLimit = 1000 -} - -/** - * Holds if `arg` is an argument of `call` with an argument position that matches - * parameter position `ppos`. - */ -pragma[noinline] -predicate argumentPositionMatch(DataFlowCall call, ArgNode arg, ParameterPosition ppos) { - exists(ArgumentPosition apos | - arg.argumentOf(call, apos) and - parameterMatch(ppos, apos) - ) -} - -/** - * Provides a simple data-flow analysis for resolving lambda calls. The analysis - * currently excludes read-steps, store-steps, and flow-through. - * - * The analysis uses non-linear recursion: When computing a flow path in or out - * of a call, we use the results of the analysis recursively to resolve lambda - * calls. For this reason, we cannot reuse the code from `DataFlowImpl.qll` directly. - */ -private module LambdaFlow { - pragma[noinline] - private predicate viableParamNonLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) { - p.isParameterOf(viableCallable(call), ppos) - } - - pragma[noinline] - private predicate viableParamLambda(DataFlowCall call, ParameterPosition ppos, ParamNode p) { - p.isParameterOf(viableCallableLambda(call, _), ppos) - } - - private predicate viableParamArgNonLambda(DataFlowCall call, ParamNode p, ArgNode arg) { - exists(ParameterPosition ppos | - viableParamNonLambda(call, ppos, p) and - argumentPositionMatch(call, arg, ppos) - ) - } - - private predicate viableParamArgLambda(DataFlowCall call, ParamNode p, ArgNode arg) { - exists(ParameterPosition ppos | - viableParamLambda(call, ppos, p) and - argumentPositionMatch(call, arg, ppos) - ) - } - - private newtype TReturnPositionSimple = - TReturnPositionSimple0(DataFlowCallable c, ReturnKind kind) { - exists(ReturnNode ret | - c = getNodeEnclosingCallable(ret) and - kind = ret.getKind() - ) - } - - pragma[noinline] - private TReturnPositionSimple getReturnPositionSimple(ReturnNode ret, ReturnKind kind) { - result = TReturnPositionSimple0(getNodeEnclosingCallable(ret), kind) - } - - pragma[nomagic] - private TReturnPositionSimple viableReturnPosNonLambda(DataFlowCall call, ReturnKind kind) { - result = TReturnPositionSimple0(viableCallable(call), kind) - } - - pragma[nomagic] - private TReturnPositionSimple viableReturnPosLambda( - DataFlowCall call, DataFlowCallOption lastCall, ReturnKind kind - ) { - result = TReturnPositionSimple0(viableCallableLambda(call, lastCall), kind) - } - - private predicate viableReturnPosOutNonLambda( - DataFlowCall call, TReturnPositionSimple pos, OutNode out - ) { - exists(ReturnKind kind | - pos = viableReturnPosNonLambda(call, kind) and - out = getAnOutNode(call, kind) - ) - } - - private predicate viableReturnPosOutLambda( - DataFlowCall call, DataFlowCallOption lastCall, TReturnPositionSimple pos, OutNode out - ) { - exists(ReturnKind kind | - pos = viableReturnPosLambda(call, lastCall, kind) and - out = getAnOutNode(call, kind) - ) - } - - /** - * Holds if data can flow (inter-procedurally) from `node` (of type `t`) to - * the lambda call `lambdaCall`. - * - * The parameter `toReturn` indicates whether the path from `node` to - * `lambdaCall` goes through a return, and `toJump` whether the path goes - * through a jump step. - * - * The call context `lastCall` records the last call on the path from `node` - * to `lambdaCall`, if any. That is, `lastCall` is able to target the enclosing - * callable of `lambdaCall`. - */ - pragma[nomagic] - predicate revLambdaFlow( - DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, - boolean toJump, DataFlowCallOption lastCall - ) { - revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and - if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode - then compatibleTypes(t, getNodeDataFlowType(node)) - else any() - } - - pragma[nomagic] - predicate revLambdaFlow0( - DataFlowCall lambdaCall, LambdaCallKind kind, Node node, DataFlowType t, boolean toReturn, - boolean toJump, DataFlowCallOption lastCall - ) { - lambdaCall(lambdaCall, kind, node) and - t = getNodeDataFlowType(node) and - toReturn = false and - toJump = false and - lastCall = TDataFlowCallNone() - or - // local flow - exists(Node mid, DataFlowType t0 | - revLambdaFlow(lambdaCall, kind, mid, t0, toReturn, toJump, lastCall) - | - simpleLocalFlowStep(node, mid) and - t = t0 - or - exists(boolean preservesValue | - additionalLambdaFlowStep(node, mid, preservesValue) and - getNodeEnclosingCallable(node) = getNodeEnclosingCallable(mid) - | - preservesValue = false and - t = getNodeDataFlowType(node) - or - preservesValue = true and - t = t0 - ) - ) - or - // jump step - exists(Node mid, DataFlowType t0 | - revLambdaFlow(lambdaCall, kind, mid, t0, _, _, lastCall) and - toReturn = false and - toJump = true - | - jumpStepCached(node, mid) and - t = t0 - or - exists(boolean preservesValue | - additionalLambdaFlowStep(node, mid, preservesValue) and - getNodeEnclosingCallable(node) != getNodeEnclosingCallable(mid) - | - preservesValue = false and - t = getNodeDataFlowType(node) - or - preservesValue = true and - t = t0 - ) - ) - or - // flow into a callable - exists(ParamNode p, DataFlowCallOption lastCall0, DataFlowCall call | - revLambdaFlowIn(lambdaCall, kind, p, t, toJump, lastCall0) and - ( - if lastCall0 = TDataFlowCallNone() and toJump = false - then lastCall = TDataFlowCallSome(call) - else lastCall = lastCall0 - ) and - toReturn = false - | - viableParamArgNonLambda(call, p, node) - or - viableParamArgLambda(call, p, node) // non-linear recursion - ) - or - // flow out of a callable - exists(TReturnPositionSimple pos | - revLambdaFlowOut(lambdaCall, kind, pos, t, toJump, lastCall) and - getReturnPositionSimple(node, node.(ReturnNode).getKind()) = pos and - toReturn = true - ) - } - - pragma[nomagic] - predicate revLambdaFlowOutLambdaCall( - DataFlowCall lambdaCall, LambdaCallKind kind, OutNode out, DataFlowType t, boolean toJump, - DataFlowCall call, DataFlowCallOption lastCall - ) { - revLambdaFlow(lambdaCall, kind, out, t, _, toJump, lastCall) and - exists(ReturnKindExt rk | - out = rk.getAnOutNode(call) and - lambdaCall(call, _, _) - ) - } - - pragma[nomagic] - predicate revLambdaFlowOut( - DataFlowCall lambdaCall, LambdaCallKind kind, TReturnPositionSimple pos, DataFlowType t, - boolean toJump, DataFlowCallOption lastCall - ) { - exists(DataFlowCall call, OutNode out | - revLambdaFlow(lambdaCall, kind, out, t, _, toJump, lastCall) and - viableReturnPosOutNonLambda(call, pos, out) - or - // non-linear recursion - revLambdaFlowOutLambdaCall(lambdaCall, kind, out, t, toJump, call, lastCall) and - viableReturnPosOutLambda(call, _, pos, out) - ) - } - - pragma[nomagic] - predicate revLambdaFlowIn( - DataFlowCall lambdaCall, LambdaCallKind kind, ParamNode p, DataFlowType t, boolean toJump, - DataFlowCallOption lastCall - ) { - revLambdaFlow(lambdaCall, kind, p, t, false, toJump, lastCall) - } -} - -private DataFlowCallable viableCallableExt(DataFlowCall call) { - result = viableCallable(call) - or - result = viableCallableLambda(call, _) -} - -cached -private module Cached { - /** - * If needed, call this predicate from `DataFlowImplSpecific.qll` in order to - * force a stage-dependency on the `DataFlowImplCommon.qll` stage and thereby - * collapsing the two stages. - */ - cached - predicate forceCachingInSameStage() { any() } - - cached - predicate nodeEnclosingCallable(Node n, DataFlowCallable c) { c = nodeGetEnclosingCallable(n) } - - cached - predicate callEnclosingCallable(DataFlowCall call, DataFlowCallable c) { - c = call.getEnclosingCallable() - } - - cached - predicate nodeDataFlowType(Node n, DataFlowType t) { t = getNodeType(n) } - - cached - predicate jumpStepCached(Node node1, Node node2) { jumpStep(node1, node2) } - - cached - predicate clearsContentCached(Node n, ContentSet c) { clearsContent(n, c) } - - cached - predicate expectsContentCached(Node n, ContentSet c) { expectsContent(n, c) } - - cached - predicate isUnreachableInCallCached(Node n, DataFlowCall call) { isUnreachableInCall(n, call) } - - cached - predicate outNodeExt(Node n) { - n instanceof OutNode - or - n.(PostUpdateNode).getPreUpdateNode() instanceof ArgNode - } - - cached - predicate hiddenNode(Node n) { nodeIsHidden(n) } - - cached - OutNodeExt getAnOutNodeExt(DataFlowCall call, ReturnKindExt k) { - result = getAnOutNode(call, k.(ValueReturnKind).getKind()) - or - exists(ArgNode arg | - result.(PostUpdateNode).getPreUpdateNode() = arg and - arg.argumentOf(call, k.(ParamUpdateReturnKind).getAMatchingArgumentPosition()) - ) - } - - cached - predicate returnNodeExt(Node n, ReturnKindExt k) { - k = TValueReturn(n.(ReturnNode).getKind()) - or - exists(ParamNode p, ParameterPosition pos | - parameterValueFlowsToPreUpdate(p, n) and - p.isParameterOf(_, pos) and - k = TParamUpdate(pos) - ) - } - - cached - predicate castNode(Node n) { n instanceof CastNode } - - cached - predicate castingNode(Node n) { - castNode(n) or - n instanceof ParamNode or - n instanceof OutNodeExt or - // For reads, `x.f`, we want to check that the tracked type after the read (which - // is obtained by popping the head of the access path stack) is compatible with - // the type of `x.f`. - readSet(_, _, n) - } - - cached - predicate parameterNode(Node p, DataFlowCallable c, ParameterPosition pos) { - isParameterNode(p, c, pos) - } - - cached - predicate argumentNode(Node n, DataFlowCall call, ArgumentPosition pos) { - isArgumentNode(n, call, pos) - } - - /** - * Gets a viable target for the lambda call `call`. - * - * `lastCall` records the call required to reach `call` in order for the result - * to be a viable target, if any. - */ - cached - DataFlowCallable viableCallableLambda(DataFlowCall call, DataFlowCallOption lastCall) { - exists(Node creation, LambdaCallKind kind | - LambdaFlow::revLambdaFlow(call, kind, creation, _, _, _, lastCall) and - lambdaCreation(creation, kind, result) - ) - } - - /** - * Holds if `p` is the parameter of a viable dispatch target of `call`, - * and `p` has position `ppos`. - */ - pragma[nomagic] - private predicate viableParam(DataFlowCall call, ParameterPosition ppos, ParamNode p) { - p.isParameterOf(viableCallableExt(call), ppos) - } - - /** - * Holds if `arg` is a possible argument to `p` in `call`, taking virtual - * dispatch into account. - */ - cached - predicate viableParamArg(DataFlowCall call, ParamNode p, ArgNode arg) { - exists(ParameterPosition ppos | - viableParam(call, ppos, p) and - argumentPositionMatch(call, arg, ppos) and - compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(p)) - ) - } - - pragma[nomagic] - private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { - viableCallableExt(call) = result.getCallable() and - kind = result.getKind() - } - - /** - * Holds if a value at return position `pos` can be returned to `out` via `call`, - * taking virtual dispatch into account. - */ - cached - predicate viableReturnPosOut(DataFlowCall call, ReturnPosition pos, Node out) { - exists(ReturnKindExt kind | - pos = viableReturnPos(call, kind) and - out = kind.getAnOutNode(call) - ) - } - - /** Provides predicates for calculating flow-through summaries. */ - private module FlowThrough { - /** - * The first flow-through approximation: - * - * - Input access paths are abstracted with a Boolean parameter - * that indicates (non-)emptiness. - */ - private module Cand { - /** - * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps. - * - * `read` indicates whether it is contents of `p` that can flow to `node`. - */ - pragma[nomagic] - private predicate parameterValueFlowCand(ParamNode p, Node node, boolean read) { - p = node and - read = false - or - // local flow - exists(Node mid | - parameterValueFlowCand(p, mid, read) and - simpleLocalFlowStep(mid, node) - ) - or - // read - exists(Node mid | - parameterValueFlowCand(p, mid, false) and - readSet(mid, _, node) and - read = true - ) - or - // flow through: no prior read - exists(ArgNode arg | - parameterValueFlowArgCand(p, arg, false) and - argumentValueFlowsThroughCand(arg, node, read) - ) - or - // flow through: no read inside method - exists(ArgNode arg | - parameterValueFlowArgCand(p, arg, read) and - argumentValueFlowsThroughCand(arg, node, false) - ) - } - - pragma[nomagic] - private predicate parameterValueFlowArgCand(ParamNode p, ArgNode arg, boolean read) { - parameterValueFlowCand(p, arg, read) - } - - pragma[nomagic] - predicate parameterValueFlowsToPreUpdateCand(ParamNode p, PostUpdateNode n) { - parameterValueFlowCand(p, n.getPreUpdateNode(), false) - } - - /** - * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps, not taking call contexts - * into account. - * - * `read` indicates whether it is contents of `p` that can flow to the return - * node. - */ - predicate parameterValueFlowReturnCand(ParamNode p, ReturnKind kind, boolean read) { - exists(ReturnNode ret | - parameterValueFlowCand(p, ret, read) and - kind = ret.getKind() - ) - } - - pragma[nomagic] - private predicate argumentValueFlowsThroughCand0( - DataFlowCall call, ArgNode arg, ReturnKind kind, boolean read - ) { - exists(ParamNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturnCand(param, kind, read) - ) - } - - /** - * Holds if `arg` flows to `out` through a call using only value-preserving steps, - * not taking call contexts into account. - * - * `read` indicates whether it is contents of `arg` that can flow to `out`. - */ - predicate argumentValueFlowsThroughCand(ArgNode arg, Node out, boolean read) { - exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThroughCand0(call, arg, kind, read) and - out = getAnOutNode(call, kind) - ) - } - - predicate cand(ParamNode p, Node n) { - parameterValueFlowCand(p, n, _) and - ( - parameterValueFlowReturnCand(p, _, _) - or - parameterValueFlowsToPreUpdateCand(p, _) - ) - } - } - - /** - * The final flow-through calculation: - * - * - Calculated flow is either value-preserving (`read = TReadStepTypesNone()`) - * or summarized as a single read step with before and after types recorded - * in the `ReadStepTypesOption` parameter. - * - Types are checked using the `compatibleTypes()` relation. - */ - private module Final { - /** - * Holds if `p` can flow to `node` in the same callable using only - * value-preserving steps and possibly a single read step, not taking - * call contexts into account. - * - * If a read step was taken, then `read` captures the `Content`, the - * container type, and the content type. - */ - predicate parameterValueFlow(ParamNode p, Node node, ReadStepTypesOption read) { - parameterValueFlow0(p, node, read) and - if node instanceof CastingNode - then - // normal flow through - read = TReadStepTypesNone() and - compatibleTypes(getNodeDataFlowType(p), getNodeDataFlowType(node)) - or - // getter - compatibleTypes(read.getContentType(), getNodeDataFlowType(node)) - else any() - } - - pragma[nomagic] - private predicate parameterValueFlow0(ParamNode p, Node node, ReadStepTypesOption read) { - p = node and - Cand::cand(p, _) and - read = TReadStepTypesNone() - or - // local flow - exists(Node mid | - parameterValueFlow(p, mid, read) and - simpleLocalFlowStep(mid, node) - ) - or - // read - exists(Node mid | - parameterValueFlow(p, mid, TReadStepTypesNone()) and - readStepWithTypes(mid, read.getContainerType(), read.getContent(), node, - read.getContentType()) and - Cand::parameterValueFlowReturnCand(p, _, true) and - compatibleTypes(getNodeDataFlowType(p), read.getContainerType()) - ) - or - parameterValueFlow0_0(TReadStepTypesNone(), p, node, read) - } - - pragma[nomagic] - private predicate parameterValueFlow0_0( - ReadStepTypesOption mustBeNone, ParamNode p, Node node, ReadStepTypesOption read - ) { - // flow through: no prior read - exists(ArgNode arg | - parameterValueFlowArg(p, arg, mustBeNone) and - argumentValueFlowsThrough(arg, read, node) - ) - or - // flow through: no read inside method - exists(ArgNode arg | - parameterValueFlowArg(p, arg, read) and - argumentValueFlowsThrough(arg, mustBeNone, node) - ) - } - - pragma[nomagic] - private predicate parameterValueFlowArg(ParamNode p, ArgNode arg, ReadStepTypesOption read) { - parameterValueFlow(p, arg, read) and - Cand::argumentValueFlowsThroughCand(arg, _, _) - } - - pragma[nomagic] - private predicate argumentValueFlowsThrough0( - DataFlowCall call, ArgNode arg, ReturnKind kind, ReadStepTypesOption read - ) { - exists(ParamNode param | viableParamArg(call, param, arg) | - parameterValueFlowReturn(param, kind, read) - ) - } - - /** - * Holds if `arg` flows to `out` through a call using only - * value-preserving steps and possibly a single read step, not taking - * call contexts into account. - * - * If a read step was taken, then `read` captures the `Content`, the - * container type, and the content type. - */ - pragma[nomagic] - predicate argumentValueFlowsThrough(ArgNode arg, ReadStepTypesOption read, Node out) { - exists(DataFlowCall call, ReturnKind kind | - argumentValueFlowsThrough0(call, arg, kind, read) and - out = getAnOutNode(call, kind) - | - // normal flow through - read = TReadStepTypesNone() and - compatibleTypes(getNodeDataFlowType(arg), getNodeDataFlowType(out)) - or - // getter - compatibleTypes(getNodeDataFlowType(arg), read.getContainerType()) and - compatibleTypes(read.getContentType(), getNodeDataFlowType(out)) - ) - } - - /** - * Holds if `arg` flows to `out` through a call using only - * value-preserving steps and a single read step, not taking call - * contexts into account, thus representing a getter-step. - * - * This predicate is exposed for testing only. - */ - predicate getterStep(ArgNode arg, ContentSet c, Node out) { - argumentValueFlowsThrough(arg, TReadStepTypesSome(_, c, _), out) - } - - /** - * Holds if `p` can flow to a return node of kind `kind` in the same - * callable using only value-preserving steps and possibly a single read - * step. - * - * If a read step was taken, then `read` captures the `Content`, the - * container type, and the content type. - */ - private predicate parameterValueFlowReturn( - ParamNode p, ReturnKind kind, ReadStepTypesOption read - ) { - exists(ReturnNode ret | - parameterValueFlow(p, ret, read) and - kind = ret.getKind() - ) - } - } - - import Final - } - - import FlowThrough - - cached - private module DispatchWithCallContext { - /** - * Holds if the set of viable implementations that can be called by `call` - * might be improved by knowing the call context. - */ - pragma[nomagic] - private predicate mayBenefitFromCallContextExt(DataFlowCall call, DataFlowCallable callable) { - mayBenefitFromCallContext(call, callable) - or - callEnclosingCallable(call, callable) and - exists(viableCallableLambda(call, TDataFlowCallSome(_))) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference. - */ - cached - DataFlowCallable viableImplInCallContextExt(DataFlowCall call, DataFlowCall ctx) { - result = viableImplInCallContext(call, ctx) and - result = viableCallable(call) - or - result = viableCallableLambda(call, TDataFlowCallSome(ctx)) - or - exists(DataFlowCallable enclosing | - mayBenefitFromCallContextExt(call, enclosing) and - enclosing = viableCallableExt(ctx) and - result = viableCallableLambda(call, TDataFlowCallNone()) - ) - } - - /** - * Holds if the call context `ctx` reduces the set of viable run-time - * dispatch targets of call `call` in `c`. - */ - cached - predicate reducedViableImplInCallContext(DataFlowCall call, DataFlowCallable c, DataFlowCall ctx) { - exists(int tgts, int ctxtgts | - mayBenefitFromCallContextExt(call, c) and - c = viableCallableExt(ctx) and - ctxtgts = count(viableImplInCallContextExt(call, ctx)) and - tgts = strictcount(viableCallableExt(call)) and - ctxtgts < tgts - ) - } - - /** - * Gets a viable run-time dispatch target for the call `call` in the - * context `ctx`. This is restricted to those calls for which a context - * makes a difference. - */ - cached - DataFlowCallable prunedViableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { - result = viableImplInCallContextExt(call, ctx) and - reducedViableImplInCallContext(call, _, ctx) - } - - /** - * Holds if flow returning from callable `c` to call `call` might return - * further and if this path restricts the set of call sites that can be - * returned to. - */ - cached - predicate reducedViableImplInReturn(DataFlowCallable c, DataFlowCall call) { - exists(int tgts, int ctxtgts | - mayBenefitFromCallContextExt(call, _) and - c = viableCallableExt(call) and - ctxtgts = count(DataFlowCall ctx | c = viableImplInCallContextExt(call, ctx)) and - tgts = strictcount(DataFlowCall ctx | callEnclosingCallable(call, viableCallableExt(ctx))) and - ctxtgts < tgts - ) - } - - /** - * Gets a viable run-time dispatch target for the call `call` in the - * context `ctx`. This is restricted to those calls and results for which - * the return flow from the result to `call` restricts the possible context - * `ctx`. - */ - cached - DataFlowCallable prunedViableImplInCallContextReverse(DataFlowCall call, DataFlowCall ctx) { - result = viableImplInCallContextExt(call, ctx) and - reducedViableImplInReturn(result, call) - } - } - - import DispatchWithCallContext - - /** - * Holds if `p` can flow to the pre-update node associated with post-update - * node `n`, in the same callable, using only value-preserving steps. - */ - private predicate parameterValueFlowsToPreUpdate(ParamNode p, PostUpdateNode n) { - parameterValueFlow(p, n.getPreUpdateNode(), TReadStepTypesNone()) - } - - cached - predicate readSet(Node node1, ContentSet c, Node node2) { readStep(node1, c, node2) } - - cached - predicate storeSet( - Node node1, ContentSet c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - storeStep(node1, c, node2) and - contentType = getNodeDataFlowType(node1) and - containerType = getNodeDataFlowType(node2) - or - exists(Node n1, Node n2 | - n1 = node1.(PostUpdateNode).getPreUpdateNode() and - n2 = node2.(PostUpdateNode).getPreUpdateNode() - | - argumentValueFlowsThrough(n2, TReadStepTypesSome(containerType, c, contentType), n1) - or - readSet(n2, c, n1) and - contentType = getNodeDataFlowType(n1) and - containerType = getNodeDataFlowType(n2) - ) - } - - private predicate store( - Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType - ) { - exists(ContentSet cs | - c = cs.getAStoreContent() and storeSet(node1, cs, node2, contentType, containerType) - ) - } - - /** - * Holds if data can flow from `node1` to `node2` via a direct assignment to - * `f`. - * - * This includes reverse steps through reads when the result of the read has - * been stored into, in order to handle cases like `x.f1.f2 = y`. - */ - cached - predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) { - 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. - */ - private 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.(ArgNode).argumentOf(c, _) and - simpleLocalFlowStep(toPre.(ArgNode), fromPre) - ) - or - argumentValueFlowsThrough(toPre, TReadStepTypesNone(), fromPre) - ) - } - - cached - predicate simpleLocalFlowStepExt(Node node1, Node node2) { - simpleLocalFlowStep(node1, node2) or - reverseStepThroughInputOutputAlias(node1, node2) - } - - /** - * Holds if the call context `call` improves virtual dispatch in `callable`. - */ - cached - predicate recordDataFlowCallSiteDispatch(DataFlowCall call, DataFlowCallable callable) { - reducedViableImplInCallContext(_, callable, call) - } - - /** - * Holds if the call context `call` allows us to prune unreachable nodes in `callable`. - */ - cached - predicate recordDataFlowCallSiteUnreachable(DataFlowCall call, DataFlowCallable callable) { - exists(Node n | getNodeEnclosingCallable(n) = callable | isUnreachableInCallCached(n, call)) - } - - cached - predicate allowParameterReturnInSelfCached(ParamNode p) { allowParameterReturnInSelf(p) } - - cached - newtype TCallContext = - TAnyCallContext() or - TSpecificCall(DataFlowCall call) { recordDataFlowCallSite(call, _) } or - TSomeCall() or - TReturn(DataFlowCallable c, DataFlowCall call) { reducedViableImplInReturn(c, call) } - - cached - newtype TReturnPosition = - TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) { - exists(ReturnNodeExt ret | - c = returnNodeGetEnclosingCallable(ret) and - kind = ret.getKind() - ) - } - - cached - newtype TLocalFlowCallContext = - TAnyLocalCall() or - TSpecificLocalCall(DataFlowCall call) { isUnreachableInCallCached(_, call) } - - cached - newtype TReturnKindExt = - TValueReturn(ReturnKind kind) or - TParamUpdate(ParameterPosition pos) { exists(ParamNode p | p.isParameterOf(_, pos)) } - - cached - newtype TBooleanOption = - TBooleanNone() or - TBooleanSome(boolean b) { b = true or b = false } - - cached - newtype TDataFlowCallOption = - TDataFlowCallNone() or - TDataFlowCallSome(DataFlowCall call) - - cached - newtype TParamNodeOption = - TParamNodeNone() or - TParamNodeSome(ParamNode p) - - cached - newtype TReturnCtx = - TReturnCtxNone() or - TReturnCtxNoFlowThrough() or - TReturnCtxMaybeFlowThrough(ReturnPosition pos) - - cached - newtype TTypedContentApprox = - MkTypedContentApprox(ContentApprox c, DataFlowType t) { - exists(Content cont | - c = getContentApprox(cont) and - store(_, cont, _, _, t) - ) - } - - cached - newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) } - - cached - TypedContent getATypedContent(TypedContentApprox c) { - exists(ContentApprox cls, DataFlowType t, Content cont | - c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and - result = MkTypedContent(cont, pragma[only_bind_into](t)) and - cls = getContentApprox(cont) - ) - } - - cached - newtype TAccessPathFront = - TFrontNil(DataFlowType t) or - TFrontHead(TypedContent tc) - - cached - newtype TApproxAccessPathFront = - TApproxFrontNil(DataFlowType t) or - TApproxFrontHead(TypedContentApprox tc) - - cached - newtype TAccessPathFrontOption = - TAccessPathFrontNone() or - TAccessPathFrontSome(AccessPathFront apf) - - cached - newtype TApproxAccessPathFrontOption = - TApproxAccessPathFrontNone() or - TApproxAccessPathFrontSome(ApproxAccessPathFront apf) -} - -/** - * Holds if the call context `call` either improves virtual dispatch in - * `callable` or if it allows us to prune unreachable nodes in `callable`. - */ -predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) { - recordDataFlowCallSiteDispatch(call, callable) or - recordDataFlowCallSiteUnreachable(call, callable) -} - -/** - * A `Node` at which a cast can occur such that the type should be checked. - */ -class CastingNode extends Node { - CastingNode() { castingNode(this) } -} - -private predicate readStepWithTypes( - Node n1, DataFlowType container, ContentSet c, Node n2, DataFlowType content -) { - readSet(n1, c, n2) and - container = getNodeDataFlowType(n1) and - content = getNodeDataFlowType(n2) -} - -private newtype TReadStepTypesOption = - TReadStepTypesNone() or - TReadStepTypesSome(DataFlowType container, ContentSet c, DataFlowType content) { - readStepWithTypes(_, container, c, _, content) - } - -private class ReadStepTypesOption extends TReadStepTypesOption { - predicate isSome() { this instanceof TReadStepTypesSome } - - DataFlowType getContainerType() { this = TReadStepTypesSome(result, _, _) } - - ContentSet getContent() { this = TReadStepTypesSome(_, result, _) } - - DataFlowType getContentType() { this = TReadStepTypesSome(_, _, result) } - - string toString() { if this.isSome() then result = "Some(..)" else result = "None()" } -} - -/** - * A call context to restrict the targets of virtual dispatch, prune local flow, - * and match the call sites of flow into a method with flow out of a method. - * - * There are four cases: - * - `TAnyCallContext()` : No restrictions on method flow. - * - `TSpecificCall(DataFlowCall call)` : Flow entered through the - * given `call`. This call improves the set of viable - * dispatch targets for at least one method call in the current callable - * or helps prune unreachable nodes in the current callable. - * - `TSomeCall()` : Flow entered through a parameter. The - * originating call does not improve the set of dispatch targets for any - * method call in the current callable and was therefore not recorded. - * - `TReturn(Callable c, DataFlowCall call)` : Flow reached `call` from `c` and - * this dispatch target of `call` implies a reduced set of dispatch origins - * to which data may flow if it should reach a `return` statement. - */ -abstract class CallContext extends TCallContext { - abstract string toString(); - - /** Holds if this call context is relevant for `callable`. */ - abstract predicate relevantFor(DataFlowCallable callable); -} - -abstract class CallContextNoCall extends CallContext { } - -class CallContextAny extends CallContextNoCall, TAnyCallContext { - override string toString() { result = "CcAny" } - - override predicate relevantFor(DataFlowCallable callable) { any() } -} - -abstract class CallContextCall extends CallContext { - /** Holds if this call context may be `call`. */ - bindingset[call] - abstract predicate matchesCall(DataFlowCall call); -} - -class CallContextSpecificCall extends CallContextCall, TSpecificCall { - override string toString() { - exists(DataFlowCall call | this = TSpecificCall(call) | result = "CcCall(" + call + ")") - } - - override predicate relevantFor(DataFlowCallable callable) { - recordDataFlowCallSite(this.getCall(), callable) - } - - override predicate matchesCall(DataFlowCall call) { call = this.getCall() } - - DataFlowCall getCall() { this = TSpecificCall(result) } -} - -class CallContextSomeCall extends CallContextCall, TSomeCall { - override string toString() { result = "CcSomeCall" } - - override predicate relevantFor(DataFlowCallable callable) { - exists(ParamNode p | getNodeEnclosingCallable(p) = callable) - } - - override predicate matchesCall(DataFlowCall call) { any() } -} - -class CallContextReturn extends CallContextNoCall, TReturn { - override string toString() { - exists(DataFlowCall call | this = TReturn(_, call) | result = "CcReturn(" + call + ")") - } - - override predicate relevantFor(DataFlowCallable callable) { - exists(DataFlowCall call | this = TReturn(_, call) and callEnclosingCallable(call, callable)) - } -} - -/** - * A call context that is relevant for pruning local flow. - */ -abstract class LocalCallContext extends TLocalFlowCallContext { - abstract string toString(); - - /** Holds if this call context is relevant for `callable`. */ - abstract predicate relevantFor(DataFlowCallable callable); -} - -class LocalCallContextAny extends LocalCallContext, TAnyLocalCall { - override string toString() { result = "LocalCcAny" } - - override predicate relevantFor(DataFlowCallable callable) { any() } -} - -class LocalCallContextSpecificCall extends LocalCallContext, TSpecificLocalCall { - LocalCallContextSpecificCall() { this = TSpecificLocalCall(call) } - - DataFlowCall call; - - DataFlowCall getCall() { result = call } - - override string toString() { result = "LocalCcCall(" + call + ")" } - - override predicate relevantFor(DataFlowCallable callable) { relevantLocalCCtx(call, callable) } -} - -private predicate relevantLocalCCtx(DataFlowCall call, DataFlowCallable callable) { - exists(Node n | getNodeEnclosingCallable(n) = callable and isUnreachableInCallCached(n, call)) -} - -/** - * Gets the local call context given the call context and the callable that - * the contexts apply to. - */ -LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable) { - ctx.relevantFor(callable) and - if relevantLocalCCtx(ctx.(CallContextSpecificCall).getCall(), callable) - then result.(LocalCallContextSpecificCall).getCall() = ctx.(CallContextSpecificCall).getCall() - else result instanceof LocalCallContextAny -} - -/** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. - */ -class ParamNode extends Node { - ParamNode() { parameterNode(this, _, _) } - - /** - * Holds if this node is the parameter of callable `c` at the specified - * position. - */ - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { parameterNode(this, c, pos) } -} - -/** A data-flow node that represents a call argument. */ -class ArgNode extends Node { - ArgNode() { argumentNode(this, _, _) } - - /** Holds if this argument occurs at the given position in the given call. */ - final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - argumentNode(this, call, pos) - } -} - -/** - * A node from which flow can return to the caller. This is either a regular - * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. - */ -class ReturnNodeExt extends Node { - ReturnNodeExt() { returnNodeExt(this, _) } - - /** Gets the kind of this returned value. */ - ReturnKindExt getKind() { returnNodeExt(this, result) } -} - -/** - * A node to which data can flow from a call. Either an ordinary out node - * or a post-update node associated with a call argument. - */ -class OutNodeExt extends Node { - OutNodeExt() { outNodeExt(this) } -} - -/** - * An extended return kind. A return kind describes how data can be returned - * from a callable. This can either be through a returned value or an updated - * parameter. - */ -abstract class ReturnKindExt extends TReturnKindExt { - /** Gets a textual representation of this return kind. */ - abstract string toString(); - - /** Gets a node corresponding to data flow out of `call`. */ - final OutNodeExt getAnOutNode(DataFlowCall call) { result = getAnOutNodeExt(call, this) } -} - -class ValueReturnKind extends ReturnKindExt, TValueReturn { - private ReturnKind kind; - - ValueReturnKind() { this = TValueReturn(kind) } - - ReturnKind getKind() { result = kind } - - override string toString() { result = kind.toString() } -} - -class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { - private ParameterPosition pos; - - ParamUpdateReturnKind() { this = TParamUpdate(pos) } - - ParameterPosition getPosition() { result = pos } - - pragma[nomagic] - ArgumentPosition getAMatchingArgumentPosition() { parameterMatch(pos, result) } - - override string toString() { result = "param update " + pos } -} - -/** A callable tagged with a relevant return kind. */ -class ReturnPosition extends TReturnPosition0 { - private DataFlowCallable c; - private ReturnKindExt kind; - - ReturnPosition() { this = TReturnPosition0(c, kind) } - - /** Gets the callable. */ - DataFlowCallable getCallable() { result = c } - - /** Gets the return kind. */ - ReturnKindExt getKind() { result = kind } - - /** Gets a textual representation of this return position. */ - string toString() { result = "[" + kind + "] " + c } -} - -/** - * Gets the enclosing callable of `n`. Unlike `n.getEnclosingCallable()`, this - * predicate ensures that joins go from `n` to the result instead of the other - * way around. - */ -pragma[inline] -DataFlowCallable getNodeEnclosingCallable(Node n) { - nodeEnclosingCallable(pragma[only_bind_out](n), pragma[only_bind_into](result)) -} - -/** Gets the type of `n` used for type pruning. */ -pragma[inline] -DataFlowType getNodeDataFlowType(Node n) { - nodeDataFlowType(pragma[only_bind_out](n), pragma[only_bind_into](result)) -} - -pragma[noinline] -private DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) { - result = getNodeEnclosingCallable(ret) -} - -pragma[noinline] -private ReturnPosition getReturnPosition0(ReturnNodeExt ret, ReturnKindExt kind) { - result.getCallable() = returnNodeGetEnclosingCallable(ret) and - kind = result.getKind() -} - -pragma[noinline] -ReturnPosition getReturnPosition(ReturnNodeExt ret) { - result = getReturnPosition0(ret, ret.getKind()) -} - -/** - * Checks whether `inner` can return to `call` in the call context `innercc`. - * Assumes a context of `inner = viableCallableExt(call)`. - */ -bindingset[innercc, inner, call] -predicate checkCallContextReturn(CallContext innercc, DataFlowCallable inner, DataFlowCall call) { - innercc instanceof CallContextAny - or - exists(DataFlowCallable c0, DataFlowCall call0 | - callEnclosingCallable(call0, inner) and - innercc = TReturn(c0, call0) and - c0 = prunedViableImplInCallContextReverse(call0, call) - ) -} - -/** - * Checks whether `call` can resolve to `calltarget` in the call context `cc`. - * Assumes a context of `calltarget = viableCallableExt(call)`. - */ -bindingset[cc, call, calltarget] -predicate checkCallContextCall(CallContext cc, DataFlowCall call, DataFlowCallable calltarget) { - exists(DataFlowCall ctx | cc = TSpecificCall(ctx) | - if reducedViableImplInCallContext(call, _, ctx) - then calltarget = prunedViableImplInCallContext(call, ctx) - else any() - ) - or - cc instanceof CallContextSomeCall - or - cc instanceof CallContextAny - or - cc instanceof CallContextReturn -} - -/** - * Resolves a return from `callable` in `cc` to `call`. This is equivalent to - * `callable = viableCallableExt(call) and checkCallContextReturn(cc, callable, call)`. - */ -bindingset[cc, callable] -predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { - cc instanceof CallContextAny and callable = viableCallableExt(call) - or - exists(DataFlowCallable c0, DataFlowCall call0 | - callEnclosingCallable(call0, callable) and - cc = TReturn(c0, call0) and - c0 = prunedViableImplInCallContextReverse(call0, call) - ) -} - -/** - * Resolves a call from `call` in `cc` to `result`. This is equivalent to - * `result = viableCallableExt(call) and checkCallContextCall(cc, call, result)`. - */ -bindingset[call, cc] -DataFlowCallable resolveCall(DataFlowCall call, CallContext cc) { - exists(DataFlowCall ctx | cc = TSpecificCall(ctx) | - if reducedViableImplInCallContext(call, _, ctx) - then result = prunedViableImplInCallContext(call, ctx) - else result = viableCallableExt(call) - ) - or - result = viableCallableExt(call) and cc instanceof CallContextSomeCall - or - result = viableCallableExt(call) and cc instanceof CallContextAny - or - result = viableCallableExt(call) and cc instanceof CallContextReturn -} - -/** An optional Boolean value. */ -class BooleanOption extends TBooleanOption { - string toString() { - this = TBooleanNone() and result = "" - or - this = TBooleanSome(any(boolean b | result = b.toString())) - } -} - -/** An optional `DataFlowCall`. */ -class DataFlowCallOption extends TDataFlowCallOption { - string toString() { - this = TDataFlowCallNone() and - result = "(none)" - or - exists(DataFlowCall call | - this = TDataFlowCallSome(call) and - result = call.toString() - ) - } -} - -/** An optional `ParamNode`. */ -class ParamNodeOption extends TParamNodeOption { - string toString() { - this = TParamNodeNone() and - result = "(none)" - or - exists(ParamNode p | - this = TParamNodeSome(p) and - result = p.toString() - ) - } -} - -/** - * A return context used to calculate flow summaries in reverse flow. - * - * The possible values are: - * - * - `TReturnCtxNone()`: no return flow. - * - `TReturnCtxNoFlowThrough()`: return flow, but flow through is not possible. - * - `TReturnCtxMaybeFlowThrough(ReturnPosition pos)`: return flow, of kind `pos`, and - * flow through may be possible. - */ -class ReturnCtx extends TReturnCtx { - string toString() { - this = TReturnCtxNone() and - result = "(none)" - or - this = TReturnCtxNoFlowThrough() and - result = "(no flow through)" - or - exists(ReturnPosition pos | - this = TReturnCtxMaybeFlowThrough(pos) and - result = pos.toString() - ) - } -} - -/** An approximated `Content` tagged with the type of a containing object. */ -class TypedContentApprox extends MkTypedContentApprox { - private ContentApprox c; - private DataFlowType t; - - TypedContentApprox() { this = MkTypedContentApprox(c, t) } - - /** Gets a typed content approximated by this value. */ - TypedContent getATypedContent() { result = getATypedContent(this) } - - /** Gets the content. */ - ContentApprox getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this approximated content. */ - string toString() { result = c.toString() } -} - -/** - * The front of an approximated access path. This is either a head or a nil. - */ -abstract class ApproxAccessPathFront extends TApproxAccessPathFront { - abstract string toString(); - - abstract DataFlowType getType(); - - abstract boolean toBoolNonEmpty(); - - TypedContentApprox getHead() { this = TApproxFrontHead(result) } - - pragma[nomagic] - TypedContent getAHead() { - exists(TypedContentApprox cont | - this = TApproxFrontHead(cont) and - result = cont.getATypedContent() - ) - } -} - -class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil { - private DataFlowType t; - - ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override boolean toBoolNonEmpty() { result = false } -} - -class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead { - private TypedContentApprox tc; - - ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) } - - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } - - override boolean toBoolNonEmpty() { result = true } -} - -/** An optional approximated access path front. */ -class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption { - string toString() { - this = TApproxAccessPathFrontNone() and result = "" - or - this = TApproxAccessPathFrontSome(any(ApproxAccessPathFront apf | result = apf.toString())) - } -} - -/** A `Content` tagged with the type of a containing object. */ -class TypedContent extends MkTypedContent { - private Content c; - private DataFlowType t; - - TypedContent() { this = MkTypedContent(c, t) } - - /** Gets the content. */ - Content getContent() { result = c } - - /** Gets the container type. */ - DataFlowType getContainerType() { result = t } - - /** Gets a textual representation of this content. */ - string toString() { result = c.toString() } - - /** - * Holds if access paths with this `TypedContent` at their head always should - * be tracked at high precision. This disables adaptive access path precision - * for such access paths. - */ - predicate forceHighPrecision() { forceHighPrecision(c) } -} - -/** - * The front of an access path. This is either a head or a nil. - */ -abstract class AccessPathFront extends TAccessPathFront { - abstract string toString(); - - abstract DataFlowType getType(); - - abstract ApproxAccessPathFront toApprox(); - - TypedContent getHead() { this = TFrontHead(result) } -} - -class AccessPathFrontNil extends AccessPathFront, TFrontNil { - private DataFlowType t; - - AccessPathFrontNil() { this = TFrontNil(t) } - - override string toString() { result = ppReprType(t) } - - override DataFlowType getType() { result = t } - - override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) } -} - -class AccessPathFrontHead extends AccessPathFront, TFrontHead { - private TypedContent tc; - - AccessPathFrontHead() { this = TFrontHead(tc) } - - override string toString() { result = tc.toString() } - - override DataFlowType getType() { result = tc.getContainerType() } - - override ApproxAccessPathFront toApprox() { result.getAHead() = tc } -} - -/** An optional access path front. */ -class AccessPathFrontOption extends TAccessPathFrontOption { - string toString() { - this = TAccessPathFrontNone() and result = "" - or - this = TAccessPathFrontSome(any(AccessPathFront apf | result = apf.toString())) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll deleted file mode 100644 index 9bbc70fbdf9..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ /dev/null @@ -1,278 +0,0 @@ -/** - * Provides consistency queries for checking invariants in the language-specific - * data-flow classes and predicates. - */ - -private import DataFlowImplSpecific::Private -private import DataFlowImplSpecific::Public -private import tainttracking1.TaintTrackingParameter::Private -private import tainttracking1.TaintTrackingParameter::Public - -module Consistency { - private newtype TConsistencyConfiguration = MkConsistencyConfiguration() - - /** A class for configuring the consistency queries. */ - class ConsistencyConfiguration extends TConsistencyConfiguration { - string toString() { none() } - - /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ - predicate uniqueEnclosingCallableExclude(Node n) { none() } - - /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ - predicate uniqueNodeLocationExclude(Node n) { none() } - - /** Holds if `n` should be excluded from the consistency test `missingLocation`. */ - predicate missingLocationExclude(Node n) { none() } - - /** Holds if `n` should be excluded from the consistency test `postWithInFlow`. */ - predicate postWithInFlowExclude(Node n) { none() } - - /** Holds if `n` should be excluded from the consistency test `argHasPostUpdate`. */ - predicate argHasPostUpdateExclude(ArgumentNode n) { none() } - - /** Holds if `n` should be excluded from the consistency test `reverseRead`. */ - predicate reverseReadExclude(Node n) { none() } - - /** Holds if `n` should be excluded from the consistency test `postHasUniquePre`. */ - predicate postHasUniquePreExclude(PostUpdateNode n) { none() } - - /** Holds if `n` should be excluded from the consistency test `uniquePostUpdate`. */ - predicate uniquePostUpdateExclude(Node n) { none() } - - /** Holds if `(call, ctx)` should be excluded from the consistency test `viableImplInCallContextTooLargeExclude`. */ - predicate viableImplInCallContextTooLargeExclude( - DataFlowCall call, DataFlowCall ctx, DataFlowCallable callable - ) { - none() - } - - /** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodeAtPosition`. */ - predicate uniqueParameterNodeAtPositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) { - none() - } - - /** Holds if `(c, pos, p)` should be excluded from the consistency test `uniqueParameterNodePosition`. */ - predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) { - none() - } - } - - private class RelevantNode extends Node { - RelevantNode() { - this instanceof ArgumentNode or - this instanceof ParameterNode or - this instanceof ReturnNode or - this = getAnOutNode(_, _) or - simpleLocalFlowStep(this, _) or - simpleLocalFlowStep(_, this) or - jumpStep(this, _) or - jumpStep(_, this) or - storeStep(this, _, _) or - storeStep(_, _, this) or - readStep(this, _, _) or - readStep(_, _, this) or - defaultAdditionalTaintStep(this, _) or - defaultAdditionalTaintStep(_, this) - } - } - - query predicate uniqueEnclosingCallable(Node n, string msg) { - exists(int c | - n instanceof RelevantNode and - c = count(nodeGetEnclosingCallable(n)) and - c != 1 and - not any(ConsistencyConfiguration conf).uniqueEnclosingCallableExclude(n) and - msg = "Node should have one enclosing callable but has " + c + "." - ) - } - - query predicate uniqueType(Node n, string msg) { - exists(int c | - n instanceof RelevantNode and - c = count(getNodeType(n)) and - c != 1 and - msg = "Node should have one type but has " + c + "." - ) - } - - query predicate uniqueNodeLocation(Node n, string msg) { - exists(int c | - c = - count(string filepath, int startline, int startcolumn, int endline, int endcolumn | - n.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - ) and - c != 1 and - not any(ConsistencyConfiguration conf).uniqueNodeLocationExclude(n) and - msg = "Node should have one location but has " + c + "." - ) - } - - query predicate missingLocation(string msg) { - exists(int c | - c = - strictcount(Node n | - not n.hasLocationInfo(_, _, _, _, _) and - not any(ConsistencyConfiguration conf).missingLocationExclude(n) - ) and - msg = "Nodes without location: " + c - ) - } - - query predicate uniqueNodeToString(Node n, string msg) { - exists(int c | - c = count(n.toString()) and - c != 1 and - msg = "Node should have one toString but has " + c + "." - ) - } - - query predicate missingToString(string msg) { - exists(int c | - c = strictcount(Node n | not exists(n.toString())) and - msg = "Nodes without toString: " + c - ) - } - - query predicate parameterCallable(ParameterNode p, string msg) { - exists(DataFlowCallable c | isParameterNode(p, c, _) and c != nodeGetEnclosingCallable(p)) and - msg = "Callable mismatch for parameter." - } - - query predicate localFlowIsLocal(Node n1, Node n2, string msg) { - simpleLocalFlowStep(n1, n2) and - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and - msg = "Local flow step does not preserve enclosing callable." - } - - query predicate readStepIsLocal(Node n1, Node n2, string msg) { - readStep(n1, _, n2) and - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and - msg = "Read step does not preserve enclosing callable." - } - - query predicate storeStepIsLocal(Node n1, Node n2, string msg) { - storeStep(n1, _, n2) and - nodeGetEnclosingCallable(n1) != nodeGetEnclosingCallable(n2) and - msg = "Store step does not preserve enclosing callable." - } - - private DataFlowType typeRepr() { result = getNodeType(_) } - - query predicate compatibleTypesReflexive(DataFlowType t, string msg) { - t = typeRepr() and - not compatibleTypes(t, t) and - msg = "Type compatibility predicate is not reflexive." - } - - query predicate unreachableNodeCCtx(Node n, DataFlowCall call, string msg) { - isUnreachableInCall(n, call) and - exists(DataFlowCallable c | - c = nodeGetEnclosingCallable(n) and - not viableCallable(call) = c - ) and - msg = "Call context for isUnreachableInCall is inconsistent with call graph." - } - - query predicate localCallNodes(DataFlowCall call, Node n, string msg) { - ( - n = getAnOutNode(call, _) and - msg = "OutNode and call does not share enclosing callable." - or - n.(ArgumentNode).argumentOf(call, _) and - msg = "ArgumentNode and call does not share enclosing callable." - ) and - nodeGetEnclosingCallable(n) != call.getEnclosingCallable() - } - - // This predicate helps the compiler forget that in some languages - // it is impossible for a result of `getPreUpdateNode` to be an - // instance of `PostUpdateNode`. - private Node getPre(PostUpdateNode n) { - result = n.getPreUpdateNode() - or - none() - } - - query predicate postIsNotPre(PostUpdateNode n, string msg) { - getPre(n) = n and - msg = "PostUpdateNode should not equal its pre-update node." - } - - query predicate postHasUniquePre(PostUpdateNode n, string msg) { - not any(ConsistencyConfiguration conf).postHasUniquePreExclude(n) and - exists(int c | - c = count(n.getPreUpdateNode()) and - c != 1 and - msg = "PostUpdateNode should have one pre-update node but has " + c + "." - ) - } - - query predicate uniquePostUpdate(Node n, string msg) { - not any(ConsistencyConfiguration conf).uniquePostUpdateExclude(n) and - 1 < strictcount(PostUpdateNode post | post.getPreUpdateNode() = n) and - msg = "Node has multiple PostUpdateNodes." - } - - query predicate postIsInSameCallable(PostUpdateNode n, string msg) { - nodeGetEnclosingCallable(n) != nodeGetEnclosingCallable(n.getPreUpdateNode()) and - msg = "PostUpdateNode does not share callable with its pre-update node." - } - - private predicate hasPost(Node n) { exists(PostUpdateNode post | post.getPreUpdateNode() = n) } - - query predicate reverseRead(Node n, string msg) { - exists(Node n2 | readStep(n, _, n2) and hasPost(n2) and not hasPost(n)) and - not any(ConsistencyConfiguration conf).reverseReadExclude(n) and - msg = "Origin of readStep is missing a PostUpdateNode." - } - - query predicate argHasPostUpdate(ArgumentNode n, string msg) { - not hasPost(n) and - not any(ConsistencyConfiguration c).argHasPostUpdateExclude(n) and - msg = "ArgumentNode is missing PostUpdateNode." - } - - // This predicate helps the compiler forget that in some languages - // it is impossible for a `PostUpdateNode` to be the target of - // `simpleLocalFlowStep`. - private predicate isPostUpdateNode(Node n) { n instanceof PostUpdateNode or none() } - - query predicate postWithInFlow(Node n, string msg) { - isPostUpdateNode(n) and - not clearsContent(n, _) and - simpleLocalFlowStep(_, n) and - not any(ConsistencyConfiguration c).postWithInFlowExclude(n) and - msg = "PostUpdateNode should not be the target of local flow." - } - - query predicate viableImplInCallContextTooLarge( - DataFlowCall call, DataFlowCall ctx, DataFlowCallable callable - ) { - callable = viableImplInCallContext(call, ctx) and - not callable = viableCallable(call) and - not any(ConsistencyConfiguration c).viableImplInCallContextTooLargeExclude(call, ctx, callable) - } - - query predicate uniqueParameterNodeAtPosition( - DataFlowCallable c, ParameterPosition pos, Node p, string msg - ) { - not any(ConsistencyConfiguration conf).uniqueParameterNodeAtPositionExclude(c, pos, p) and - isParameterNode(p, c, pos) and - not exists(unique(Node p0 | isParameterNode(p0, c, pos))) and - msg = "Parameters with overlapping positions." - } - - query predicate uniqueParameterNodePosition( - DataFlowCallable c, ParameterPosition pos, Node p, string msg - ) { - not any(ConsistencyConfiguration conf).uniqueParameterNodePositionExclude(c, pos, p) and - isParameterNode(p, c, pos) and - not exists(unique(ParameterPosition pos0 | isParameterNode(p, c, pos0))) and - msg = "Parameter node with multiple positions." - } - - query predicate uniqueContentApprox(Content c, string msg) { - not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and - msg = "Non-unique content approximation." - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll deleted file mode 100644 index 4ea383b20a1..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImplSpecific.qll +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Provides IR-specific definitions for use in the data flow library. - */ -module Private { - import DataFlowPrivate - import DataFlowDispatch -} - -module Public { - import DataFlowUtil -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll deleted file mode 100644 index 58569ef2425..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ /dev/null @@ -1,567 +0,0 @@ -private import cpp as Cpp -private import DataFlowUtil -private import semmle.code.cpp.ir.IR -private import DataFlowDispatch -private import DataFlowImplConsistency -private import semmle.code.cpp.ir.internal.IRCppLanguage -private import SsaInternals as Ssa - -/** Gets the callable in which this node occurs. */ -DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() } - -/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */ -predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos) { - p.isParameterOf(c, pos) -} - -/** Holds if `arg` is an `ArgumentNode` of `c` with position `pos`. */ -predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) { - arg.argumentOf(c, pos) -} - -/** - * A data flow node that occurs as the argument of a call and is passed as-is - * to the callable. Instance arguments (`this` pointer) and read side effects - * on parameters are also included. - */ -abstract class ArgumentNode extends Node { - /** - * Holds if this argument occurs at the given position in the given call. - * The instance argument is considered to have index `-1`. - */ - abstract predicate argumentOf(DataFlowCall call, ArgumentPosition pos); - - /** Gets the call in which this node is an argument. */ - DataFlowCall getCall() { this.argumentOf(result, _) } -} - -/** - * A data flow node that occurs as the argument to a call, or an - * implicit `this` pointer argument. - */ -private class PrimaryArgumentNode extends ArgumentNode, OperandNode { - override ArgumentOperand op; - - PrimaryArgumentNode() { exists(CallInstruction call | op = call.getAnArgumentOperand()) } - - override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - op = call.getArgumentOperand(pos.(DirectPosition).getIndex()) - } - - override string toStringImpl() { result = argumentOperandToString(op) } -} - -private string argumentOperandToString(ArgumentOperand op) { - exists(Expr unconverted | - unconverted = op.getDef().getUnconvertedResultExpression() and - result = unconverted.toString() - ) - or - // Certain instructions don't map to an unconverted result expression. For these cases - // we fall back to a simpler naming scheme. This can happen in IR-generated constructors. - not exists(op.getDef().getUnconvertedResultExpression()) and - ( - result = "Argument " + op.(PositionalArgumentOperand).getIndex() - or - op instanceof ThisArgumentOperand and result = "Argument this" - ) -} - -private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode { - override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) { - this.getCallInstruction() = dfCall and - pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and - pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex() - } - - override string toStringImpl() { - result = argumentOperandToString(this.getAddressOperand()) + " indirection" - } -} - -/** A parameter position represented by an integer. */ -class ParameterPosition = Position; - -/** An argument position represented by an integer. */ -class ArgumentPosition = Position; - -class Position extends TPosition { - abstract string toString(); -} - -class DirectPosition extends Position, TDirectPosition { - int index; - - DirectPosition() { this = TDirectPosition(index) } - - override string toString() { if index = -1 then result = "this" else result = index.toString() } - - int getIndex() { result = index } -} - -class IndirectionPosition extends Position, TIndirectionPosition { - int argumentIndex; - int indirectionIndex; - - IndirectionPosition() { this = TIndirectionPosition(argumentIndex, indirectionIndex) } - - override string toString() { - if argumentIndex = -1 - then if indirectionIndex > 0 then result = "this indirection" else result = "this" - else - if indirectionIndex > 0 - then result = argumentIndex.toString() + " indirection" - else result = argumentIndex.toString() - } - - int getArgumentIndex() { result = argumentIndex } - - int getIndirectionIndex() { result = indirectionIndex } -} - -newtype TPosition = - TDirectPosition(int index) { exists(any(CallInstruction c).getArgument(index)) } or - TIndirectionPosition(int argumentIndex, int indirectionIndex) { - hasOperandAndIndex(_, any(CallInstruction call).getArgumentOperand(argumentIndex), - indirectionIndex) - } - -private newtype TReturnKind = - TNormalReturnKind(int index) { - exists(IndirectReturnNode return | - return.getAddressOperand() = any(ReturnValueInstruction r).getReturnAddressOperand() and - index = return.getIndirectionIndex() - 1 // We subtract one because the return loads the value. - ) - } or - TIndirectReturnKind(int argumentIndex, int indirectionIndex) { - exists(IndirectReturnNode return, ReturnIndirectionInstruction returnInd | - returnInd.hasIndex(argumentIndex) and - return.getAddressOperand() = returnInd.getSourceAddressOperand() and - indirectionIndex = return.getIndirectionIndex() - ) - } - -/** - * A return kind. A return kind describes how a value can be returned - * from a callable. For C++, this is simply a function return. - */ -class ReturnKind extends TReturnKind { - /** Gets a textual representation of this return kind. */ - abstract string toString(); -} - -private class NormalReturnKind extends ReturnKind, TNormalReturnKind { - int index; - - NormalReturnKind() { this = TNormalReturnKind(index) } - - override string toString() { result = "indirect return" } -} - -private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind { - int argumentIndex; - int indirectionIndex; - - IndirectReturnKind() { this = TIndirectReturnKind(argumentIndex, indirectionIndex) } - - override string toString() { result = "indirect outparam[" + argumentIndex.toString() + "]" } -} - -/** A data flow node that occurs as the result of a `ReturnStmt`. */ -class ReturnNode extends Node instanceof IndirectReturnNode { - /** Gets the kind of this returned value. */ - abstract ReturnKind getKind(); -} - -/** - * This predicate represents an annoying hack that we have to do. We use the - * `ReturnIndirectionInstruction` to determine which variables need flow back - * out of a function. However, the IR will unconditionally create those for a - * variable passed to a function even though the variable was never updated by - * the function. And if a function has too many `ReturnNode`s the dataflow - * library lowers its precision for that function by disabling field flow. - * - * So we those eliminate `ReturnNode`s that would have otherwise been created - * by this unconditional `ReturnIndirectionInstruction` by requiring that there - * must exist an SSA definition of the IR variable in the function. - */ -private predicate hasNonInitializeParameterDef(IRVariable v) { - exists(Ssa::Def def | - not def.getDefiningInstruction() instanceof InitializeParameterInstruction and - v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable() - ) -} - -class ReturnIndirectionNode extends IndirectReturnNode, ReturnNode { - override ReturnKind getKind() { - exists(int argumentIndex, ReturnIndirectionInstruction returnInd | - returnInd.hasIndex(argumentIndex) and - this.getAddressOperand() = returnInd.getSourceAddressOperand() and - result = TIndirectReturnKind(argumentIndex, this.getIndirectionIndex()) and - hasNonInitializeParameterDef(returnInd.getIRVariable()) - ) - or - this.getAddressOperand() = any(ReturnValueInstruction r).getReturnAddressOperand() and - result = TNormalReturnKind(this.getIndirectionIndex() - 1) - } -} - -private Operand fullyConvertedCallStep(Operand op) { - not exists(getANonConversionUse(op)) and - exists(Instruction instr | - conversionFlow(op, instr, _) and - result = getAUse(instr) - ) -} - -/** - * Gets the instruction that uses this operand, if the instruction is not - * ignored for dataflow purposes. - */ -private Instruction getUse(Operand op) { - result = op.getUse() and - not Ssa::ignoreOperand(op) -} - -/** Gets a use of the instruction `instr` that is not ignored for dataflow purposes. */ -Operand getAUse(Instruction instr) { - result = instr.getAUse() and - not Ssa::ignoreOperand(result) -} - -/** - * Gets a use of `operand` that is: - * - not ignored for dataflow purposes, and - * - not a conversion-like instruction. - */ -private Instruction getANonConversionUse(Operand operand) { - result = getUse(operand) and - not conversionFlow(_, result, _) -} - -/** - * Gets the operand that represents the first use of the value of `call` following - * a sequence of conversion-like instructions. - */ -predicate operandForfullyConvertedCall(Operand operand, CallInstruction call) { - exists(getANonConversionUse(operand)) and - ( - operand = getAUse(call) - or - operand = fullyConvertedCallStep*(getAUse(call)) - ) -} - -/** - * Gets the instruction that represents the first use of the value of `call` following - * a sequence of conversion-like instructions. - * - * This predicate only holds if there is no suitable operand (i.e., no operand of a non- - * conversion instruction) to use to represent the value of `call` after conversions. - */ -predicate instructionForfullyConvertedCall(Instruction instr, CallInstruction call) { - not operandForfullyConvertedCall(_, call) and - ( - // If there is no use of the call then we pick the call instruction - not exists(getAUse(call)) and - instr = call - or - // Otherwise, flow to the first non-conversion use. - exists(Operand operand | operand = fullyConvertedCallStep*(getAUse(call)) | - instr = getANonConversionUse(operand) - ) - ) -} - -/** Holds if `node` represents the output node for `call`. */ -private predicate simpleOutNode(Node node, CallInstruction call) { - operandForfullyConvertedCall(node.asOperand(), call) - or - instructionForfullyConvertedCall(node.asInstruction(), call) -} - -/** A data flow node that represents the output of a call. */ -class OutNode extends Node { - OutNode() { - // Return values not hidden behind indirections - simpleOutNode(this, _) - or - // Return values hidden behind indirections - this instanceof IndirectReturnOutNode - or - // Modified arguments hidden behind indirections - this instanceof IndirectArgumentOutNode - } - - /** Gets the underlying call. */ - abstract DataFlowCall getCall(); - - abstract ReturnKind getReturnKind(); -} - -private class DirectCallOutNode extends OutNode { - CallInstruction call; - - DirectCallOutNode() { simpleOutNode(this, call) } - - override DataFlowCall getCall() { result = call } - - override ReturnKind getReturnKind() { result = TNormalReturnKind(0) } -} - -private class IndirectCallOutNode extends OutNode, IndirectReturnOutNode { - override DataFlowCall getCall() { result = this.getCallInstruction() } - - override ReturnKind getReturnKind() { result = TNormalReturnKind(this.getIndirectionIndex()) } -} - -private class SideEffectOutNode extends OutNode, IndirectArgumentOutNode { - override DataFlowCall getCall() { result = this.getCallInstruction() } - - override ReturnKind getReturnKind() { - result = TIndirectReturnKind(this.getArgumentIndex(), this.getIndirectionIndex()) - } -} - -/** - * Gets a node that can read the value returned from `call` with return kind - * `kind`. - */ -OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { - result.getCall() = call and - result.getReturnKind() = kind -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that loses the - * calling context. For example, this would happen with flow through a - * global or static variable. - */ -predicate jumpStep(Node n1, Node n2) { - exists(Cpp::GlobalOrNamespaceVariable v | - v = - n1.asInstruction() - .(StoreInstruction) - .getResultAddress() - .(VariableAddressInstruction) - .getAstVariable() and - v = n2.asVariable() - or - v = - n2.asInstruction() - .(LoadInstruction) - .getSourceAddress() - .(VariableAddressInstruction) - .getAstVariable() and - v = n1.asVariable() - ) -} - -/** - * Holds if data can flow from `node1` to `node2` via an assignment to `f`. - * Thus, `node2` references an object with a field `f` that contains the - * value of `node1`. - */ -predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) { - exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store | - nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and - node2.getIndirectionIndex() = 1 and - numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(), - numberOfLoads) - | - exists(FieldContent fc | fc = c | - fc.getField() = node2.getUpdatedField() and - fc.getIndirectionIndex() = 1 + indirectionIndex1 + numberOfLoads - ) - or - exists(UnionContent uc | uc = c | - uc.getAField() = node2.getUpdatedField() and - uc.getIndirectionIndex() = 1 + indirectionIndex1 + numberOfLoads - ) - ) -} - -/** - * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like - * operations and exactly `n` `LoadInstruction` operations. - */ -private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand operandTo, int ind) { - exists(LoadInstruction load | load.getSourceAddressOperand() = operandFrom | - operandTo = operandFrom and ind = 0 - or - numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1) - ) - or - exists(Operand op, Instruction instr | - instr = op.getDef() and - conversionFlow(operandFrom, instr, _) and - numberOfLoadsFromOperand(op, operandTo, ind) - ) -} - -/** - * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like - * operations and exactly `n` `LoadInstruction` operations. - */ -private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n) { - numberOfLoadsFromOperandRec(operandFrom, operandTo, n) - or - not any(LoadInstruction load).getSourceAddressOperand() = operandFrom and - not conversionFlow(operandFrom, _, _) and - operandFrom = operandTo and - n = 0 -} - -// Needed to join on both an operand and an index at the same time. -pragma[noinline] -predicate nodeHasOperand(Node node, Operand operand, int indirectionIndex) { - node.asOperand() = operand and indirectionIndex = 0 - or - hasOperandAndIndex(node, operand, indirectionIndex) -} - -// Needed to join on both an instruction and an index at the same time. -pragma[noinline] -predicate nodeHasInstruction(Node node, Instruction instr, int indirectionIndex) { - node.asInstruction() = instr and indirectionIndex = 0 - or - hasInstructionAndIndex(node, instr, indirectionIndex) -} - -/** - * Holds if data can flow from `node1` to `node2` via a read of `f`. - * Thus, `node1` references an object with a field `f` whose value ends up in - * `node2`. - */ -predicate readStep(Node node1, Content c, Node node2) { - exists(FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2 | - nodeHasOperand(node2, operand, indirectionIndex2) and - nodeHasOperand(node1, fa1.getObjectAddressOperand(), _) and - numberOfLoadsFromOperand(fa1, operand, numberOfLoads) - | - exists(FieldContent fc | fc = c | - fc.getField() = fa1.getField() and - fc.getIndirectionIndex() = indirectionIndex2 + numberOfLoads - ) - or - exists(UnionContent uc | uc = c | - uc.getAField() = fa1.getField() and - uc.getIndirectionIndex() = indirectionIndex2 + numberOfLoads - ) - ) -} - -/** - * Holds if values stored inside content `c` are cleared at node `n`. - */ -predicate clearsContent(Node n, Content c) { - none() // stub implementation -} - -/** - * Holds if the value that is being tracked is expected to be stored inside content `c` - * at node `n`. - */ -predicate expectsContent(Node n, ContentSet c) { none() } - -/** Gets the type of `n` used for type pruning. */ -DataFlowType getNodeType(Node n) { - suppressUnusedNode(n) and - result instanceof VoidType // stub implementation -} - -/** Gets a string representation of a type returned by `getNodeType`. */ -string ppReprType(DataFlowType t) { none() } // stub implementation - -/** - * Holds if `t1` and `t2` are compatible, that is, whether data can flow from - * a node of type `t1` to a node of type `t2`. - */ -pragma[inline] -predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { - any() // stub implementation -} - -private predicate suppressUnusedNode(Node n) { any() } - -////////////////////////////////////////////////////////////////////////////// -// Java QL library compatibility wrappers -////////////////////////////////////////////////////////////////////////////// -/** A node that performs a type cast. */ -class CastNode extends Node { - CastNode() { none() } // stub implementation -} - -/** - * A function that may contain code or a variable that may contain itself. When - * flow crosses from one _enclosing callable_ to another, the interprocedural - * data-flow library discards call contexts and inserts a node in the big-step - * relation used for human-readable path explanations. - */ -class DataFlowCallable = Cpp::Declaration; - -class DataFlowExpr = Expr; - -class DataFlowType = Type; - -/** A function call relevant for data flow. */ -class DataFlowCall extends CallInstruction { - Function getEnclosingCallable() { result = this.getEnclosingFunction() } -} - -predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation - -int accessPathLimit() { result = 5 } - -/** - * Holds if access paths with `c` at their head always should be tracked at high - * precision. This disables adaptive access path precision for such access paths. - */ -predicate forceHighPrecision(Content c) { none() } - -/** The unit type. */ -private newtype TUnit = TMkUnit() - -/** The trivial type with a single element. */ -class Unit extends TUnit { - /** Gets a textual representation of this element. */ - string toString() { result = "unit" } -} - -/** Holds if `n` should be hidden from path explanations. */ -predicate nodeIsHidden(Node n) { n instanceof OperandNode and not n instanceof ArgumentNode } - -class LambdaCallKind = Unit; - -/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */ -predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() } - -/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */ -predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() } - -/** Extra data-flow steps needed for lambda flow analysis. */ -predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } - -/** - * Holds if flow is allowed to pass from parameter `p` and back to itself as a - * side-effect, resulting in a summary from `p` to itself. - * - * One example would be to allow flow like `p.foo = p.bar;`, which is disallowed - * by default as a heuristic. - */ -predicate allowParameterReturnInSelf(ParameterNode p) { none() } - -/** An approximated `Content`. */ -class ContentApprox = Unit; - -/** Gets an approximated value for content `c`. */ -pragma[inline] -ContentApprox getContentApprox(Content c) { any() } - -private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration { - override predicate argHasPostUpdateExclude(ArgumentNode n) { - // The rules for whether an IR argument gets a post-update node are too - // complex to model here. - any() - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll deleted file mode 100644 index dc462fecc94..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ /dev/null @@ -1,1434 +0,0 @@ -/** - * Provides C++-specific definitions for use in the data flow library. - */ - -private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.controlflow.IRGuards -private import semmle.code.cpp.models.interfaces.DataFlow -private import DataFlowPrivate -private import ModelUtil -private import SsaInternals as Ssa - -cached -private module Cached { - /** - * The IR dataflow graph consists of the following nodes: - * - `InstructionNode`, which injects most instructions directly into the dataflow graph. - * - `OperandNode`, which similarly injects most operands directly into the dataflow graph. - * - `VariableNode`, which is used to model flow through global variables. - * - `PostFieldUpdateNode`, which is used to model the state of a field after a value has been stored - * into an address after a number of loads. - * - `SsaPhiNode`, which represents phi nodes as computed by the shared SSA library. - * - `IndirectArgumentOutNode`, which represents the value of an argument (and its indirections) after - * it leaves a function call. - * - `IndirectOperand`, which represents the value of `operand` after loading the address a number - * of times. - * - `IndirectInstruction`, which represents the value of `instr` after loading the address a number - * of times. - */ - cached - newtype TIRDataFlowNode = - TInstructionNode(Instruction i) { not Ssa::ignoreInstruction(i) } or - TOperandNode(Operand op) { not Ssa::ignoreOperand(op) } or - TVariableNode(Variable var) or - TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) { - indirectionIndex = - [1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())] - } or - TSsaPhiNode(Ssa::PhiNode phi) or - TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) { - Ssa::isModifiableByCall(operand) and - indirectionIndex = [1 .. Ssa::countIndirectionsForCppType(operand.getLanguageType())] - } or - TIndirectOperand(Operand op, int indirectionIndex) { - Ssa::hasIndirectOperand(op, indirectionIndex) - } or - TIndirectInstruction(Instruction instr, int indirectionIndex) { - Ssa::hasIndirectInstruction(instr, indirectionIndex) - } -} - -/** - * An operand that is defined by a `FieldAddressInstruction`. - */ -class FieldAddress extends Operand { - FieldAddressInstruction fai; - - FieldAddress() { fai = this.getDef() } - - /** Gets the field associated with this instruction. */ - Field getField() { result = fai.getField() } - - /** Gets the instruction whose result provides the address of the object containing the field. */ - Instruction getObjectAddress() { result = fai.getObjectAddress() } - - /** Gets the operand that provides the address of the object containing the field. */ - Operand getObjectAddressOperand() { result = fai.getObjectAddressOperand() } -} - -/** - * Holds if `opFrom` is an operand whose value flows to the result of `instrTo`. - * - * `isPointerArith` is `true` if `instrTo` is a `PointerArithmeticInstruction` and `opFrom` - * is the left operand. - */ -predicate conversionFlow(Operand opFrom, Instruction instrTo, boolean isPointerArith) { - isPointerArith = false and - ( - instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom - or - instrTo.(ConvertInstruction).getUnaryOperand() = opFrom - or - instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom - or - instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom - ) - or - isPointerArith = true and - instrTo.(PointerArithmeticInstruction).getLeftOperand() = opFrom -} - -private import Cached - -/** - * A node in a data flow graph. - * - * A node can be either an expression, a parameter, or an uninitialized local - * variable. Such nodes are created with `DataFlow::exprNode`, - * `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively. - */ -class Node extends TIRDataFlowNode { - /** - * INTERNAL: Do not use. - */ - Declaration getEnclosingCallable() { none() } // overridden in subclasses - - /** Gets the function to which this node belongs, if any. */ - Declaration getFunction() { none() } // overridden in subclasses - - /** Gets the type of this node. */ - DataFlowType getType() { none() } // overridden in subclasses - - /** Gets the instruction corresponding to this node, if any. */ - Instruction asInstruction() { result = this.(InstructionNode).getInstruction() } - - /** Gets the operands corresponding to this node, if any. */ - Operand asOperand() { result = this.(OperandNode).getOperand() } - - /** - * Gets the non-conversion expression corresponding to this node, if any. - * This predicate only has a result on nodes that represent the value of - * evaluating the expression. For data flowing _out of_ an expression, like - * when an argument is passed by reference, use `asDefiningArgument` instead - * of `asExpr`. - * - * If this node strictly (in the sense of `asConvertedExpr`) corresponds to - * a `Conversion`, then the result is the underlying non-`Conversion` base - * expression. - */ - Expr asExpr() { result = this.(ExprNode).getExpr() } - - /** - * Gets the non-conversion expression that's indirectly tracked by this node - * under `index` number of indirections. - */ - Expr asIndirectExpr(int index) { - exists(Operand operand | hasOperandAndIndex(this, operand, index) | - result = operand.getDef().getUnconvertedResultExpression() - ) - } - - /** - * Gets the non-conversion expression that's indirectly tracked by this node - * behind a number of indirections. - */ - Expr asIndirectExpr() { result = this.asIndirectExpr(_) } - - /** - * Gets the expression corresponding to this node, if any. The returned - * expression may be a `Conversion`. - */ - Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() } - - /** - * Gets the expression that's indirectly tracked by this node - * behind `index` number of indirections. - */ - Expr asIndirectConvertedExpr(int index) { - exists(Operand operand | hasOperandAndIndex(this, operand, index) | - result = operand.getDef().getConvertedResultExpression() - ) - } - - /** - * Gets the expression that's indirectly tracked by this node behind a - * number of indirections. - */ - Expr asIndirectConvertedExpr() { result = this.asIndirectConvertedExpr(_) } - - /** - * Gets the argument that defines this `DefinitionByReferenceNode`, if any. - * This predicate should be used instead of `asExpr` when referring to the - * value of a reference argument _after_ the call has returned. For example, - * in `f(&x)`, this predicate will have `&x` as its result for the `Node` - * that represents the new value of `x`. - */ - Expr asDefiningArgument() { result = this.asDefiningArgument(_) } - - /** - * Gets the argument that defines this `DefinitionByReferenceNode`, if any. - * - * Unlike `Node::asDefiningArgument/0`, this predicate gets the node representing - * the value of the `index`'th indirection after leaving a function. For example, - * in: - * ```cpp - * void f(int**); - * ... - * int** x = ...; - * f(x); - * ``` - * The node `n` such that `n.asDefiningArgument(1)` is the argument `x` will - * contain the value of `*x` after `f` has returned, and the node `n` such that - * `n.asDefiningArgument(2)` is the argument `x` will contain the value of `**x` - * after the `f` has returned. - */ - Expr asDefiningArgument(int index) { - // Subtract one because `DefinitionByReferenceNode` is defined to be in - // the range `[0 ... n - 1]` for some `n` instead of `[1 ... n]`. - this.(DefinitionByReferenceNode).getIndirectionIndex() = index - 1 and - result = this.(DefinitionByReferenceNode).getArgument() - } - - /** - * Gets the the argument going into a function for a node that represents - * the indirect value of the argument after `index` loads. For example, in: - * ```cpp - * void f(int**); - * ... - * int** x = ...; - * f(x); - * ``` - * The node `n` such that `n.asIndirectArgument(1)` represents the value of - * `*x` going into `f`, and the node `n` such that `n.asIndirectArgument(2)` - * represents the value of `**x` going into `f`. - */ - Expr asIndirectArgument(int index) { - this.(SideEffectOperandNode).getIndirectionIndex() = index and - result = this.(SideEffectOperandNode).getArgument() - } - - /** - * Gets the the argument going into a function for a node that represents - * the indirect value of the argument after any non-zero number of loads. - */ - Expr asIndirectArgument() { result = this.asIndirectArgument(_) } - - /** Gets the positional parameter corresponding to this node, if any. */ - Parameter asParameter() { result = this.asParameter(0) } - - /** - * Gets the uninitialized local variable corresponding to this node, if - * any. - */ - LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } - - /** - * Gets the positional parameter corresponding to the node that represents - * the value of the parameter after `index` number of loads, if any. For - * example, in: - * ```cpp - * void f(int** x) { ... } - * ``` - * - The node `n` such that `n.asParameter(0)` is the parameter `x` represents - * the value of `x`. - * - The node `n` such that `n.asParameter(1)` is the parameter `x` represents - * the value of `*x`. - * The node `n` such that `n.asParameter(2)` is the parameter `x` represents - * the value of `**x`. - */ - Parameter asParameter(int index) { - index = 0 and - result = this.(ExplicitParameterNode).getParameter() - or - this.(IndirectParameterNode).getIndirectionIndex() = index and - result = this.(IndirectParameterNode).getParameter() - } - - /** - * Gets the variable corresponding to this node, if any. This can be used for - * modeling flow in and out of global variables. - */ - Variable asVariable() { result = this.(VariableNode).getVariable() } - - /** - * Gets the expression that is partially defined by this node, if any. - * - * Partial definitions are created for field stores (`x.y = taint();` is a partial - * definition of `x`), and for calls that may change the value of an object (so - * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is - * a partial definition of `&x`). - */ - Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() } - - /** - * Gets an upper bound on the type of this node. - */ - DataFlowType getTypeBound() { result = this.getType() } - - /** Gets the location of this element. */ - cached - final Location getLocation() { result = this.getLocationImpl() } - - /** INTERNAL: Do not use. */ - Location getLocationImpl() { - none() // overridden by subclasses - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets a textual representation of this element. */ - cached - final string toString() { result = this.toStringImpl() } - - /** INTERNAL: Do not use. */ - string toStringImpl() { - none() // overridden by subclasses - } -} - -/** - * An instruction, viewed as a node in a data flow graph. - */ -class InstructionNode extends Node, TInstructionNode { - Instruction instr; - - InstructionNode() { this = TInstructionNode(instr) } - - /** Gets the instruction corresponding to this node. */ - Instruction getInstruction() { result = instr } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Declaration getFunction() { result = instr.getEnclosingFunction() } - - override DataFlowType getType() { result = instr.getResultType() } - - final override Location getLocationImpl() { result = instr.getLocation() } - - override string toStringImpl() { - // This predicate is overridden in subclasses. This default implementation - // does not use `Instruction.toString` because that's expensive to compute. - result = this.getInstruction().getOpcode().toString() - } -} - -/** - * An operand, viewed as a node in a data flow graph. - */ -class OperandNode extends Node, TOperandNode { - Operand op; - - OperandNode() { this = TOperandNode(op) } - - /** Gets the operand corresponding to this node. */ - Operand getOperand() { result = op } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Declaration getFunction() { result = op.getUse().getEnclosingFunction() } - - override DataFlowType getType() { result = op.getType() } - - final override Location getLocationImpl() { result = op.getLocation() } - - override string toStringImpl() { result = this.getOperand().toString() } -} - -/** - * Returns `t`, but stripped of the `n` outermost pointers, references, etc. - * - * For example, `stripPointers(int*&, 2)` is `int` and `stripPointers(int*, 0)` is `int*`. - */ -private Type stripPointers(Type t, int n) { - result = t and n = 0 - or - result = stripPointers(t.(PointerType).getBaseType(), n - 1) - or - result = stripPointers(t.(ArrayType).getBaseType(), n - 1) - or - result = stripPointers(t.(ReferenceType).getBaseType(), n - 1) - or - result = stripPointers(t.(PointerToMemberType).getBaseType(), n - 1) - or - result = stripPointers(t.(FunctionPointerIshType).getBaseType(), n - 1) -} - -/** - * INTERNAL: do not use. - * - * The node representing the value of a field after it has been updated. - */ -class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode { - int indirectionIndex; - FieldAddress fieldAddress; - - PostFieldUpdateNode() { this = TPostFieldUpdateNode(fieldAddress, indirectionIndex) } - - override Function getFunction() { result = fieldAddress.getUse().getEnclosingFunction() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - FieldAddress getFieldAddress() { result = fieldAddress } - - Field getUpdatedField() { result = fieldAddress.getField() } - - int getIndirectionIndex() { result = indirectionIndex } - - override Node getPreUpdateNode() { - hasOperandAndIndex(result, pragma[only_bind_into](fieldAddress).getObjectAddressOperand(), - indirectionIndex) - } - - override Expr getDefinedExpr() { - result = fieldAddress.getObjectAddress().getUnconvertedResultExpression() - } - - override Location getLocationImpl() { result = fieldAddress.getLocation() } - - override string toStringImpl() { result = this.getPreUpdateNode() + " [post update]" } -} - -/** - * INTERNAL: do not use. - * - * A phi node produced by the shared SSA library, viewed as a node in a data flow graph. - */ -class SsaPhiNode extends Node, TSsaPhiNode { - Ssa::PhiNode phi; - - SsaPhiNode() { this = TSsaPhiNode(phi) } - - /** Gets the phi node associated with this node. */ - Ssa::PhiNode getPhiNode() { result = phi } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() } - - override DataFlowType getType() { result = this.getAnInput().getType() } - - final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() } - - override string toStringImpl() { result = "Phi" } - - /** - * Gets a node that is used as input to this phi node. - * `fromBackEdge` is true if data flows along a back-edge, - * and `false` otherwise. - */ - final Node getAnInput(boolean fromBackEdge) { - localFlowStep(result, this) and - if phi.getBasicBlock().dominates(getBasicBlock(result)) - then fromBackEdge = true - else fromBackEdge = false - } - - /** Gets a node that is used as input to this phi node. */ - final Node getAnInput() { result = this.getAnInput(_) } -} - -/** - * INTERNAL: do not use. - * - * A node representing a value after leaving a function. - */ -class SideEffectOperandNode extends Node, IndirectOperand { - CallInstruction call; - int argumentIndex; - - SideEffectOperandNode() { operand = call.getArgumentOperand(argumentIndex) } - - CallInstruction getCallInstruction() { result = call } - - Operand getAddressOperand() { result = operand } - - int getArgumentIndex() { result = argumentIndex } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Function getFunction() { result = call.getEnclosingFunction() } - - Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() } -} - -/** - * INTERNAL: do not use. - * - * A node representing an indirection of a parameter. - */ -class IndirectParameterNode extends Node, IndirectInstruction { - InitializeParameterInstruction init; - - IndirectParameterNode() { this.getInstruction() = init } - - int getArgumentIndex() { init.hasIndex(result) } - - /** Gets the parameter whose indirection is initialized. */ - Parameter getParameter() { result = init.getParameter() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Function getFunction() { result = this.getInstruction().getEnclosingFunction() } - - override string toStringImpl() { - result = this.getParameter().toString() + " indirection" - or - not exists(this.getParameter()) and - result = "this indirection" - } -} - -/** - * INTERNAL: do not use. - * - * A node representing the indirection of a value that is - * about to be returned from a function. - */ -class IndirectReturnNode extends IndirectOperand { - IndirectReturnNode() { - this.getOperand() = any(ReturnIndirectionInstruction ret).getSourceAddressOperand() - or - this.getOperand() = any(ReturnValueInstruction ret).getReturnAddressOperand() - } - - Operand getAddressOperand() { result = operand } - - override Declaration getEnclosingCallable() { result = this.getFunction() } -} - -/** - * INTERNAL: do not use. - * - * A node representing the indirection of a value after it - * has been returned from a function. - */ -class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PostUpdateNode { - ArgumentOperand operand; - int indirectionIndex; - - IndirectArgumentOutNode() { this = TIndirectArgumentOutNode(operand, indirectionIndex) } - - int getIndirectionIndex() { result = indirectionIndex } - - int getArgumentIndex() { - exists(CallInstruction call | call.getArgumentOperand(result) = operand) - } - - Operand getAddressOperand() { result = operand } - - CallInstruction getCallInstruction() { result.getAnArgumentOperand() = operand } - - Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Function getFunction() { result = this.getCallInstruction().getEnclosingFunction() } - - override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex) } - - override string toStringImpl() { - // This string should be unique enough to be helpful but common enough to - // avoid storing too many different strings. - result = this.getStaticCallTarget().getName() + " output argument" - or - not exists(this.getStaticCallTarget()) and - result = "output argument" - } - - override Location getLocationImpl() { result = operand.getLocation() } -} - -pragma[nomagic] -predicate indirectReturnOutNodeOperand0(CallInstruction call, Operand operand, int indirectionIndex) { - Ssa::hasIndirectInstruction(call, indirectionIndex) and - operandForfullyConvertedCall(operand, call) -} - -pragma[nomagic] -predicate indirectReturnOutNodeInstruction0( - CallInstruction call, Instruction instr, int indirectionIndex -) { - Ssa::hasIndirectInstruction(call, indirectionIndex) and - instructionForfullyConvertedCall(instr, call) -} - -/** - * INTERNAL: do not use. - * - * A node representing the value of a function call. - */ -class IndirectReturnOutNode extends Node { - CallInstruction call; - int indirectionIndex; - - IndirectReturnOutNode() { - // Annoyingly, we need to pick the fully converted value as the output of the function to - // make flow through in the shared dataflow library work correctly. - exists(Operand operand | - indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and - hasOperandAndIndex(this, operand, indirectionIndex) - ) - or - exists(Instruction instr | - indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and - hasInstructionAndIndex(this, instr, indirectionIndex) - ) - } - - CallInstruction getCallInstruction() { result = call } - - int getIndirectionIndex() { result = indirectionIndex } -} - -private PointerType getGLValueType(Type t, int indirectionIndex) { - result.getBaseType() = stripPointers(t, indirectionIndex - 1) -} - -bindingset[isGLValue] -private DataFlowType getTypeImpl(Type t, int indirectionIndex, boolean isGLValue) { - if isGLValue = true - then - result = getGLValueType(t, indirectionIndex) - or - // Ideally, the above case would cover all glvalue cases. However, consider the case where - // the database consists only of: - // ``` - // void test() { - // int* x; - // x = nullptr; - // } - // ``` - // and we want to compute the type of `*x` in the assignment `x = nullptr`. Here, `x` is an lvalue - // of type int* (which morally is an int**). So when we call `getTypeImpl` it will be with the - // parameters: - // - t = int* - // - indirectionIndex = 1 (when we want to model the dataflow node corresponding to *x) - // - isGLValue = true - // In this case, `getTypeImpl(t, indirectionIndex, isGLValue)` should give back `int**`. In this - // case, however, `int**` does not exist in the database. So instead we return int* (which is - // wrong, but at least we have a type). - not exists(getGLValueType(t, indirectionIndex)) and - result = stripPointers(t, indirectionIndex - 1) - else result = stripPointers(t, indirectionIndex) -} - -/** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an operand in the IR - * after `index` number of loads. - */ -class IndirectOperand extends Node, TIndirectOperand { - Operand operand; - int indirectionIndex; - - IndirectOperand() { this = TIndirectOperand(operand, indirectionIndex) } - - /** Gets the underlying instruction. */ - Operand getOperand() { result = operand } - - int getIndirectionIndex() { result = indirectionIndex } - - override Function getFunction() { result = this.getOperand().getDef().getEnclosingFunction() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override DataFlowType getType() { - exists(boolean isGLValue | if operand.isGLValue() then isGLValue = true else isGLValue = false | - result = getTypeImpl(operand.getType().getUnspecifiedType(), indirectionIndex, isGLValue) - ) - } - - final override Location getLocationImpl() { result = this.getOperand().getLocation() } - - override string toStringImpl() { - result = instructionNode(this.getOperand().getDef()).toStringImpl() + " indirection" - } -} - -/** - * The value of an uninitialized local variable, viewed as a node in a data - * flow graph. - */ -class UninitializedNode extends Node { - LocalVariable v; - - UninitializedNode() { - exists(Ssa::Def def | - def.getDefiningInstruction() instanceof UninitializedInstruction and - Ssa::nodeToDefOrUse(this, def) and - v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() - ) - } - - /** Gets the uninitialized local variable corresponding to this node. */ - LocalVariable getLocalVariable() { result = v } -} - -/** - * INTERNAL: Do not use. - * - * A node that represents the indirect value of an instruction in the IR - * after `index` number of loads. - */ -class IndirectInstruction extends Node, TIndirectInstruction { - Instruction instr; - int indirectionIndex; - - IndirectInstruction() { this = TIndirectInstruction(instr, indirectionIndex) } - - /** Gets the underlying instruction. */ - Instruction getInstruction() { result = instr } - - int getIndirectionIndex() { result = indirectionIndex } - - override Function getFunction() { result = this.getInstruction().getEnclosingFunction() } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override DataFlowType getType() { - exists(boolean isGLValue | if instr.isGLValue() then isGLValue = true else isGLValue = false | - result = getTypeImpl(instr.getResultType().getUnspecifiedType(), indirectionIndex, isGLValue) - ) - } - - final override Location getLocationImpl() { result = this.getInstruction().getLocation() } - - override string toStringImpl() { - result = instructionNode(this.getInstruction()).toStringImpl() + " indirection" - } -} - -private predicate isFullyConvertedArgument(Expr e) { - e = any(Call call).getAnArgument().getFullyConverted() -} - -private predicate isFullyConvertedCall(Expr e) { e = any(Call call).getFullyConverted() } - -/** Holds if `Node::asExpr` should map an some operand node to `e`. */ -private predicate convertedExprMustBeOperand(Expr e) { - isFullyConvertedArgument(e) - or - isFullyConvertedCall(e) -} - -/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */ -predicate exprNodeShouldBeOperand(Node node, Expr e) { - e = node.asOperand().getDef().getConvertedResultExpression() and - convertedExprMustBeOperand(e) -} - -/** - * Holds if `load` is a `LoadInstruction` that is the result of evaluating `e` - * and `node` is an `IndirectOperandNode` that should map `node.asExpr()` to `e`. - * - * We map `e` to `node.asExpr()` when `node` semantically represents the - * same value as `load`. A subsequent flow step will flow `node` to - * the `LoadInstruction`. - */ -private predicate exprNodeShouldBeIndirectOperand(IndirectOperand node, Expr e, LoadInstruction load) { - node.getIndirectionIndex() = 1 and - e = load.getConvertedResultExpression() and - load.getSourceAddressOperand() = node.getOperand() and - not convertedExprMustBeOperand(e) -} - -/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */ -predicate exprNodeShouldBeInstruction(Node node, Expr e) { - e = node.asInstruction().getConvertedResultExpression() and - not exprNodeShouldBeOperand(_, e) and - not exprNodeShouldBeIndirectOperand(_, e, _) -} - -private class ExprNodeBase extends Node { - Expr getConvertedExpr() { none() } // overridden by subclasses - - Expr getExpr() { none() } // overridden by subclasses -} - -private class InstructionExprNode extends ExprNodeBase, InstructionNode { - InstructionExprNode() { exprNodeShouldBeInstruction(this, _) } - - final override Expr getConvertedExpr() { exprNodeShouldBeInstruction(this, result) } - - final override Expr getExpr() { result = this.getInstruction().getUnconvertedResultExpression() } - - final override string toStringImpl() { result = this.getConvertedExpr().toString() } -} - -private class OperandExprNode extends ExprNodeBase, OperandNode { - OperandExprNode() { exprNodeShouldBeOperand(this, _) } - - final override Expr getConvertedExpr() { exprNodeShouldBeOperand(this, result) } - - final override Expr getExpr() { - result = this.getOperand().getDef().getUnconvertedResultExpression() - } - - final override string toStringImpl() { - // Avoid generating multiple `toString` results for `ArgumentNode`s - // since they have a better `toString`. - result = this.(ArgumentNode).toStringImpl() - or - not this instanceof ArgumentNode and - result = this.getConvertedExpr().toString() - } -} - -private class IndirectOperandExprNode extends ExprNodeBase, IndirectOperand { - LoadInstruction load; - - IndirectOperandExprNode() { exprNodeShouldBeIndirectOperand(this, _, load) } - - final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOperand(this, result, load) } - - final override Expr getExpr() { result = load.getUnconvertedResultExpression() } - - final override string toStringImpl() { result = this.getConvertedExpr().toString() } -} - -/** - * An expression, viewed as a node in a data flow graph. - */ -class ExprNode extends Node instanceof ExprNodeBase { - /** - * Gets the non-conversion expression corresponding to this node, if any. If - * this node strictly (in the sense of `getConvertedExpr`) corresponds to a - * `Conversion`, then the result is that `Conversion`'s non-`Conversion` base - * expression. - */ - Expr getExpr() { result = super.getExpr() } - - /** - * Gets the expression corresponding to this node, if any. The returned - * expression may be a `Conversion`. - */ - Expr getConvertedExpr() { result = super.getConvertedExpr() } -} - -/** - * The value of a parameter at function entry, viewed as a node in a data - * flow graph. This includes both explicit parameters such as `x` in `f(x)` - * and implicit parameters such as `this` in `x.f()`. - * - * To match a specific kind of parameter, consider using one of the subclasses - * `ExplicitParameterNode`, `ThisParameterNode`, or - * `ParameterIndirectionNode`. - */ -class ParameterNode extends Node { - ParameterNode() { - // To avoid making this class abstract, we enumerate its values here - this.asInstruction() instanceof InitializeParameterInstruction - or - this instanceof IndirectParameterNode - } - - /** - * Holds if this node is the parameter of `f` at the specified position. The - * implicit `this` parameter is considered to have position `-1`, and - * pointer-indirection parameters are at further negative positions. - */ - predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses -} - -/** An explicit positional parameter, not including `this` or `...`. */ -private class ExplicitParameterNode extends ParameterNode, InstructionNode { - override InitializeParameterInstruction instr; - - ExplicitParameterNode() { exists(instr.getParameter()) } - - override predicate isParameterOf(Function f, ParameterPosition pos) { - f.getParameter(pos.(DirectPosition).getIndex()) = instr.getParameter() - } - - /** Gets the `Parameter` associated with this node. */ - Parameter getParameter() { result = instr.getParameter() } - - override string toStringImpl() { result = instr.getParameter().toString() } -} - -/** An implicit `this` parameter. */ -class ThisParameterNode extends ParameterNode, InstructionNode { - override InitializeParameterInstruction instr; - - ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable } - - override predicate isParameterOf(Function f, ParameterPosition pos) { - pos.(DirectPosition).getIndex() = -1 and instr.getEnclosingFunction() = f - } - - override string toStringImpl() { result = "this" } -} - -pragma[noinline] -private predicate indirectPostionHasArgumentIndexAndIndex( - IndirectionPosition pos, int argumentIndex, int indirectionIndex -) { - pos.getArgumentIndex() = argumentIndex and - pos.getIndirectionIndex() = indirectionIndex -} - -pragma[noinline] -private predicate indirectParameterNodeHasArgumentIndexAndIndex( - IndirectParameterNode node, int argumentIndex, int indirectionIndex -) { - node.getArgumentIndex() = argumentIndex and - node.getIndirectionIndex() = indirectionIndex -} - -/** A synthetic parameter to model the pointed-to object of a pointer parameter. */ -class ParameterIndirectionNode extends ParameterNode instanceof IndirectParameterNode { - override predicate isParameterOf(Function f, ParameterPosition pos) { - IndirectParameterNode.super.getEnclosingCallable() = f and - exists(int argumentIndex, int indirectionIndex | - indirectPostionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and - indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex) - ) - } -} - -/** - * A node associated with an object after an operation that might have - * changed its state. - * - * This can be either the argument to a callable after the callable returns - * (which might have mutated the argument), or the qualifier of a field after - * an update to the field. - * - * Nodes corresponding to AST elements, for example `ExprNode`, usually refer - * to the value before the update with the exception of `ClassInstanceExpr`, - * which represents the value after the constructor has run. - */ -abstract class PostUpdateNode extends Node { - /** - * Gets the node before the state update. - */ - abstract Node getPreUpdateNode(); - - final override DataFlowType getType() { result = this.getPreUpdateNode().getType() } -} - -/** - * The base class for nodes that perform "partial definitions". - * - * In contrast to a normal "definition", which provides a new value for - * something, a partial definition is an expression that may affect a - * value, but does not necessarily replace it entirely. For example: - * ``` - * x.y = 1; // a partial definition of the object `x`. - * x.y.z = 1; // a partial definition of the object `x.y` and `x`. - * x.setY(1); // a partial definition of the object `x`. - * setY(&x); // a partial definition of the object `x`. - * ``` - */ -abstract private class PartialDefinitionNode extends PostUpdateNode { - abstract Expr getDefinedExpr(); -} - -/** - * A node that represents the value of a variable after a function call that - * may have changed the variable because it's passed by reference. - * - * A typical example would be a call `f(&x)`. Firstly, there will be flow into - * `x` from previous definitions of `x`. Secondly, there will be a - * `DefinitionByReferenceNode` to represent the value of `x` after the call has - * returned. This node will have its `getArgument()` equal to `&x` and its - * `getVariableAccess()` equal to `x`. - */ -class DefinitionByReferenceNode extends IndirectArgumentOutNode { - /** Gets the unconverted argument corresponding to this node. */ - Expr getArgument() { result = this.getAddressOperand().getDef().getUnconvertedResultExpression() } - - /** Gets the parameter through which this value is assigned. */ - Parameter getParameter() { - result = this.getCallInstruction().getStaticCallTarget().getParameter(this.getArgumentIndex()) - } -} - -/** - * A `Node` corresponding to a variable in the program, as opposed to the - * value of that variable at some particular point. This can be used for - * modeling flow in and out of global variables. - */ -class VariableNode extends Node, TVariableNode { - Variable v; - - VariableNode() { this = TVariableNode(v) } - - /** Gets the variable corresponding to this node. */ - Variable getVariable() { result = v } - - override Declaration getFunction() { none() } - - override Declaration getEnclosingCallable() { - // When flow crosses from one _enclosing callable_ to another, the - // interprocedural data-flow library discards call contexts and inserts a - // node in the big-step relation used for human-readable path explanations. - // Therefore we want a distinct enclosing callable for each `VariableNode`, - // and that can be the `Variable` itself. - result = v - } - - override DataFlowType getType() { result = v.getType() } - - final override Location getLocationImpl() { result = v.getLocation() } - - override string toStringImpl() { result = v.toString() } -} - -/** - * Gets the node corresponding to `instr`. - */ -InstructionNode instructionNode(Instruction instr) { result.getInstruction() = instr } - -/** - * Gets the node corresponding to `operand`. - */ -OperandNode operandNode(Operand operand) { result.getOperand() = operand } - -/** - * Gets the `Node` corresponding to the value of evaluating `e` or any of its - * conversions. There is no result if `e` is a `Conversion`. For data flowing - * _out of_ an expression, like when an argument is passed by reference, use - * `definitionByReferenceNodeFromArgument` instead. - */ -ExprNode exprNode(Expr e) { result.getExpr() = e } - -/** - * Gets the `Node` corresponding to the value of evaluating `e`. Here, `e` may - * be a `Conversion`. For data flowing _out of_ an expression, like when an - * argument is passed by reference, use - * `definitionByReferenceNodeFromArgument` instead. - */ -ExprNode convertedExprNode(Expr e) { result.getConvertedExpr() = e } - -/** - * Gets the `Node` corresponding to the value of `p` at function entry. - */ -ExplicitParameterNode parameterNode(Parameter p) { result.getParameter() = p } - -/** - * Gets the `Node` corresponding to a definition by reference of the variable - * that is passed as unconverted `argument` of a call. - */ -DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) { - result.getArgument() = argument -} - -/** Gets the `VariableNode` corresponding to the variable `v`. */ -VariableNode variableNode(Variable v) { result.getVariable() = v } - -/** - * DEPRECATED: See UninitializedNode. - * - * Gets the `Node` corresponding to the value of an uninitialized local - * variable `v`. - */ -Node uninitializedNode(LocalVariable v) { none() } - -/** - * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local - * (intra-procedural) step. - */ -predicate localFlowStep = simpleLocalFlowStep/2; - -private predicate indirectionOperandFlow(IndirectOperand nodeFrom, Node nodeTo) { - // Reduce the indirection count by 1 if we're passing through a `LoadInstruction`. - exists(int ind, LoadInstruction load | - hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and - nodeHasInstruction(nodeTo, load, ind - 1) - ) - or - // If an operand flows to an instruction, then the indirection of - // the operand also flows to the indirction of the instruction. - exists(Operand operand, Instruction instr, int indirectionIndex | - simpleInstructionLocalFlowStep(operand, instr) and - hasOperandAndIndex(nodeFrom, operand, indirectionIndex) and - hasInstructionAndIndex(nodeTo, instr, indirectionIndex) - ) - or - // If there's indirect flow to an operand, then there's also indirect - // flow to the operand after applying some pointer arithmetic. - exists(PointerArithmeticInstruction pointerArith, int indirectionIndex | - hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), indirectionIndex) and - hasInstructionAndIndex(nodeTo, pointerArith, indirectionIndex) - ) -} - -pragma[noinline] -predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) { - indirectOperand.getOperand() = operand and - indirectOperand.getIndirectionIndex() = indirectionIndex -} - -pragma[noinline] -predicate hasInstructionAndIndex( - IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex -) { - indirectInstr.getInstruction() = instr and - indirectInstr.getIndirectionIndex() = indirectionIndex -} - -private predicate indirectionInstructionFlow(IndirectInstruction nodeFrom, IndirectOperand nodeTo) { - // If there's flow from an instruction to an operand, then there's also flow from the - // indirect instruction to the indirect operand. - exists(Operand operand, Instruction instr, int indirectionIndex | - simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) - | - hasOperandAndIndex(nodeTo, operand, indirectionIndex) and - hasInstructionAndIndex(nodeFrom, instr, indirectionIndex) - ) -} - -/** - * INTERNAL: do not use. - * - * This is the local flow predicate that's used as a building block in global - * data flow. It may have less flow than the `localFlowStep` predicate. - */ -predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { - // Post update node -> Node flow - Ssa::ssaFlow(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo) - or - // Def-use/Use-use flow - Ssa::ssaFlow(nodeFrom, nodeTo) - or - // Operand -> Instruction flow - simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) - or - // Instruction -> Operand flow - simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) - or - // Phi node -> Node flow - Ssa::fromPhiNode(nodeFrom, nodeTo) - or - // Indirect operand -> (indirect) instruction flow - indirectionOperandFlow(nodeFrom, nodeTo) - or - // Indirect instruction -> indirect operand flow - indirectionInstructionFlow(nodeFrom, nodeTo) - or - // Flow through modeled functions - modelFlow(nodeFrom, nodeTo) - or - // Reverse flow: data that flows from the definition node back into the indirection returned - // by a function. This allows data to flow 'in' through references returned by a modeled - // function such as `operator[]`. - exists(Operand address, int indirectionIndex | - nodeHasOperand(nodeTo.(IndirectReturnOutNode), address, indirectionIndex) - | - exists(StoreInstruction store | - nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and - store.getDestinationAddressOperand() = address - ) - or - Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex) - ) -} - -pragma[noinline] -private predicate getAddressType(LoadInstruction load, Type t) { - exists(Instruction address | - address = load.getSourceAddress() and - t = address.getResultType() - ) -} - -/** - * Like the AST dataflow library, we want to conflate the address and value of a reference. This class - * represents the `LoadInstruction` that is generated from a reference dereference. - */ -private class ReferenceDereferenceInstruction extends LoadInstruction { - ReferenceDereferenceInstruction() { - exists(ReferenceType ref | - getAddressType(this, ref) and - this.getResultType() = ref.getBaseType() - ) - } -} - -private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) { - // Treat all conversions as flow, even conversions between different numeric types. - conversionFlow(opFrom, iTo, false) - or - iTo.(CopyInstruction).getSourceValueOperand() = opFrom - or - // Conflate references and values like in AST dataflow. - iTo.(ReferenceDereferenceInstruction).getSourceAddressOperand() = opFrom -} - -private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) { - not opTo instanceof MemoryOperand and - opTo.getDef() = iFrom -} - -private predicate modelFlow(Node nodeFrom, Node nodeTo) { - exists( - CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut - | - call.getStaticCallTarget() = func and - func.hasDataFlow(modelIn, modelOut) - | - nodeFrom = callInput(call, modelIn) and - nodeTo = callOutput(call, modelOut) - or - exists(int d | - nodeFrom = callInput(call, modelIn, d) and - nodeTo = callOutput(call, modelOut, d) - ) - ) -} - -/** - * Holds if data flows from `source` to `sink` in zero or more local - * (intra-procedural) steps. - */ -pragma[inline] -predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } - -/** - * Holds if data can flow from `i1` to `i2` in zero or more - * local (intra-procedural) steps. - */ -pragma[inline] -predicate localInstructionFlow(Instruction e1, Instruction e2) { - localFlow(instructionNode(e1), instructionNode(e2)) -} - -/** - * Holds if data can flow from `e1` to `e2` in zero or more - * local (intra-procedural) steps. - */ -pragma[inline] -predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } - -cached -private newtype TContent = - TFieldContent(Field f, int indirectionIndex) { - indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(f.getUnspecifiedType())] and - // Reads and writes of union fields are tracked using `UnionContent`. - not f.getDeclaringType() instanceof Union - } or - TUnionContent(Union u, int indirectionIndex) { - // We key `UnionContent` by the union instead of its fields since a write to one - // field can be read by any read of the union's fields. - indirectionIndex = - [1 .. max(Ssa::getMaxIndirectionsForType(u.getAField().getUnspecifiedType()))] - } or - TCollectionContent() or // Not used in C/C++ - TArrayContent() // Not used in C/C++. - -/** - * A description of the way data may be stored inside an object. Examples - * include instance fields, the contents of a collection object, or the contents - * of an array. - */ -class Content extends TContent { - /** Gets a textual representation of this element. */ - abstract string toString(); - - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0 - } -} - -/** A reference through a non-union instance field. */ -class FieldContent extends Content, TFieldContent { - Field f; - int indirectionIndex; - - FieldContent() { this = TFieldContent(f, indirectionIndex) } - - override string toString() { - indirectionIndex = 1 and result = f.toString() - or - indirectionIndex > 1 and result = f.toString() + " indirection" - } - - Field getField() { result = f } - - pragma[inline] - int getIndirectionIndex() { - pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex) - } -} - -/** A reference through an instance field of a union. */ -class UnionContent extends Content, TUnionContent { - Union u; - int indirectionIndex; - - UnionContent() { this = TUnionContent(u, indirectionIndex) } - - override string toString() { - indirectionIndex = 1 and result = u.toString() - or - indirectionIndex > 1 and result = u.toString() + " indirection" - } - - Field getAField() { result = u.getAField() } - - pragma[inline] - int getIndirectionIndex() { - pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex) - } -} - -/** A reference through an array. */ -class ArrayContent extends Content, TArrayContent { - override string toString() { result = "[]" } -} - -/** A reference through the contents of some collection-like container. */ -private class CollectionContent extends Content, TCollectionContent { - override string toString() { result = "" } -} - -/** - * An entity that represents a set of `Content`s. - * - * The set may be interpreted differently depending on whether it is - * stored into (`getAStoreContent`) or read from (`getAReadContent`). - */ -class ContentSet instanceof Content { - /** Gets a content that may be stored into when storing into this set. */ - Content getAStoreContent() { result = this } - - /** Gets a content that may be read from when reading from this set. */ - Content getAReadContent() { result = this } - - /** Gets a textual representation of this content set. */ - string toString() { result = super.toString() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) { - super.hasLocationInfo(path, sl, sc, el, ec) - } -} - -private IRBlock getBasicBlock(Node node) { - node.asInstruction().getBlock() = result - or - node.asOperand().getUse().getBlock() = result - or - node.(SsaPhiNode).getPhiNode().getBasicBlock() = result - or - node.(IndirectOperand).getOperand().getUse().getBlock() = result - or - node.(IndirectInstruction).getInstruction().getBlock() = result - or - result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode()) -} - -/** - * Holds if the guard `g` validates the expression `e` upon evaluating to `branch`. - * - * The expression `e` is expected to be a syntactic part of the guard `g`. - * For example, the guard `g` might be a call `isSafe(x)` and the expression `e` - * the argument `x`. - */ -signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch); - -/** - * Provides a set of barrier nodes for a guard that validates an expression. - * - * This is expected to be used in `isBarrier`/`isSanitizer` definitions - * in data flow and taint tracking. - */ -module BarrierGuard { - /** Gets a node that is safely guarded by the given guard check. */ - ExprNode getABarrierNode() { - exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge | - e = value.getAnInstruction().getConvertedResultExpression() and - result.getConvertedExpr() = e and - guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and - g.controls(getBasicBlock(result), edge) - ) - } -} - -/** - * Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`. - */ -signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction instr, boolean branch); - -/** - * Provides a set of barrier nodes for a guard that validates an instruction. - * - * This is expected to be used in `isBarrier`/`isSanitizer` definitions - * in data flow and taint tracking. - */ -module InstructionBarrierGuard { - /** Gets a node that is safely guarded by the given guard check. */ - ExprNode getABarrierNode() { - exists(IRGuardCondition g, ValueNumber value, boolean edge | - instructionGuardChecks(g, value.getAnInstruction(), edge) and - result.asInstruction() = value.getAnInstruction() and - g.controls(result.asInstruction().getBlock(), edge) - ) - } -} - -/** - * DEPRECATED: Use `BarrierGuard` module instead. - * - * A guard that validates some instruction. - * - * To use this in a configuration, extend the class and provide a - * characteristic predicate precisely specifying the guard, and override - * `checks` to specify what is being validated and in which branch. - * - * It is important that all extending classes in scope are disjoint. - */ -deprecated class BarrierGuard extends IRGuardCondition { - /** Override this predicate to hold if this guard validates `instr` upon evaluating to `b`. */ - predicate checksInstr(Instruction instr, boolean b) { none() } - - /** Override this predicate to hold if this guard validates `expr` upon evaluating to `b`. */ - predicate checks(Expr e, boolean b) { none() } - - /** Gets a node guarded by this guard. */ - final Node getAGuardedNode() { - exists(ValueNumber value, boolean edge | - ( - this.checksInstr(value.getAnInstruction(), edge) - or - this.checks(value.getAnInstruction().getConvertedResultExpression(), edge) - ) and - result.asInstruction() = value.getAnInstruction() and - this.controls(result.asInstruction().getBlock(), edge) - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll deleted file mode 100644 index 27edf7ce02c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Provides predicates for mapping the `FunctionInput` and `FunctionOutput` - * classes used in function models to the corresponding instructions. - */ - -private import semmle.code.cpp.ir.IR -private import experimental.semmle.code.cpp.ir.dataflow.DataFlow -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import SsaInternals as Ssa - -/** - * Gets the instruction that goes into `input` for `call`. - */ -DataFlow::Node callInput(CallInstruction call, FunctionInput input) { - // An argument or qualifier - exists(int index | - result.asOperand() = call.getArgumentOperand(index) and - input.isParameterOrQualifierAddress(index) - ) - or - // A value pointed to by an argument or qualifier - exists(int index, int indirectionIndex | - hasOperandAndIndex(result, call.getArgumentOperand(index), indirectionIndex) and - input.isParameterDerefOrQualifierObject(index, indirectionIndex) - ) - or - exists(int ind | - result = getIndirectReturnOutNode(call, ind) and - input.isReturnValueDeref(ind) - ) -} - -/** - * Gets the instruction that holds the `output` for `call`. - */ -Node callOutput(CallInstruction call, FunctionOutput output) { - // The return value - result.asInstruction() = call and - output.isReturnValue() - or - // The side effect of a call on the value pointed to by an argument or qualifier - exists(int index, int indirectionIndex | - result.(IndirectArgumentOutNode).getArgumentIndex() = index and - result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and - result.(IndirectArgumentOutNode).getCallInstruction() = call and - output.isParameterDerefOrQualifierObject(index, indirectionIndex) - ) - or - exists(int ind | - result = getIndirectReturnOutNode(call, ind) and - output.isReturnValueDeref(ind) - ) -} - -DataFlow::Node callInput(CallInstruction call, FunctionInput input, int d) { - exists(DataFlow::Node n | n = callInput(call, input) and d > 0 | - // An argument or qualifier - hasOperandAndIndex(result, n.asOperand(), d) - or - exists(Operand operand, int indirectionIndex | - // A value pointed to by an argument or qualifier - hasOperandAndIndex(n, operand, indirectionIndex) and - hasOperandAndIndex(result, operand, indirectionIndex + d) - ) - ) -} - -private IndirectReturnOutNode getIndirectReturnOutNode(CallInstruction call, int d) { - result.getCallInstruction() = call and - result.getIndirectionIndex() = d -} - -/** - * Gets the instruction that holds the `output` for `call`. - */ -bindingset[d] -Node callOutput(CallInstruction call, FunctionOutput output, int d) { - exists(DataFlow::Node n | n = callOutput(call, output) and d > 0 | - // The return value - result = getIndirectReturnOutNode(n.asInstruction(), d) - or - // If there isn't an indirect out node for the call with indirection `d` then - // we conflate this with the underlying `CallInstruction`. - not exists(getIndirectReturnOutNode(call, d)) and - n.asInstruction() = result.asInstruction() - or - // The side effect of a call on the value pointed to by an argument or qualifier - exists(Operand operand, int indirectionIndex | - Ssa::outNodeHasAddressAndIndex(n, operand, indirectionIndex) and - Ssa::outNodeHasAddressAndIndex(result, operand, indirectionIndex + d) - ) - ) -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll deleted file mode 100644 index a14b2b00651..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll +++ /dev/null @@ -1,136 +0,0 @@ -private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow -private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import PrintIRUtilities - -/** - * Gets the local dataflow from other nodes in the same function to this node. - */ -private string getFromFlow(DataFlow::Node useNode, int order1, int order2) { - exists(DataFlow::Node defNode, string prefix | - ( - simpleLocalFlowStep(defNode, useNode) and prefix = "" - or - any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and - defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and - prefix = "+" - ) and - if defNode.asInstruction() = useNode.asOperand().getAnyDef() - then - // Shorthand for flow from the def of this operand. - result = prefix + "def" and - order1 = -1 and - order2 = 0 - else - if defNode.asOperand().getUse() = useNode.asInstruction() - then - // Shorthand for flow from an operand of this instruction - result = prefix + defNode.asOperand().getDumpId() and - order1 = -1 and - order2 = defNode.asOperand().getDumpSortOrder() - else result = prefix + nodeId(defNode, order1, order2) - ) -} - -/** - * Gets the local dataflow from this node to other nodes in the same function. - */ -private string getToFlow(DataFlow::Node defNode, int order1, int order2) { - exists(DataFlow::Node useNode, string prefix | - ( - simpleLocalFlowStep(defNode, useNode) and prefix = "" - or - any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and - defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and - prefix = "+" - ) and - if useNode.asInstruction() = defNode.asOperand().getUse() - then - // Shorthand for flow to this operand's instruction. - result = prefix + "result" and - order1 = -1 and - order2 = 0 - else result = prefix + nodeId(useNode, order1, order2) - ) -} - -/** - * Gets the properties of the dataflow node `node`. - */ -private string getNodeProperty(DataFlow::Node node, string key) { - // List dataflow into and out of this node. Flow into this node is printed as `src->@`, and flow - // out of this node is printed as `@->dest`. - key = "flow" and - result = - strictconcat(string flow, boolean to, int order1, int order2 | - flow = getFromFlow(node, order1, order2) + "->@" and to = false - or - flow = "@->" + getToFlow(node, order1, order2) and to = true - | - flow, ", " order by to, order1, order2, flow - ) - or - // Is this node a dataflow sink? - key = "sink" and - any(DataFlow::Configuration cfg).isSink(node) and - result = "true" - or - // Is this node a dataflow source? - key = "source" and - any(DataFlow::Configuration cfg).isSource(node) and - result = "true" - or - // Is this node a dataflow barrier, and if so, what kind? - key = "barrier" and - result = - strictconcat(string kind | - any(DataFlow::Configuration cfg).isBarrier(node) and kind = "full" - or - any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in" - or - any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out" - | - kind, ", " - ) - or - // Is there partial flow from a source to this node? - // This property will only be emitted if partial flow is enabled by overriding - // `DataFlow::Configuration::explorationLimit()`. - key = "pflow" and - result = - strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist, - int order1, int order2 | - any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and - destNode.getNode() = node and - // Only print flow from a source in the same function. - sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable() - | - nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", " - order by - order1, order2, dist desc - ) -} - -/** - * Property provider for local IR dataflow. - */ -class LocalFlowPropertyProvider extends IRPropertyProvider { - override string getOperandProperty(Operand operand, string key) { - exists(DataFlow::Node node | - operand = node.asOperand() and - result = getNodeProperty(node, key) - ) - } - - override string getInstructionProperty(Instruction instruction, string key) { - exists(DataFlow::Node node | - instruction = node.asInstruction() and - result = getNodeProperty(node, key) - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll deleted file mode 100644 index 8c318216217..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRStoreSteps.qll +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Print the dataflow local store steps in IR dumps. - */ - -private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow -private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate -private import PrintIRUtilities - -/** - * Property provider for local IR dataflow store steps. - */ -class LocalFlowPropertyProvider extends IRPropertyProvider { - override string getInstructionProperty(Instruction instruction, string key) { - exists(DataFlow::Node objectNode, Content content | - key = "content[" + content.toString() + "]" and - instruction = objectNode.asInstruction() and - result = - strictconcat(string element, DataFlow::Node fieldNode | - storeStep(fieldNode, content, objectNode) and - element = nodeId(fieldNode, _, _) - | - element, ", " - ) - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll deleted file mode 100644 index 5fc15cf986c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/PrintIRUtilities.qll +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Shared utilities used when printing dataflow annotations in IR dumps. - */ - -private import cpp -// The `ValueNumbering` library has to be imported right after `cpp` to ensure -// that the cached IR gets the same checksum here as it does in queries that use -// `ValueNumbering` without `DataFlow`. -private import semmle.code.cpp.ir.ValueNumbering -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.dataflow.DataFlow - -/** - * Gets a short ID for an IR dataflow node. - * - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`). - * - For `Operand`s, this is the label of the operand, prefixed with the result ID of the - * instruction and a dot (e.g. `m128.left`). - * - For `Variable`s, this is the qualified name of the variable. - */ -string nodeId(DataFlow::Node node, int order1, int order2) { - exists(Instruction instruction | instruction = node.asInstruction() | - result = instruction.getResultId() and - order1 = instruction.getBlock().getDisplayIndex() and - order2 = instruction.getDisplayIndexInBlock() - ) - or - exists(Operand operand, Instruction instruction | - operand = node.asOperand() and - instruction = operand.getUse() - | - result = instruction.getResultId() + "." + operand.getDumpId() and - order1 = instruction.getBlock().getDisplayIndex() and - order2 = instruction.getDisplayIndexInBlock() - ) - or - result = "var(" + node.asVariable().getQualifiedName() + ")" and - order1 = 1000000 and - order2 = 0 -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll deleted file mode 100644 index 57487c21b4c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ /dev/null @@ -1,552 +0,0 @@ -private import codeql.ssa.Ssa as SsaImplCommon -private import semmle.code.cpp.ir.IR -private import DataFlowUtil -private import DataFlowImplCommon as DataFlowImplCommon -private import semmle.code.cpp.models.interfaces.Allocation as Alloc -private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow -private import semmle.code.cpp.ir.internal.IRCppLanguage -private import DataFlowPrivate -private import ssa0.SsaInternals as SsaInternals0 -import SsaInternalsCommon - -private module SourceVariables { - int getMaxIndirectionForIRVariable(IRVariable var) { - exists(Type type, boolean isGLValue | - var.getLanguageType().hasType(type, isGLValue) and - if isGLValue = true - then result = 1 + getMaxIndirectionsForType(type) - else result = getMaxIndirectionsForType(type) - ) - } - - class BaseSourceVariable = SsaInternals0::BaseSourceVariable; - - class BaseIRVariable = SsaInternals0::BaseIRVariable; - - class BaseCallVariable = SsaInternals0::BaseCallVariable; - - cached - private newtype TSourceVariable = - TSourceIRVariable(BaseIRVariable baseVar, int ind) { - ind = [0 .. getMaxIndirectionForIRVariable(baseVar.getIRVariable())] - } or - TCallVariable(AllocationInstruction call, int ind) { - ind = [0 .. countIndirectionsForCppType(getResultLanguageType(call))] - } - - abstract class SourceVariable extends TSourceVariable { - int ind; - - bindingset[ind] - SourceVariable() { any() } - - abstract string toString(); - - int getIndirection() { result = ind } - - abstract BaseSourceVariable getBaseVariable(); - } - - class SourceIRVariable extends SourceVariable, TSourceIRVariable { - BaseIRVariable var; - - SourceIRVariable() { this = TSourceIRVariable(var, ind) } - - IRVariable getIRVariable() { result = var.getIRVariable() } - - override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() } - - override string toString() { - ind = 0 and - result = this.getIRVariable().toString() - or - ind > 0 and - result = this.getIRVariable().toString() + " indirection" - } - } - - class CallVariable extends SourceVariable, TCallVariable { - AllocationInstruction call; - - CallVariable() { this = TCallVariable(call, ind) } - - AllocationInstruction getCall() { result = call } - - override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call } - - override string toString() { - ind = 0 and - result = "Call" - or - ind > 0 and - result = "Call indirection" - } - } -} - -import SourceVariables - -predicate hasIndirectOperand(Operand op, int indirectionIndex) { - exists(CppType type, int m | - not ignoreOperand(op) and - type = getLanguageType(op) and - m = countIndirectionsForCppType(type) and - indirectionIndex = [1 .. m] - ) -} - -predicate hasIndirectInstruction(Instruction instr, int indirectionIndex) { - exists(CppType type, int m | - not ignoreInstruction(instr) and - type = getResultLanguageType(instr) and - m = countIndirectionsForCppType(type) and - indirectionIndex = [1 .. m] - ) -} - -cached -private newtype TDefOrUseImpl = - TDefImpl(Operand address, int indirectionIndex) { - isDef(_, _, address, _, _, indirectionIndex) and - // We only include the definition if the SSA pruning stage - // concluded that the definition is live after the write. - any(SsaInternals0::Def def).getAddressOperand() = address - } or - TUseImpl(Operand operand, int indirectionIndex) { - isUse(_, operand, _, _, indirectionIndex) and - not isDef(_, _, operand, _, _, _) - } - -abstract private class DefOrUseImpl extends TDefOrUseImpl { - /** Gets a textual representation of this element. */ - abstract string toString(); - - /** Gets the block of this definition or use. */ - abstract IRBlock getBlock(); - - /** Holds if this definition or use has index `index` in block `block`. */ - abstract predicate hasIndexInBlock(IRBlock block, int index); - - final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { - this.hasIndexInBlock(block, index) and - sv = this.getSourceVariable() - } - - /** Gets the location of this element. */ - abstract Cpp::Location getLocation(); - - /** - * Gets the index (i.e., the number of loads required) of this - * definition or use. - * - * Note that this is _not_ the definition's (or use's) index in - * the enclosing basic block. To obtain this index, use - * `DefOrUseImpl::hasIndexInBlock/2` or `DefOrUseImpl::hasIndexInBlock/3`. - */ - abstract int getIndirectionIndex(); - - /** - * Gets the instruction that computes the base of this definition or use. - * This is always a `VariableAddressInstruction` or an `AllocationInstruction`. - */ - abstract Instruction getBase(); - - final BaseSourceVariable getBaseSourceVariable() { - exists(IRVariable var | - result.(BaseIRVariable).getIRVariable() = var and - instructionHasIRVariable(this.getBase(), var) - ) - or - result.(BaseCallVariable).getCallInstruction() = this.getBase() - } - - /** Gets the variable that is defined or used. */ - final SourceVariable getSourceVariable() { - exists(BaseSourceVariable v, int ind | - sourceVariableHasBaseAndIndex(result, v, ind) and - defOrUseHasSourceVariable(this, v, ind) - ) - } -} - -pragma[noinline] -private predicate instructionHasIRVariable(VariableAddressInstruction vai, IRVariable var) { - vai.getIRVariable() = var -} - -private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv, int ind) { - defHasSourceVariable(defOrUse, bv, ind) - or - useHasSourceVariable(defOrUse, bv, ind) -} - -pragma[noinline] -private predicate defHasSourceVariable(DefImpl def, BaseSourceVariable bv, int ind) { - bv = def.getBaseSourceVariable() and - ind = def.getIndirection() -} - -pragma[noinline] -private predicate useHasSourceVariable(UseImpl use, BaseSourceVariable bv, int ind) { - bv = use.getBaseSourceVariable() and - ind = use.getIndirection() -} - -pragma[noinline] -private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVariable bv, int ind) { - v.getBaseVariable() = bv and - v.getIndirection() = ind -} - -class DefImpl extends DefOrUseImpl, TDefImpl { - Operand address; - int ind; - - DefImpl() { this = TDefImpl(address, ind) } - - override Instruction getBase() { isDef(_, _, address, result, _, _) } - - Operand getAddressOperand() { result = address } - - int getIndirection() { isDef(_, _, address, _, result, ind) } - - override int getIndirectionIndex() { result = ind } - - Instruction getDefiningInstruction() { isDef(_, result, address, _, _, _) } - - override string toString() { result = "DefImpl" } - - override IRBlock getBlock() { result = this.getDefiningInstruction().getBlock() } - - override Cpp::Location getLocation() { result = this.getDefiningInstruction().getLocation() } - - final override predicate hasIndexInBlock(IRBlock block, int index) { - this.getDefiningInstruction() = block.getInstruction(index) - } - - predicate isCertain() { isDef(true, _, address, _, _, ind) } -} - -class UseImpl extends DefOrUseImpl, TUseImpl { - Operand operand; - int ind; - - UseImpl() { this = TUseImpl(operand, ind) } - - Operand getOperand() { result = operand } - - override string toString() { result = "UseImpl" } - - final override predicate hasIndexInBlock(IRBlock block, int index) { - operand.getUse() = block.getInstruction(index) - } - - final override IRBlock getBlock() { result = operand.getUse().getBlock() } - - final override Cpp::Location getLocation() { result = operand.getLocation() } - - final int getIndirection() { isUse(_, operand, _, result, ind) } - - override int getIndirectionIndex() { result = ind } - - override Instruction getBase() { isUse(_, operand, result, _, ind) } - - predicate isCertain() { isUse(true, operand, _, _, ind) } -} - -/** - * Holds if `defOrUse1` is a definition which is first read by `use`, - * or if `defOrUse1` is a use and `use` is a next subsequent use. - * - * In both cases, `use` can either be an explicit use written in the - * source file, or it can be a phi node as computed by the SSA library. - */ -predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) { - exists(IRBlock bb1, int i1, SourceVariable v | - defOrUse1.asDefOrUse().hasIndexInBlock(bb1, i1, v) - | - exists(IRBlock bb2, int i2 | - adjacentDefRead(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1), - pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) - | - use.asDefOrUse().(UseImpl).hasIndexInBlock(bb2, i2, v) - ) - or - exists(PhiNode phi | - lastRefRedef(_, bb1, i1, phi) and - use.asPhi() = phi and - phi.getSourceVariable() = pragma[only_bind_into](v) - ) - ) -} - -private predicate useToNode(UseOrPhi use, Node nodeTo) { - exists(UseImpl useImpl | - useImpl = use.asDefOrUse() and - nodeHasOperand(nodeTo, useImpl.getOperand(), useImpl.getIndirectionIndex()) - ) - or - nodeTo.(SsaPhiNode).getPhiNode() = use.asPhi() -} - -pragma[noinline] -predicate outNodeHasAddressAndIndex( - IndirectArgumentOutNode out, Operand address, int indirectionIndex -) { - out.getAddressOperand() = address and - out.getIndirectionIndex() = indirectionIndex -} - -private predicate defToNode(Node nodeFrom, Def def) { - nodeHasInstruction(nodeFrom, def.getDefiningInstruction(), def.getIndirectionIndex()) -} - -/** - * INTERNAL: Do not use. - * - * Holds if `nodeFrom` is the node that correspond to the definition or use `defOrUse`. - */ -predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse) { - // Node -> Def - defToNode(nodeFrom, defOrUse) - or - // Node -> Use - useToNode(defOrUse, nodeFrom) -} - -/** - * Perform a single conversion-like step from `nFrom` to `nTo`. This relation - * only holds when there is no use-use relation out of `nTo`. - */ -private predicate indirectConversionFlowStep(Node nFrom, Node nTo) { - not exists(UseOrPhi defOrUse | - nodeToDefOrUse(nTo, defOrUse) and - adjacentDefRead(defOrUse, _) - ) and - exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr | - hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and - hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and - instr = op2.getDef() and - conversionFlow(op1, instr, _) - ) -} - -/** - * The reason for this predicate is a bit annoying: - * We cannot mark a `PointerArithmeticInstruction` that computes an offset based on some SSA - * variable `x` as a use of `x` since this creates taint-flow in the following example: - * ```c - * int x = array[source] - * sink(*array) - * ``` - * This is because `source` would flow from the operand of `PointerArithmeticInstruction` to the - * result of the instruction, and into the `IndirectOperand` that represents the value of `*array`. - * Then, via use-use flow, flow will arrive at `*array` in `sink(*array)`. - * - * So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the - * first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`. - */ -private predicate adjustForPointerArith(Node nodeFrom, UseOrPhi use) { - nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and - exists(DefOrUse defOrUse, Node adjusted | - indirectConversionFlowStep*(adjusted, nodeFrom) and - nodeToDefOrUse(adjusted, defOrUse) and - adjacentDefRead(defOrUse, use) - ) -} - -/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */ -predicate ssaFlow(Node nodeFrom, Node nodeTo) { - // `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith. - exists(UseOrPhi use | - adjustForPointerArith(nodeFrom, use) and - useToNode(use, nodeTo) - ) - or - not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and - exists(DefOrUse defOrUse1, UseOrPhi use | - nodeToDefOrUse(nodeFrom, defOrUse1) and - adjacentDefRead(defOrUse1, use) and - useToNode(use, nodeTo) - ) -} - -/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */ -predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) { - exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use | - phi = nodeFrom.getPhiNode() and - phi.definesAt(sv, bb1, i1) and - useToNode(use, nodeTo) - | - exists(IRBlock bb2, int i2 | - use.asDefOrUse().hasIndexInBlock(bb2, i2, sv) and - adjacentDefRead(phi, bb1, i1, bb2, i2) - ) - or - exists(PhiNode phiTo | - lastRefRedef(phi, _, _, phiTo) and - nodeTo.(SsaPhiNode).getPhiNode() = phiTo - ) - ) -} - -private SsaInternals0::SourceVariable getOldSourceVariable(SourceVariable v) { - v.getBaseVariable().(BaseIRVariable).getIRVariable() = - result.getBaseVariable().(SsaInternals0::BaseIRVariable).getIRVariable() - or - v.getBaseVariable().(BaseCallVariable).getCallInstruction() = - result.getBaseVariable().(SsaInternals0::BaseCallVariable).getCallInstruction() -} - -/** - * Holds if there is a write at index `i` in basic block `bb` to variable `v` that's - * subsequently read (as determined by the SSA pruning stage). - */ -private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) { - exists(SsaInternals0::Def def, SsaInternals0::SourceVariable v0 | - def.asDefOrUse().hasIndexInBlock(bb, i, v0) and - v0 = getOldSourceVariable(v) - ) -} - -private module SsaInput implements SsaImplCommon::InputSig { - import InputSigCommon - import SourceVariables - - /** - * Holds if the `i`'th write in block `bb` writes to the variable `v`. - * `certain` is `true` if the write is guaranteed to overwrite the entire variable. - */ - predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) { - DataFlowImplCommon::forceCachingInSameStage() and - variableWriteCand(bb, i, v) and - exists(DefImpl def | def.hasIndexInBlock(bb, i, v) | - if def.isCertain() then certain = true else certain = false - ) - } - - /** - * Holds if the `i`'th read in block `bb` reads to the variable `v`. - * `certain` is `true` if the read is guaranteed. For C++, this is always the case. - */ - predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) { - exists(UseImpl use | use.hasIndexInBlock(bb, i, v) | - if use.isCertain() then certain = true else certain = false - ) - } -} - -/** - * The final SSA predicates used for dataflow purposes. - */ -cached -module SsaCached { - /** - * 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`. - */ - cached - predicate adjacentDefRead(Definition def, IRBlock bb1, int i1, IRBlock bb2, int i2) { - SsaImpl::adjacentDefRead(def, bb1, i1, bb2, i2) - } - - /** - * 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. - */ - cached - predicate lastRefRedef(Definition def, IRBlock bb, int i, Definition next) { - SsaImpl::lastRefRedef(def, bb, i, next) - } -} - -cached -private newtype TSsaDefOrUse = - TDefOrUse(DefOrUseImpl defOrUse) { - defOrUse instanceof UseImpl - or - // Like in the pruning stage, we only include definition that's live after the - // write as the final definitions computed by SSA. - exists(Definition def, SourceVariable sv, IRBlock bb, int i | - def.definesAt(sv, bb, i) and - defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv) - ) - } or - TPhi(PhiNode phi) - -abstract private class SsaDefOrUse extends TSsaDefOrUse { - string toString() { none() } - - DefOrUseImpl asDefOrUse() { none() } - - PhiNode asPhi() { none() } - - abstract Location getLocation(); -} - -class DefOrUse extends TDefOrUse, SsaDefOrUse { - DefOrUseImpl defOrUse; - - DefOrUse() { this = TDefOrUse(defOrUse) } - - final override DefOrUseImpl asDefOrUse() { result = defOrUse } - - final override Location getLocation() { result = defOrUse.getLocation() } - - final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() } - - override string toString() { result = defOrUse.toString() } -} - -class Phi extends TPhi, SsaDefOrUse { - PhiNode phi; - - Phi() { this = TPhi(phi) } - - final override PhiNode asPhi() { result = phi } - - final override Location getLocation() { result = phi.getBasicBlock().getLocation() } - - override string toString() { result = "Phi" } -} - -class UseOrPhi extends SsaDefOrUse { - UseOrPhi() { - this.asDefOrUse() instanceof UseImpl - or - this instanceof Phi - } - - final override Location getLocation() { - result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation() - } -} - -class Def extends DefOrUse { - override DefImpl defOrUse; - - Operand getAddressOperand() { result = defOrUse.getAddressOperand() } - - Instruction getAddress() { result = this.getAddressOperand().getDef() } - - /** - * This predicate ensures that joins go from `defOrUse` to the result - * instead of the other way around. - */ - pragma[inline] - int getIndirectionIndex() { - pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirectionIndex() - } - - Instruction getDefiningInstruction() { result = defOrUse.getDefiningInstruction() } -} - -private module SsaImpl = SsaImplCommon::Make; - -class PhiNode = SsaImpl::PhiNode; - -class Definition = SsaImpl::Definition; - -import SsaCached diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll deleted file mode 100644 index 2e0a20fcfdc..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll +++ /dev/null @@ -1,270 +0,0 @@ -import cpp as Cpp -import semmle.code.cpp.ir.IR -import semmle.code.cpp.ir.internal.IRCppLanguage -private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects -private import DataFlowImplCommon as DataFlowImplCommon -private import DataFlowUtil - -/** - * Holds if `operand` is an operand that is not used by the dataflow library. - * Ignored operands are not recognizd as uses by SSA, and they don't have a - * corresponding `(Indirect)OperandNode`. - */ -predicate ignoreOperand(Operand operand) { - operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or - operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or - operand instanceof MemoryOperand -} - -/** - * Holds if `instr` is an instruction that is not used by the dataflow library. - * Ignored instructions are not recognized as reads/writes by SSA, and they - * don't have a corresponding `(Indirect)InstructionNode`. - */ -predicate ignoreInstruction(Instruction instr) { - DataFlowImplCommon::forceCachingInSameStage() and - ( - instr instanceof WriteSideEffectInstruction or - instr instanceof PhiInstruction or - instr instanceof ReadSideEffectInstruction or - instr instanceof ChiInstruction or - instr instanceof InitializeIndirectionInstruction - ) -} - -/** - * Gets the C++ type of `this` in the member function `f`. - * The result is a glvalue if `isGLValue` is true, and - * a prvalue if `isGLValue` is false. - */ -bindingset[isGLValue] -private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) { - result.hasType(f.getTypeOfThis(), isGLValue) -} - -/** - * Gets the C++ type of the instruction `i`. - * - * This is equivalent to `i.getResultLanguageType()` with the exception - * of instructions that directly references a `this` IRVariable. In this - * case, `i.getResultLanguageType()` gives an unknown type, whereas the - * predicate gives the expected type (i.e., a potentially cv-qualified - * type `A*` where `A` is the declaring type of the member function that - * contains `i`). - */ -cached -CppType getResultLanguageType(Instruction i) { - if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable - then - if i.isGLValue() - then result = getThisType(i.getEnclosingFunction(), true) - else result = getThisType(i.getEnclosingFunction(), false) - else result = i.getResultLanguageType() -} - -/** - * Gets the C++ type of the operand `operand`. - * This is equivalent to the type of the operand's defining instruction. - * - * See `getResultLanguageType` for a description of this behavior. - */ -CppType getLanguageType(Operand operand) { result = getResultLanguageType(operand.getDef()) } - -/** - * Gets the maximum number of indirections a glvalue of type `type` can have. - * For example: - * - If `type = int`, the result is 1 - * - If `type = MyStruct`, the result is 1 - * - If `type = char*`, the result is 2 - */ -int getMaxIndirectionsForType(Type type) { - result = countIndirectionsForCppType(getTypeForGLValue(type)) -} - -/** - * Gets the maximum number of indirections a value of type `type` can have. - * - * Note that this predicate is intended to be called on unspecified types - * (i.e., `countIndirections(e.getUnspecifiedType())`). - */ -private int countIndirections(Type t) { - result = - 1 + - countIndirections([t.(Cpp::PointerType).getBaseType(), t.(Cpp::ReferenceType).getBaseType()]) - or - not t instanceof Cpp::PointerType and - not t instanceof Cpp::ReferenceType and - result = 0 -} - -/** - * Gets the maximum number of indirections a value of C++ - * type `langType` can have. - */ -int countIndirectionsForCppType(LanguageType langType) { - exists(Type type | langType.hasType(type, true) | - result = 1 + countIndirections(type.getUnspecifiedType()) - ) - or - exists(Type type | langType.hasType(type, false) | - result = countIndirections(type.getUnspecifiedType()) - ) -} - -/** - * A `CallInstruction` that calls an allocation function such - * as `malloc` or `operator new`. - */ -class AllocationInstruction extends CallInstruction { - AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction } -} - -/** - * Holds if `i` is a base instruction that starts a sequence of uses - * of some variable that SSA can handle. - * - * This is either when `i` is a `VariableAddressInstruction` or when - * `i` is a fresh allocation produced by an `AllocationInstruction`. - */ -private predicate isSourceVariableBase(Instruction i) { - i instanceof VariableAddressInstruction or i instanceof AllocationInstruction -} - -/** - * Holds if the value pointed to by `operand` can potentially be - * modified be the caller. - */ -predicate isModifiableByCall(ArgumentOperand operand) { - exists(CallInstruction call, int index, CppType type | - type = getLanguageType(operand) and - call.getArgumentOperand(index) = operand and - if index = -1 - then not call.getStaticCallTarget() instanceof Cpp::ConstMemberFunction - else not SideEffects::isConstPointerLike(any(Type t | type.hasType(t, _))) - ) -} - -cached -private module Cached { - /** - * Holds if `op` is a use of an SSA variable rooted at `base` with `ind` number - * of indirections. - * - * `certain` is `true` if the operand is guaranteed to read the variable, and - * `indirectionIndex` specifies the number of loads required to read the variable. - */ - cached - predicate isUse(boolean certain, Operand op, Instruction base, int ind, int indirectionIndex) { - not ignoreOperand(op) and - certain = true and - exists(LanguageType type, int m, int ind0 | - type = getLanguageType(op) and - m = countIndirectionsForCppType(type) and - isUseImpl(op, base, ind0) and - ind = ind0 + [0 .. m] and - indirectionIndex = ind - ind0 - ) - } - - /** - * Holds if `operand` is a use of an SSA variable rooted at `base`, and the - * path from `base` to `operand` passes through `ind` load-like instructions. - */ - private predicate isUseImpl(Operand operand, Instruction base, int ind) { - DataFlowImplCommon::forceCachingInSameStage() and - ind = 0 and - operand.getDef() = base and - isSourceVariableBase(base) - or - exists(Operand mid, Instruction instr | - isUseImpl(mid, base, ind) and - instr = operand.getDef() and - conversionFlow(mid, instr, false) - ) - or - exists(int ind0 | - isUseImpl(operand.getDef().(LoadInstruction).getSourceAddressOperand(), base, ind0) - or - isUseImpl(operand.getDef().(InitializeParameterInstruction).getAnOperand(), base, ind0) - | - ind0 = ind - 1 - ) - } - - /** - * Holds if `address` is an address of an SSA variable rooted at `base`, - * and `instr` is a definition of the SSA variable with `ind` number of indirections. - * - * `certain` is `true` if `instr` is guaranteed to write to the variable, and - * `indirectionIndex` specifies the number of loads required to read the variable - * after the write operation. - */ - cached - predicate isDef( - boolean certain, Instruction instr, Operand address, Instruction base, int ind, - int indirectionIndex - ) { - certain = true and - exists(int ind0, CppType type, int m | - address = - [ - instr.(StoreInstruction).getDestinationAddressOperand(), - instr.(InitializeParameterInstruction).getAnOperand(), - instr.(InitializeDynamicAllocationInstruction).getAllocationAddressOperand(), - instr.(UninitializedInstruction).getAnOperand() - ] - | - isDefImpl(address, base, ind0) and - type = getLanguageType(address) and - m = countIndirectionsForCppType(type) and - ind = ind0 + [1 .. m] and - indirectionIndex = ind - (ind0 + 1) - ) - } - - /** - * Holds if `address` is a use of an SSA variable rooted at `base`, and the - * path from `base` to `address` passes through `ind` load-like instructions. - * - * Note: Unlike `isUseImpl`, this predicate recurses through pointer-arithmetic - * instructions. - */ - private predicate isDefImpl(Operand address, Instruction base, int ind) { - DataFlowImplCommon::forceCachingInSameStage() and - ind = 0 and - address.getDef() = base and - isSourceVariableBase(base) - or - exists(Operand mid, Instruction instr | - isDefImpl(mid, base, ind) and - instr = address.getDef() and - conversionFlow(mid, instr, _) - ) - or - exists(int ind0 | - isDefImpl(address.getDef().(LoadInstruction).getSourceAddressOperand(), base, ind0) - or - isDefImpl(address.getDef().(InitializeParameterInstruction).getAnOperand(), base, ind0) - | - ind0 = ind - 1 - ) - } -} - -import Cached - -/** - * Inputs to the shared SSA library's parameterized module that is shared - * between the SSA pruning stage, and the final SSA stage. - */ -module InputSigCommon { - class BasicBlock = IRBlock; - - BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) } - - BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } - - class ExitBasicBlock extends IRBlock { - ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction } - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll deleted file mode 100644 index 1ab232923bf..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ /dev/null @@ -1,208 +0,0 @@ -private import semmle.code.cpp.ir.IR -private import experimental.semmle.code.cpp.ir.dataflow.DataFlow -private import ModelUtil -private import semmle.code.cpp.models.interfaces.DataFlow -private import semmle.code.cpp.models.interfaces.SideEffect -private import DataFlowUtil -private import DataFlowPrivate -private import semmle.code.cpp.models.Models - -/** - * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local - * (intra-procedural) step. - */ -predicate localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - DataFlow::localFlowStep(nodeFrom, nodeTo) - or - localAdditionalTaintStep(nodeFrom, nodeTo) -} - -/** - * Holds if taint can flow in one local step from `nodeFrom` to `nodeTo` excluding - * local data flow steps. That is, `nodeFrom` and `nodeTo` are likely to represent - * different objects. - */ -cached -predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { - operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) - or - modeledTaintStep(nodeFrom, nodeTo) - or - // Flow from `op` to `*op`. - exists(Operand operand, int indirectionIndex | - nodeHasOperand(nodeFrom, operand, indirectionIndex) and - nodeHasOperand(nodeTo, operand, indirectionIndex - 1) - ) - or - // Flow from `instr` to `*instr`. - exists(Instruction instr, int indirectionIndex | - nodeHasInstruction(nodeFrom, instr, indirectionIndex) and - nodeHasInstruction(nodeTo, instr, indirectionIndex - 1) - ) - or - // Flow from (the indirection of) an operand of a pointer arithmetic instruction to the - // indirection of the pointer arithmetic instruction. This provides flow from `source` - // in `x[source]` to the result of the associated load instruction. - exists(PointerArithmeticInstruction pai, int indirectionIndex | - nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and - hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1) - ) -} - -/** - * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local - * (intra-procedural) step. - */ -private predicate operandToInstructionTaintStep(Operand opFrom, Instruction instrTo) { - // Taint can flow through expressions that alter the value but preserve - // more than one bit of it _or_ expressions that follow data through - // pointer indirections. - instrTo.getAnOperand() = opFrom and - ( - instrTo instanceof ArithmeticInstruction - or - instrTo instanceof BitwiseInstruction - or - instrTo instanceof PointerArithmeticInstruction - ) - or - // The `CopyInstruction` case is also present in non-taint data flow, but - // that uses `getDef` rather than `getAnyDef`. For taint, we want flow - // from a definition of `myStruct` to a `myStruct.myField` expression. - instrTo.(LoadInstruction).getSourceAddressOperand() = opFrom - or - // Unary instructions tend to preserve enough information in practice that we - // want taint to flow through. - // The exception is `FieldAddressInstruction`. Together with the rules below for - // `LoadInstruction`s and `ChiInstruction`s, flow through `FieldAddressInstruction` - // could cause flow into one field to come out an unrelated field. - // This would happen across function boundaries, where the IR would not be able to - // match loads to stores. - instrTo.(UnaryInstruction).getUnaryOperand() = opFrom and - ( - not instrTo instanceof FieldAddressInstruction - or - instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union - ) -} - -/** - * Holds if taint may propagate from `source` to `sink` in zero or more local - * (intra-procedural) steps. - */ -pragma[inline] -predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } - -/** - * Holds if taint can flow from `i1` to `i2` in zero or more - * local (intra-procedural) steps. - */ -pragma[inline] -predicate localInstructionTaint(Instruction i1, Instruction i2) { - localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2)) -} - -/** - * Holds if taint can flow from `e1` to `e2` in zero or more - * local (intra-procedural) steps. - */ -pragma[inline] -predicate localExprTaint(Expr e1, Expr e2) { - localTaint(DataFlow::exprNode(e1), DataFlow::exprNode(e2)) -} - -/** - * Holds if the additional step from `src` to `sink` should be included in all - * global taint flow configurations. - */ -predicate defaultAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink) { - localAdditionalTaintStep(src, sink) -} - -/** - * Holds if default `TaintTracking::Configuration`s should allow implicit reads - * of `c` at sinks and inputs to additional taint steps. - */ -bindingset[node] -predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { none() } - -/** - * Holds if `node` should be a sanitizer in all global taint flow configurations - * but not in local taint. - */ -predicate defaultTaintSanitizer(DataFlow::Node node) { none() } - -/** - * Holds if taint can flow from `instrIn` to `instrOut` through a call to a - * modeled function. - */ -predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) { - // Normal taint steps - exists(CallInstruction call, TaintFunction func, FunctionInput modelIn, FunctionOutput modelOut | - call.getStaticCallTarget() = func and - func.hasTaintFlow(modelIn, modelOut) - | - ( - nodeIn = callInput(call, modelIn) - or - exists(int n | - modelIn.isParameterDerefOrQualifierObject(n) and - if n = -1 - then nodeIn = callInput(call, any(InQualifierAddress inQualifier)) - else nodeIn = callInput(call, any(InParameter inParam | inParam.getIndex() = n)) - ) - ) and - nodeOut = callOutput(call, modelOut) - or - exists(int d | - nodeIn = callInput(call, modelIn, d) - or - exists(int n | - d = 1 and - modelIn.isParameterDerefOrQualifierObject(n) and - if n = -1 - then nodeIn = callInput(call, any(InQualifierAddress inQualifier)) - else nodeIn = callInput(call, any(InParameter inParam | inParam.getIndex() = n)) - ) - | - call.getStaticCallTarget() = func and - func.hasTaintFlow(modelIn, modelOut) and - nodeOut = callOutput(call, modelOut, d) - ) - ) - or - // Taint flow from one argument to another and data flow from an argument to a - // return value. This happens in functions like `strcat` and `memcpy`. We - // could model this flow in two separate steps, but that would add reverse - // flow from the write side-effect to the call instruction, which may not be - // desirable. - exists( - CallInstruction call, Function func, FunctionInput modelIn, OutParameterDeref modelMidOut, - int indexMid, InParameter modelMidIn, OutReturnValue modelOut - | - nodeIn = callInput(call, modelIn) and - nodeOut = callOutput(call, modelOut) and - call.getStaticCallTarget() = func and - func.(TaintFunction).hasTaintFlow(modelIn, modelMidOut) and - func.(DataFlowFunction).hasDataFlow(modelMidIn, modelOut) and - modelMidOut.isParameterDeref(indexMid) and - modelMidIn.isParameter(indexMid) - ) - or - // Taint flow from a pointer argument to an output, when the model specifies flow from the deref - // to that output, but the deref is not modeled in the IR for the caller. - exists( - CallInstruction call, DataFlow::SideEffectOperandNode indirectArgument, Function func, - FunctionInput modelIn, FunctionOutput modelOut - | - indirectArgument = callInput(call, modelIn) and - indirectArgument.getAddressOperand() = nodeIn.asOperand() and - call.getStaticCallTarget() = func and - ( - func.(DataFlowFunction).hasDataFlow(modelIn, modelOut) - or - func.(TaintFunction).hasTaintFlow(modelIn, modelOut) - ) and - nodeOut = callOutput(call, modelOut) - ) -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll deleted file mode 100644 index 06c4a7f751c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll +++ /dev/null @@ -1,314 +0,0 @@ -/** - * This module defines an initial SSA pruning stage that doesn't take - * indirections into account. - */ - -private import codeql.ssa.Ssa as SsaImplCommon -private import semmle.code.cpp.ir.IR -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon -private import semmle.code.cpp.models.interfaces.Allocation as Alloc -private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow -private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects -private import semmle.code.cpp.ir.internal.IRCppLanguage -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate -private import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowUtil -private import experimental.semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon - -private module SourceVariables { - newtype TBaseSourceVariable = - // Each IR variable gets its own source variable - TBaseIRVariable(IRVariable var) or - // Each allocation gets its own source variable - TBaseCallVariable(AllocationInstruction call) - - abstract class BaseSourceVariable extends TBaseSourceVariable { - abstract string toString(); - - abstract DataFlowType getType(); - } - - class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable { - IRVariable var; - - IRVariable getIRVariable() { result = var } - - BaseIRVariable() { this = TBaseIRVariable(var) } - - override string toString() { result = var.toString() } - - override DataFlowType getType() { result = var.getType() } - } - - class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable { - AllocationInstruction call; - - BaseCallVariable() { this = TBaseCallVariable(call) } - - AllocationInstruction getCallInstruction() { result = call } - - override string toString() { result = call.toString() } - - override DataFlowType getType() { result = call.getResultType() } - } - - private newtype TSourceVariable = - TSourceIRVariable(BaseIRVariable baseVar) or - TCallVariable(AllocationInstruction call) - - abstract class SourceVariable extends TSourceVariable { - abstract string toString(); - - abstract BaseSourceVariable getBaseVariable(); - } - - class SourceIRVariable extends SourceVariable, TSourceIRVariable { - BaseIRVariable var; - - SourceIRVariable() { this = TSourceIRVariable(var) } - - IRVariable getIRVariable() { result = var.getIRVariable() } - - override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() } - - override string toString() { result = this.getIRVariable().toString() } - } - - class CallVariable extends SourceVariable, TCallVariable { - AllocationInstruction call; - - CallVariable() { this = TCallVariable(call) } - - AllocationInstruction getCall() { result = call } - - override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call } - - override string toString() { result = "Call" } - } -} - -import SourceVariables - -private newtype TDefOrUseImpl = - TDefImpl(Operand address) { isDef(_, _, address, _, _, _) } or - TUseImpl(Operand operand) { - isUse(_, operand, _, _, _) and - not isDef(_, _, operand, _, _, _) - } - -abstract private class DefOrUseImpl extends TDefOrUseImpl { - /** Gets a textual representation of this element. */ - abstract string toString(); - - /** Gets the block of this definition or use. */ - abstract IRBlock getBlock(); - - /** Holds if this definition or use has index `index` in block `block`. */ - abstract predicate hasIndexInBlock(IRBlock block, int index); - - final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { - this.hasIndexInBlock(block, index) and - sv = this.getSourceVariable() - } - - /** Gets the location of this element. */ - abstract Cpp::Location getLocation(); - - abstract Instruction getBase(); - - final BaseSourceVariable getBaseSourceVariable() { - exists(IRVariable var | - result.(BaseIRVariable).getIRVariable() = var and - instructionHasIRVariable(this.getBase(), var) - ) - or - result.(BaseCallVariable).getCallInstruction() = this.getBase() - } - - /** Gets the variable that is defined or used. */ - final SourceVariable getSourceVariable() { - exists(BaseSourceVariable v | - sourceVariableHasBaseAndIndex(result, v) and - defOrUseHasSourceVariable(this, v) - ) - } -} - -pragma[noinline] -private predicate instructionHasIRVariable(VariableAddressInstruction vai, IRVariable var) { - vai.getIRVariable() = var -} - -private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv) { - defHasSourceVariable(defOrUse, bv) - or - useHasSourceVariable(defOrUse, bv) -} - -pragma[noinline] -private predicate defHasSourceVariable(DefImpl def, BaseSourceVariable bv) { - bv = def.getBaseSourceVariable() -} - -pragma[noinline] -private predicate useHasSourceVariable(UseImpl use, BaseSourceVariable bv) { - bv = use.getBaseSourceVariable() -} - -pragma[noinline] -private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVariable bv) { - v.getBaseVariable() = bv -} - -class DefImpl extends DefOrUseImpl, TDefImpl { - Operand address; - - DefImpl() { this = TDefImpl(address) } - - override Instruction getBase() { isDef(_, _, address, result, _, _) } - - Operand getAddressOperand() { result = address } - - Instruction getDefiningInstruction() { isDef(_, result, address, _, _, _) } - - override string toString() { result = address.toString() } - - override IRBlock getBlock() { result = this.getDefiningInstruction().getBlock() } - - override Cpp::Location getLocation() { result = this.getDefiningInstruction().getLocation() } - - final override predicate hasIndexInBlock(IRBlock block, int index) { - this.getDefiningInstruction() = block.getInstruction(index) - } - - predicate isCertain() { isDef(true, _, address, _, _, _) } -} - -class UseImpl extends DefOrUseImpl, TUseImpl { - Operand operand; - - UseImpl() { this = TUseImpl(operand) } - - Operand getOperand() { result = operand } - - override string toString() { result = operand.toString() } - - final override predicate hasIndexInBlock(IRBlock block, int index) { - operand.getUse() = block.getInstruction(index) - } - - final override IRBlock getBlock() { result = operand.getUse().getBlock() } - - final override Cpp::Location getLocation() { result = operand.getLocation() } - - override Instruction getBase() { isUse(_, operand, result, _, _) } - - predicate isCertain() { isUse(true, operand, _, _, _) } -} - -private module SsaInput implements SsaImplCommon::InputSig { - import InputSigCommon - import SourceVariables - - /** - * Holds if the `i`'th write in block `bb` writes to the variable `v`. - * `certain` is `true` if the write is guaranteed to overwrite the entire variable. - */ - predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) { - DataFlowImplCommon::forceCachingInSameStage() and - exists(DefImpl def | def.hasIndexInBlock(bb, i, v) | - if def.isCertain() then certain = true else certain = false - ) - } - - /** - * Holds if the `i`'th read in block `bb` reads to the variable `v`. - * `certain` is `true` if the read is guaranteed. - */ - predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) { - exists(UseImpl use | use.hasIndexInBlock(bb, i, v) | - if use.isCertain() then certain = true else certain = false - ) - } -} - -private newtype TSsaDefOrUse = - TDefOrUse(DefOrUseImpl defOrUse) { - defOrUse instanceof UseImpl - or - // If `defOrUse` is a definition we only include it if the - // SSA library concludes that it's live after the write. - exists(Definition def, SourceVariable sv, IRBlock bb, int i | - def.definesAt(sv, bb, i) and - defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv) - ) - } or - TPhi(PhiNode phi) - -abstract private class SsaDefOrUse extends TSsaDefOrUse { - string toString() { result = "SsaDefOrUse" } - - DefOrUseImpl asDefOrUse() { none() } - - PhiNode asPhi() { none() } - - abstract Location getLocation(); -} - -class DefOrUse extends TDefOrUse, SsaDefOrUse { - DefOrUseImpl defOrUse; - - DefOrUse() { this = TDefOrUse(defOrUse) } - - final override DefOrUseImpl asDefOrUse() { result = defOrUse } - - final override Location getLocation() { result = defOrUse.getLocation() } - - final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() } -} - -class Phi extends TPhi, SsaDefOrUse { - PhiNode phi; - - Phi() { this = TPhi(phi) } - - final override PhiNode asPhi() { result = phi } - - final override Location getLocation() { result = phi.getBasicBlock().getLocation() } -} - -class UseOrPhi extends SsaDefOrUse { - UseOrPhi() { - this.asDefOrUse() instanceof UseImpl - or - this instanceof Phi - } - - final override Location getLocation() { - result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation() - } - - override string toString() { - result = this.asDefOrUse().toString() - or - this instanceof Phi and - result = "Phi" - } -} - -class Def extends DefOrUse { - override DefImpl defOrUse; - - Operand getAddressOperand() { result = defOrUse.getAddressOperand() } - - Instruction getAddress() { result = this.getAddressOperand().getDef() } - - Instruction getDefiningInstruction() { result = defOrUse.getDefiningInstruction() } - - override string toString() { result = this.asDefOrUse().toString() + " (def)" } -} - -private module SsaImpl = SsaImplCommon::Make; - -class PhiNode = SsaImpl::PhiNode; - -class Definition = SsaImpl::Definition; diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll deleted file mode 100644 index bf937b6de31..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingImpl.qll +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) taint tracking. - * This file re-exports the local (intraprocedural) taint-tracking analysis - * from `TaintTrackingParameter::Public` and adds a global analysis, mainly - * exposed through the `Configuration` class. For some languages, this file - * exists in several identical copies, allowing queries to use multiple - * `Configuration` classes that depend on each other without introducing - * mutual recursion among those configurations. - */ - -import TaintTrackingParameter::Public -private import TaintTrackingParameter::Private - -/** - * A configuration of interprocedural taint tracking analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the taint tracking library must define its own unique extension of - * this abstract class. - * - * A taint-tracking configuration is a special data flow configuration - * (`DataFlow::Configuration`) that allows for flow through nodes that do not - * necessarily preserve values but are still relevant from a taint tracking - * perspective. (For example, string concatenation, where one of the operands - * is tainted.) - * - * To create a configuration, extend this class with a subclass whose - * characteristic predicate is a unique singleton string. For example, write - * - * ```ql - * class MyAnalysisConfiguration extends TaintTracking::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isSanitizer`. - * // Optionally override `isSanitizerIn`. - * // Optionally override `isSanitizerOut`. - * // Optionally override `isSanitizerGuard`. - * // Optionally override `isAdditionalTaintStep`. - * } - * ``` - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but it is unsupported to depend on - * another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the - * overridden predicates that define sources, sinks, or additional steps. - * Instead, the dependency should go to a `TaintTracking2::Configuration` or a - * `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc. - */ -abstract class Configuration extends DataFlow::Configuration { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant taint source. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source) { none() } - - /** - * Holds if `source` is a relevant taint source with the given initial - * `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() } - - /** - * Holds if `sink` is a relevant taint sink - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink) { none() } - - /** - * Holds if `sink` is a relevant taint sink accepting `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() } - - /** Holds if the node `node` is a taint sanitizer. */ - predicate isSanitizer(DataFlow::Node node) { none() } - - final override predicate isBarrier(DataFlow::Node node) { - this.isSanitizer(node) or - defaultTaintSanitizer(node) - } - - /** - * Holds if the node `node` is a taint sanitizer when the flow state is - * `state`. - */ - predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() } - - final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { - this.isSanitizer(node, state) - } - - /** Holds if taint propagation into `node` is prohibited. */ - predicate isSanitizerIn(DataFlow::Node node) { none() } - - final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } - - /** Holds if taint propagation out of `node` is prohibited. */ - predicate isSanitizerOut(DataFlow::Node node) { none() } - - final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - - deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { - this.isSanitizerGuard(guard) - } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited - * when the flow state is `state`. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { - none() - } - - deprecated final override predicate isBarrierGuard( - DataFlow::BarrierGuard guard, DataFlow::FlowState state - ) { - this.isSanitizerGuard(guard, state) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - */ - predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } - - final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - this.isAdditionalTaintStep(node1, node2) or - defaultAdditionalTaintStep(node1, node2) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - none() - } - - final override predicate isAdditionalFlowStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - this.isAdditionalTaintStep(node1, state1, node2, state2) - } - - override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - ( - this.isSink(node) or - this.isSink(node, _) or - this.isAdditionalTaintStep(node, _) or - this.isAdditionalTaintStep(node, _, _, _) - ) and - defaultImplicitTaintRead(node, c) - } - - /** - * Holds if taint may flow from `source` to `sink` for this configuration. - */ - // overridden to provide taint-tracking specific qldoc - override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { - super.hasFlow(source, sink) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll deleted file mode 100644 index 07185a4ad57..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ /dev/null @@ -1,5 +0,0 @@ -import experimental.semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public - -module Private { - import experimental.semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as DataFlow -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll deleted file mode 100644 index bf937b6de31..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingImpl.qll +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) taint tracking. - * This file re-exports the local (intraprocedural) taint-tracking analysis - * from `TaintTrackingParameter::Public` and adds a global analysis, mainly - * exposed through the `Configuration` class. For some languages, this file - * exists in several identical copies, allowing queries to use multiple - * `Configuration` classes that depend on each other without introducing - * mutual recursion among those configurations. - */ - -import TaintTrackingParameter::Public -private import TaintTrackingParameter::Private - -/** - * A configuration of interprocedural taint tracking analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the taint tracking library must define its own unique extension of - * this abstract class. - * - * A taint-tracking configuration is a special data flow configuration - * (`DataFlow::Configuration`) that allows for flow through nodes that do not - * necessarily preserve values but are still relevant from a taint tracking - * perspective. (For example, string concatenation, where one of the operands - * is tainted.) - * - * To create a configuration, extend this class with a subclass whose - * characteristic predicate is a unique singleton string. For example, write - * - * ```ql - * class MyAnalysisConfiguration extends TaintTracking::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isSanitizer`. - * // Optionally override `isSanitizerIn`. - * // Optionally override `isSanitizerOut`. - * // Optionally override `isSanitizerGuard`. - * // Optionally override `isAdditionalTaintStep`. - * } - * ``` - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but it is unsupported to depend on - * another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the - * overridden predicates that define sources, sinks, or additional steps. - * Instead, the dependency should go to a `TaintTracking2::Configuration` or a - * `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc. - */ -abstract class Configuration extends DataFlow::Configuration { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant taint source. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source) { none() } - - /** - * Holds if `source` is a relevant taint source with the given initial - * `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() } - - /** - * Holds if `sink` is a relevant taint sink - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink) { none() } - - /** - * Holds if `sink` is a relevant taint sink accepting `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() } - - /** Holds if the node `node` is a taint sanitizer. */ - predicate isSanitizer(DataFlow::Node node) { none() } - - final override predicate isBarrier(DataFlow::Node node) { - this.isSanitizer(node) or - defaultTaintSanitizer(node) - } - - /** - * Holds if the node `node` is a taint sanitizer when the flow state is - * `state`. - */ - predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() } - - final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { - this.isSanitizer(node, state) - } - - /** Holds if taint propagation into `node` is prohibited. */ - predicate isSanitizerIn(DataFlow::Node node) { none() } - - final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } - - /** Holds if taint propagation out of `node` is prohibited. */ - predicate isSanitizerOut(DataFlow::Node node) { none() } - - final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - - deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { - this.isSanitizerGuard(guard) - } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited - * when the flow state is `state`. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { - none() - } - - deprecated final override predicate isBarrierGuard( - DataFlow::BarrierGuard guard, DataFlow::FlowState state - ) { - this.isSanitizerGuard(guard, state) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - */ - predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } - - final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - this.isAdditionalTaintStep(node1, node2) or - defaultAdditionalTaintStep(node1, node2) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - none() - } - - final override predicate isAdditionalFlowStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - this.isAdditionalTaintStep(node1, state1, node2, state2) - } - - override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - ( - this.isSink(node) or - this.isSink(node, _) or - this.isAdditionalTaintStep(node, _) or - this.isAdditionalTaintStep(node, _, _, _) - ) and - defaultImplicitTaintRead(node, c) - } - - /** - * Holds if taint may flow from `source` to `sink` for this configuration. - */ - // overridden to provide taint-tracking specific qldoc - override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { - super.hasFlow(source, sink) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingParameter.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingParameter.qll deleted file mode 100644 index 7d545fe5d04..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking2/TaintTrackingParameter.qll +++ /dev/null @@ -1,5 +0,0 @@ -import experimental.semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public - -module Private { - import experimental.semmle.code.cpp.ir.dataflow.DataFlow2::DataFlow2 as DataFlow -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll deleted file mode 100644 index bf937b6de31..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingImpl.qll +++ /dev/null @@ -1,191 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) taint tracking. - * This file re-exports the local (intraprocedural) taint-tracking analysis - * from `TaintTrackingParameter::Public` and adds a global analysis, mainly - * exposed through the `Configuration` class. For some languages, this file - * exists in several identical copies, allowing queries to use multiple - * `Configuration` classes that depend on each other without introducing - * mutual recursion among those configurations. - */ - -import TaintTrackingParameter::Public -private import TaintTrackingParameter::Private - -/** - * A configuration of interprocedural taint tracking analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the taint tracking library must define its own unique extension of - * this abstract class. - * - * A taint-tracking configuration is a special data flow configuration - * (`DataFlow::Configuration`) that allows for flow through nodes that do not - * necessarily preserve values but are still relevant from a taint tracking - * perspective. (For example, string concatenation, where one of the operands - * is tainted.) - * - * To create a configuration, extend this class with a subclass whose - * characteristic predicate is a unique singleton string. For example, write - * - * ```ql - * class MyAnalysisConfiguration extends TaintTracking::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isSanitizer`. - * // Optionally override `isSanitizerIn`. - * // Optionally override `isSanitizerOut`. - * // Optionally override `isSanitizerGuard`. - * // Optionally override `isAdditionalTaintStep`. - * } - * ``` - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but it is unsupported to depend on - * another `TaintTracking::Configuration` or a `DataFlow::Configuration` in the - * overridden predicates that define sources, sinks, or additional steps. - * Instead, the dependency should go to a `TaintTracking2::Configuration` or a - * `DataFlow2::Configuration`, `DataFlow3::Configuration`, etc. - */ -abstract class Configuration extends DataFlow::Configuration { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant taint source. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source) { none() } - - /** - * Holds if `source` is a relevant taint source with the given initial - * `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() } - - /** - * Holds if `sink` is a relevant taint sink - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink) { none() } - - /** - * Holds if `sink` is a relevant taint sink accepting `state`. - * - * The smaller this predicate is, the faster `hasFlow()` will converge. - */ - // overridden to provide taint-tracking specific qldoc - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() } - - /** Holds if the node `node` is a taint sanitizer. */ - predicate isSanitizer(DataFlow::Node node) { none() } - - final override predicate isBarrier(DataFlow::Node node) { - this.isSanitizer(node) or - defaultTaintSanitizer(node) - } - - /** - * Holds if the node `node` is a taint sanitizer when the flow state is - * `state`. - */ - predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() } - - final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { - this.isSanitizer(node, state) - } - - /** Holds if taint propagation into `node` is prohibited. */ - predicate isSanitizerIn(DataFlow::Node node) { none() } - - final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) } - - /** Holds if taint propagation out of `node` is prohibited. */ - predicate isSanitizerOut(DataFlow::Node node) { none() } - - final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() } - - deprecated final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { - this.isSanitizerGuard(guard) - } - - /** - * DEPRECATED: Use `isSanitizer` and `BarrierGuard` module instead. - * - * Holds if taint propagation through nodes guarded by `guard` is prohibited - * when the flow state is `state`. - */ - deprecated predicate isSanitizerGuard(DataFlow::BarrierGuard guard, DataFlow::FlowState state) { - none() - } - - deprecated final override predicate isBarrierGuard( - DataFlow::BarrierGuard guard, DataFlow::FlowState state - ) { - this.isSanitizerGuard(guard, state) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - */ - predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() } - - final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - this.isAdditionalTaintStep(node1, node2) or - defaultAdditionalTaintStep(node1, node2) - } - - /** - * Holds if taint may propagate from `node1` to `node2` in addition to the normal data-flow and taint steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - none() - } - - final override predicate isAdditionalFlowStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 - ) { - this.isAdditionalTaintStep(node1, state1, node2, state2) - } - - override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { - ( - this.isSink(node) or - this.isSink(node, _) or - this.isAdditionalTaintStep(node, _) or - this.isAdditionalTaintStep(node, _, _, _) - ) and - defaultImplicitTaintRead(node, c) - } - - /** - * Holds if taint may flow from `source` to `sink` for this configuration. - */ - // overridden to provide taint-tracking specific qldoc - override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { - super.hasFlow(source, sink) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingParameter.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingParameter.qll deleted file mode 100644 index 3e69abcf4a7..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/tainttracking3/TaintTrackingParameter.qll +++ /dev/null @@ -1,5 +0,0 @@ -import experimental.semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public - -module Private { - import experimental.semmle.code.cpp.ir.dataflow.DataFlow3::DataFlow3 as DataFlow -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll index f82330f3fbd..416bf4b04f8 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/security/PrivateCleartextWrite.qll @@ -3,7 +3,7 @@ */ import cpp -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.security.PrivateData import semmle.code.cpp.security.FileWrite import semmle.code.cpp.security.BufferWrite @@ -36,7 +36,7 @@ module PrivateCleartextWrite { } } - class WriteConfig extends TaintTracking::Configuration { + deprecated class WriteConfig extends TaintTracking::Configuration { WriteConfig() { this = "Write configuration" } override predicate isSource(DataFlow::Node source) { source instanceof Source } @@ -46,6 +46,16 @@ module PrivateCleartextWrite { override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer } } + private module WriteConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof Source } + + predicate isSink(DataFlow::Node sink) { sink instanceof Sink } + + predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer } + } + + module WriteFlow = TaintTracking::Make; + class PrivateDataSource extends Source { PrivateDataSource() { this.getExpr() instanceof PrivateDataExpr } } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll index 48a983c3ffb..a1814f659fc 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll @@ -5,6 +5,7 @@ private import SemanticExpr private import SemanticExprSpecific::SemanticExprConfig as Specific private import SemanticSSA +private import SemanticLocation /** * A valid base for an expression bound. @@ -14,6 +15,8 @@ private import SemanticSSA class SemBound instanceof Specific::Bound { final string toString() { result = super.toString() } + final SemLocation getLocation() { result = super.getLocation() } + final SemExpr getExpr(int delta) { result = Specific::getBoundExpr(this, delta) } } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll new file mode 100644 index 00000000000..328f85151b5 --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll @@ -0,0 +1,23 @@ +private import semmle.code.cpp.Location + +class SemLocation instanceof Location { + /** + * Gets a textual representation of this element. + * + * The format is "file://filePath:startLine:startColumn:endLine:endColumn". + */ + string toString() { result = super.toString() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll new file mode 100644 index 00000000000..83698b56229 --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll @@ -0,0 +1,29 @@ +private import RangeAnalysisStage + +module IntDelta implements DeltaSig { + class Delta = int; + + bindingset[d] + bindingset[result] + float toFloat(Delta d) { result = d } + + bindingset[d] + bindingset[result] + int toInt(Delta d) { result = d } + + bindingset[n] + bindingset[result] + Delta fromInt(int n) { result = n } + + bindingset[f] + Delta fromFloat(float f) { + result = + min(float diff, float res | + diff = (res - f) and res = f.ceil() + or + diff = (f - res) and res = f.floor() + | + res order by diff + ) + } +} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll index 50d604dee97..e9b7d9dc2ac 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll @@ -1,24 +1,2 @@ -private import RangeAnalysisStage -private import RangeAnalysisSpecific -private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta -private import RangeUtils -private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound - -module Bounds implements BoundSig { - class SemBound instanceof SemanticBound::SemBound { - string toString() { result = super.toString() } - - SemExpr getExpr(float delta) { result = super.getExpr(delta) } - } - - class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } - - class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { - SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } - } -} - -private module CppRangeAnalysis = - RangeStage>; - -import CppRangeAnalysis +import RangeAnalysisImpl +import experimental.semmle.code.cpp.semantic.SemanticBound diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll new file mode 100644 index 00000000000..49b8541b17f --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll @@ -0,0 +1,107 @@ +private import RangeAnalysisStage +private import RangeAnalysisSpecific +private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta +private import RangeUtils +private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound +private import experimental.semmle.code.cpp.semantic.SemanticLocation +private import experimental.semmle.code.cpp.semantic.SemanticSSA + +module ConstantBounds implements BoundSig { + class SemBound instanceof SemanticBound::SemBound { + SemBound() { + this instanceof SemanticBound::SemZeroBound + or + this.(SemanticBound::SemSsaBound).getAVariable() instanceof SemSsaPhiNode + } + + string toString() { result = super.toString() } + + SemLocation getLocation() { result = super.getLocation() } + + SemExpr getExpr(float delta) { result = super.getExpr(delta) } + } + + class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } + + class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { + SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } + } +} + +private module RelativeBounds implements BoundSig { + class SemBound instanceof SemanticBound::SemBound { + SemBound() { not this instanceof SemanticBound::SemZeroBound } + + string toString() { result = super.toString() } + + SemLocation getLocation() { result = super.getLocation() } + + SemExpr getExpr(float delta) { result = super.getExpr(delta) } + } + + class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } + + class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { + SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } + } +} + +private module ConstantStage = + RangeStage>; + +private module RelativeStage = + RangeStage>; + +private newtype TSemReason = + TSemNoReason() or + TSemCondReason(SemGuard guard) { + guard = any(ConstantStage::SemCondReason reason).getCond() + or + guard = any(RelativeStage::SemCondReason reason).getCond() + } + +/** + * A reason for an inferred bound. This can either be `CondReason` if the bound + * is due to a specific condition, or `NoReason` if the bound is inferred + * without going through a bounding condition. + */ +abstract class SemReason extends TSemReason { + /** Gets a textual representation of this reason. */ + abstract string toString(); +} + +/** + * A reason for an inferred bound that indicates that the bound is inferred + * without going through a bounding condition. + */ +class SemNoReason extends SemReason, TSemNoReason { + override string toString() { result = "NoReason" } +} + +/** A reason for an inferred bound pointing to a condition. */ +class SemCondReason extends SemReason, TSemCondReason { + /** Gets the condition that is the reason for the bound. */ + SemGuard getCond() { this = TSemCondReason(result) } + + override string toString() { result = getCond().toString() } +} + +private ConstantStage::SemReason constantReason(SemReason reason) { + result instanceof ConstantStage::SemNoReason and reason instanceof SemNoReason + or + result.(ConstantStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() +} + +private RelativeStage::SemReason relativeReason(SemReason reason) { + result instanceof RelativeStage::SemNoReason and reason instanceof SemNoReason + or + result.(RelativeStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() +} + +predicate semBounded( + SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason +) { + ConstantStage::semBounded(e, b, delta, upper, constantReason(reason)) + or + RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason)) +} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll index fc9e4cfbaef..cdf0943eb65 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll @@ -73,6 +73,7 @@ import experimental.semmle.code.cpp.semantic.SemanticCFG import experimental.semmle.code.cpp.semantic.SemanticType import experimental.semmle.code.cpp.semantic.SemanticOpcode private import ConstantAnalysis +import experimental.semmle.code.cpp.semantic.SemanticLocation /** * Holds if `typ` is a small integral type with the given lower and upper bounds. @@ -228,6 +229,10 @@ signature module UtilSig { signature module BoundSig { class SemBound { + string toString(); + + SemLocation getLocation(); + SemExpr getExpr(D::Delta delta); } @@ -936,6 +941,15 @@ module RangeStage Bounds, LangSig LangParam, UtilSig< bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason) } + /** + * Computes a normal form of `x` where -0.0 has changed to +0.0. This can be + * needed on the lesser side of a floating-point comparison or on both sides of + * a floating point equality because QL does not follow IEEE in floating-point + * comparisons but instead defines -0.0 to be less than and distinct from 0.0. + */ + bindingset[x] + private float normalizeFloatUp(float x) { result = x + 0.0 } + /** * Holds if `b + delta` is a valid bound for `e`. * - `upper = true` : `e <= b + delta` @@ -1020,6 +1034,15 @@ module RangeStage Bounds, LangSig LangParam, UtilSig< or upper = false and delta = D::fromFloat(D::toFloat(d1).minimum(D::toFloat(d2))) ) + or + exists(SemExpr mid, D::Delta d, float f | + e.(SemNegateExpr).getOperand() = mid and + b instanceof SemZeroBound and + bounded(mid, b, d, upper.booleanNot(), fromBackEdge, origdelta, reason) and + f = normalizeFloatUp(-D::toFloat(d)) and + delta = D::fromFloat(f) and + if semPositive(e) then f >= 0 else any() + ) ) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll new file mode 100644 index 00000000000..bd234390e3d --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll @@ -0,0 +1,132 @@ +/** + * Wrapper for the semantic range analysis library that mimics the + * interface of the simple range analysis library. + */ + +private import cpp +private import semmle.code.cpp.ir.IR +private import experimental.semmle.code.cpp.semantic.SemanticBound +private import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +private import RangeAnalysis + +/** + * Gets the lower bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the lower bound + * of the expression without including the effect of the casts. To compute + * the lower bound of the expression after all the casts have been applied, + * call `lowerBound` like this: + * + * `lowerBound(expr.getFullyConverted())` + */ +float lowerBound(Expr expr) { + exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | + semBounded(getSemanticExpr(i), b, result, false, _) + ) +} + +/** + * Gets the upper bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the upper bound + * of the expression without including the effect of the casts. To compute + * the upper bound of the expression after all the casts have been applied, + * call `upperBound` like this: + * + * `upperBound(expr.getFullyConverted())` + */ +float upperBound(Expr expr) { + exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | + semBounded(getSemanticExpr(i), b, result, true, _) + ) +} + +/** + * Holds if the upper bound of `expr` may have been widened. This means the + * upper bound is in practice likely to be overly wide. + */ +predicate upperBoundMayBeWidened(Expr e) { none() } + +/** + * Holds if `expr` has a provably empty range. For example: + * + * 10 < expr and expr < 5 + * + * The range of an expression can only be empty if it can never be + * executed. For example: + * + * ```cpp + * if (10 < x) { + * if (x < 5) { + * // Unreachable code + * return x; // x has an empty range: 10 < x && x < 5 + * } + * } + * ``` + */ +predicate exprWithEmptyRange(Expr expr) { lowerBound(expr) > upperBound(expr) } + +/** Holds if the definition might overflow negatively. */ +predicate defMightOverflowNegatively(RangeSsaDefinition def, StackVariable v) { none() } + +/** Holds if the definition might overflow positively. */ +predicate defMightOverflowPositively(RangeSsaDefinition def, StackVariable v) { none() } + +/** + * Holds if the definition might overflow (either positively or + * negatively). + */ +predicate defMightOverflow(RangeSsaDefinition def, StackVariable v) { + defMightOverflowNegatively(def, v) or + defMightOverflowPositively(def, v) +} + +/** + * Holds if the expression might overflow negatively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ +predicate exprMightOverflowNegatively(Expr expr) { none() } + +/** + * Holds if the expression might overflow negatively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ +predicate convertedExprMightOverflowNegatively(Expr expr) { + exprMightOverflowNegatively(expr) or + convertedExprMightOverflowNegatively(expr.getConversion()) +} + +/** + * Holds if the expression might overflow positively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ +predicate exprMightOverflowPositively(Expr expr) { none() } + +/** + * Holds if the expression might overflow positively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ +predicate convertedExprMightOverflowPositively(Expr expr) { + exprMightOverflowPositively(expr) or + convertedExprMightOverflowPositively(expr.getConversion()) +} + +/** + * Holds if the expression might overflow (either positively or + * negatively). The possibility that the expression might overflow + * due to an implicit or explicit cast is also considered. + */ +predicate convertedExprMightOverflow(Expr expr) { + convertedExprMightOverflowNegatively(expr) or + convertedExprMightOverflowPositively(expr) +} diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml index ee8b5187961..8e6602b6634 100644 --- a/cpp/ql/lib/qlpack.yml +++ b/cpp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-all -version: 0.5.4-dev +version: 0.5.5-dev groups: cpp dbscheme: semmlecode.cpp.dbscheme extractor: cpp diff --git a/cpp/ql/lib/semmle/code/cpp/Class.qll b/cpp/ql/lib/semmle/code/cpp/Class.qll index f139f67c70a..2aba033329d 100644 --- a/cpp/ql/lib/semmle/code/cpp/Class.qll +++ b/cpp/ql/lib/semmle/code/cpp/Class.qll @@ -227,18 +227,6 @@ class Class extends UserType { result = this.accessOfBaseMember(member.getDeclaringType(), member.getASpecifier()) } - /** - * DEPRECATED: name changed to `hasImplicitCopyConstructor` to reflect that - * `= default` members are no longer included. - */ - deprecated predicate hasGeneratedCopyConstructor() { this.hasImplicitCopyConstructor() } - - /** - * DEPRECATED: name changed to `hasImplicitCopyAssignmentOperator` to - * reflect that `= default` members are no longer included. - */ - deprecated predicate hasGeneratedCopyAssignmentOperator() { this.hasImplicitCopyConstructor() } - /** * Holds if this class, struct or union has an implicitly-declared copy * constructor that is not _deleted_. This predicate is more accurate than diff --git a/cpp/ql/lib/semmle/code/cpp/Declaration.qll b/cpp/ql/lib/semmle/code/cpp/Declaration.qll index d7cc581c384..7d7dee45aa9 100644 --- a/cpp/ql/lib/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/lib/semmle/code/cpp/Declaration.qll @@ -186,7 +186,7 @@ class Declaration extends Locatable, @declaration { predicate hasDefinition() { exists(this.getDefinition()) } /** DEPRECATED: Use `hasDefinition` instead. */ - predicate isDefined() { this.hasDefinition() } + deprecated predicate isDefined() { this.hasDefinition() } /** Gets the preferred location of this declaration, if any. */ override Location getLocation() { none() } @@ -619,11 +619,10 @@ private class DirectAccessHolder extends Element { /** * Like `couldAccessMember` but only contains derivations in which either * (5.2), (5.3) or (5.4) must be invoked. In other words, the `this` - * parameter is not ignored. This restriction makes it feasible to fully - * enumerate this predicate even on large code bases. We check for 11.4 as - * part of (5.3), since this further limits the number of tuples produced by - * this predicate. + * parameter is not ignored. We check for 11.4 as part of (5.3), since + * this further limits the number of tuples produced by this predicate. */ + pragma[inline] predicate thisCouldAccessMember(Class memberClass, AccessSpecifier memberAccess, Class derived) { // Only (5.4) is recursive, and chains of invocations of (5.4) can always // be collapsed to one invocation by the transitivity of 11.2/4. @@ -665,7 +664,9 @@ private class DirectAccessHolder extends Element { // bypasses `p`. Then that path must be public, or we are in case 2. exists(AccessSpecifier public | public.hasName("public") | exists(Class between, Class p | - between.accessOfBaseMember(memberClass, memberAccess).hasName("protected") and + between + .accessOfBaseMember(pragma[only_bind_into](memberClass), memberAccess) + .hasName("protected") and this.isFriendOfOrEqualTo(p) and ( // This is case 1 from above. If `p` derives privately from `between` diff --git a/cpp/ql/lib/semmle/code/cpp/Function.qll b/cpp/ql/lib/semmle/code/cpp/Function.qll index 98b0e8525ce..eec7a433774 100644 --- a/cpp/ql/lib/semmle/code/cpp/Function.qll +++ b/cpp/ql/lib/semmle/code/cpp/Function.qll @@ -41,7 +41,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * `min(int, int) -> int`, and the full signature of the uninstantiated * template on the first line would be `min(T, T) -> T`. */ - string getFullSignature() { + deprecated string getFullSignature() { exists(string name, string templateArgs, string args | result = name + templateArgs + args + " -> " + this.getType().toString() and name = this.getQualifiedName() and diff --git a/cpp/ql/lib/semmle/code/cpp/NameQualifiers.qll b/cpp/ql/lib/semmle/code/cpp/NameQualifiers.qll index 042ee10700a..a5894e21071 100644 --- a/cpp/ql/lib/semmle/code/cpp/NameQualifiers.qll +++ b/cpp/ql/lib/semmle/code/cpp/NameQualifiers.qll @@ -159,7 +159,8 @@ class NameQualifyingElement extends Element, @namequalifyingelement { * A special name-qualifying element. For example: `__super`. */ library class SpecialNameQualifyingElement extends NameQualifyingElement, - @specialnamequalifyingelement { + @specialnamequalifyingelement +{ /** Gets the name of this special qualifying element. */ override string getName() { specialnamequalifyingelements(underlyingElement(this), result) } diff --git a/cpp/ql/lib/semmle/code/cpp/XML.qll b/cpp/ql/lib/semmle/code/cpp/XML.qll index d74129d425e..33f4cd9e9e6 100644 --- a/cpp/ql/lib/semmle/code/cpp/XML.qll +++ b/cpp/ql/lib/semmle/code/cpp/XML.qll @@ -108,20 +108,6 @@ class XmlFile extends XmlParent, File { /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } - /** - * DEPRECATED: Use `getAbsolutePath()` instead. - * - * Gets the path of this XML file. - */ - deprecated string getPath() { result = this.getAbsolutePath() } - - /** - * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. - * - * Gets the path of the folder that contains this XML file. - */ - deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } - /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/lib/semmle/code/cpp/commons/Alloc.qll index ce3f6993525..a6fb84d3227 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Alloc.qll @@ -12,7 +12,9 @@ predicate freeFunction(Function f, int argNum) { argNum = f.(DeallocationFunctio * * DEPRECATED: Use `DeallocationExpr` instead (this also includes `delete` expressions). */ -predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getFreedExpr() } +deprecated predicate freeCall(FunctionCall fc, Expr arg) { + arg = fc.(DeallocationExpr).getFreedExpr() +} /** * Is e some kind of allocation or deallocation (`new`, `alloc`, `realloc`, `delete`, `free` etc)? diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll b/cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll index 06dcdfb9d85..1c557af797e 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Buffer.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.ir.dataflow.DataFlow /** * Holds if `v` is a member variable of `c` that looks like it might be variable sized @@ -25,10 +25,12 @@ predicate memberMayBeVarSize(Class c, MemberVariable v) { } /** - * Get the size in bytes of the buffer pointed to by an expression (if this can be determined). + * Holds if `bufferExpr` is an allocation-like expression. + * + * This includes both actual allocations, as well as various operations that return a pointer to + * stack-allocated objects. */ -language[monotonicAggregates] -int getBufferSize(Expr bufferExpr, Element why) { +private int isSource(Expr bufferExpr, Element why) { exists(Variable bufferVar | bufferVar = bufferExpr.(VariableAccess).getTarget() | // buffer is a fixed size array result = bufferVar.getUnspecifiedType().(ArrayType).getSize() and @@ -46,42 +48,12 @@ int getBufferSize(Expr bufferExpr, Element why) { ) and result = why.(Expr).getType().(ArrayType).getSize() and not exists(bufferVar.getUnspecifiedType().(ArrayType).getSize()) - or - exists(Class parentClass, VariableAccess parentPtr, int bufferSize | - // buffer is the parentPtr->bufferVar of a 'variable size struct' - memberMayBeVarSize(parentClass, bufferVar) and - why = bufferVar and - parentPtr = bufferExpr.(VariableAccess).getQualifier() and - parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and - ( - if exists(bufferVar.getType().getSize()) - then bufferSize = bufferVar.getType().getSize() - else bufferSize = 0 - ) and - result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize() - ) ) or // buffer is a fixed size dynamic allocation result = bufferExpr.(AllocationExpr).getSizeBytes() and why = bufferExpr or - exists(DataFlow::ExprNode bufferExprNode | - // dataflow (all sources must be the same size) - bufferExprNode = DataFlow::exprNode(bufferExpr) and - result = - unique(Expr def | - DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) - | - getBufferSize(def, _) - ) and - // find reason - exists(Expr def | DataFlow::localFlowStep(DataFlow::exprNode(def), bufferExprNode) | - why = def or - exists(getBufferSize(def, why)) - ) - ) - or exists(Type bufferType | // buffer is the address of a variable why = bufferExpr.(AddressOfExpr).getAddressable() and @@ -100,3 +72,30 @@ int getBufferSize(Expr bufferExpr, Element why) { result = bufferType.getSize() ) } + +/** + * Get the size in bytes of the buffer pointed to by an expression (if this can be determined). + */ +language[monotonicAggregates] +int getBufferSize(Expr bufferExpr, Element why) { + result = isSource(bufferExpr, why) + or + exists(Class parentClass, VariableAccess parentPtr, int bufferSize, Variable bufferVar | + bufferVar = bufferExpr.(VariableAccess).getTarget() and + // buffer is the parentPtr->bufferVar of a 'variable size struct' + memberMayBeVarSize(parentClass, bufferVar) and + why = bufferVar and + parentPtr = bufferExpr.(VariableAccess).getQualifier() and + parentPtr.getTarget().getUnspecifiedType().(PointerType).getBaseType() = parentClass and + result = getBufferSize(parentPtr, _) + bufferSize - parentClass.getSize() + | + if exists(bufferVar.getType().getSize()) + then bufferSize = bufferVar.getType().getSize() + else bufferSize = 0 + ) + or + // dataflow (all sources must be the same size) + result = unique(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | getBufferSize(def, _)) and + // find reason + exists(Expr def | DataFlow::localExprFlowStep(def, bufferExpr) | exists(getBufferSize(def, why))) +} diff --git a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll index d9fe287f11f..25341c25f6c 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/NullTermination.qll @@ -1,7 +1,7 @@ import cpp private import semmle.code.cpp.models.interfaces.ArrayFunction private import semmle.code.cpp.models.implementations.Strcat -import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.ir.dataflow.DataFlow /** * Holds if the expression `e` assigns something including `va` to a diff --git a/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll b/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll index f1b9cf80d64..f02958cd241 100644 --- a/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll +++ b/cpp/ql/lib/semmle/code/cpp/commons/Synchronization.qll @@ -59,26 +59,6 @@ abstract class MutexType extends Type { * Gets a call that unlocks any mutex of this type. */ FunctionCall getUnlockAccess() { this.unlockAccess(result, _) } - - /** - * DEPRECATED: use mustlockAccess(fc, arg) instead. - */ - deprecated Function getMustlockFunction() { result = this.getMustlockAccess().getTarget() } - - /** - * DEPRECATED: use trylockAccess(fc, arg) instead. - */ - deprecated Function getTrylockFunction() { result = this.getTrylockAccess().getTarget() } - - /** - * DEPRECATED: use lockAccess(fc, arg) instead. - */ - deprecated Function getLockFunction() { result = this.getLockAccess().getTarget() } - - /** - * DEPRECATED: use unlockAccess(fc, arg) instead. - */ - deprecated Function getUnlockFunction() { result = this.getUnlockAccess().getTarget() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll index 52f09eb7778..9ee0fa3131b 100644 --- a/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll +++ b/cpp/ql/lib/semmle/code/cpp/controlflow/SubBasicBlocks.qll @@ -75,13 +75,6 @@ class SubBasicBlock extends ControlFlowNodeBase { ) } - /** - * DEPRECATED: use `getRankInBasicBlock` instead. Note that this predicate - * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based - * position. - */ - deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 } - pragma[noinline] private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow.qll index 109be647f72..24fdb60eff1 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow.qll @@ -19,6 +19,11 @@ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow { - import semmle.code.cpp.dataflow.internal.DataFlowImpl + import semmle.code.cpp.dataflow.internal.DataFlow + import semmle.code.cpp.dataflow.internal.DataFlowImpl1 } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow2.qll index 91c7bdc80a9..6d9c38af545 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow2.qll @@ -11,6 +11,10 @@ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow2 { import semmle.code.cpp.dataflow.internal.DataFlowImpl2 } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow3.qll index b1360a1247f..c4e7a4906fc 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow3.qll @@ -11,6 +11,10 @@ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow3 { import semmle.code.cpp.dataflow.internal.DataFlowImpl3 } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow4.qll index f92f87b4a0f..8287ecf70fe 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/DataFlow4.qll @@ -11,6 +11,10 @@ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow4 { import semmle.code.cpp.dataflow.internal.DataFlowImpl4 } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/StackAddress.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/StackAddress.qll index f375bbae199..f8814b5f3bc 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/StackAddress.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/StackAddress.qll @@ -95,6 +95,11 @@ predicate stackPointerFlowsToUse(Expr use, Type useType, Expr source, boolean is cached private PointerType getExprPtrType(Expr use) { result = use.getUnspecifiedType() } +/** + * Holds if `use` has type `useType` and `source` is an access to a stack variable + * that flows to `use`. `isLocal` is `true` if `use` is accessed via a parameter, and + * `false` otherwise. + */ predicate stackReferenceFlowsToUse(Expr use, Type useType, Expr source, boolean isLocal) { // Stack variables exists(StackVariable var | diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking.qll index e10eb8e15a5..57d93068a4c 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking.qll @@ -18,6 +18,11 @@ import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.dataflow.DataFlow2 +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ module TaintTracking { + import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTracking import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking2.qll index bde6c363347..a8f92ee1041 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/TaintTracking2.qll @@ -10,6 +10,11 @@ * * See `semmle.code.cpp.dataflow.TaintTracking` for the full documentation. */ + +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ module TaintTracking2 { import semmle.code.cpp.dataflow.internal.tainttracking2.TaintTrackingImpl } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll new file mode 100644 index 00000000000..617362ab4f0 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlow.qll @@ -0,0 +1,353 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Make` and `MakeWithState` modules. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic +private import DataFlowImpl + +/** An input configuration for data flow. */ +signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** An input configuration for data flow using flow state. */ +signature module StateConfigSig { + bindingset[this] + class FlowState; + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state); + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state); + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ +signature int explorationLimitSig(); + +/** + * The output of a data flow computation. + */ +signature module DataFlowSig { + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode; + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink); + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink); +} + +/** + * Constructs a standard data flow computation. + */ +module Make implements DataFlowSig { + private module C implements FullStateConfigSig { + import DefaultState + import Config + } + + import Impl +} + +/** + * Constructs a data flow computation using flow state. + */ +module MakeWithState implements DataFlowSig { + private module C implements FullStateConfigSig { + import Config + } + + import Impl +} + +signature class PathNodeSig { + /** Gets a textual representation of this element. */ + string toString(); + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); + + /** Gets the underlying `Node`. */ + Node getNode(); +} + +signature module PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + predicate edges(PathNode a, PathNode b); + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + predicate nodes(PathNode n, string key, string val); + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); +} + +/** + * Constructs a `PathGraph` from two `PathGraph`s by disjoint union. + */ +module MergePathGraph< + PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig Graph1, + PathGraphSig Graph2> +{ + private newtype TPathNode = + TPathNode1(PathNode1 p) or + TPathNode2(PathNode2 p) + + /** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */ + class PathNode extends TPathNode { + /** Gets this as a projection on the first given `PathGraph`. */ + PathNode1 asPathNode1() { this = TPathNode1(result) } + + /** Gets this as a projection on the second given `PathGraph`. */ + PathNode2 asPathNode2() { this = TPathNode2(result) } + + /** Gets a textual representation of this element. */ + string toString() { + result = this.asPathNode1().toString() or + result = this.asPathNode2().toString() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + Node getNode() { + result = this.asPathNode1().getNode() or + result = this.asPathNode2().getNode() + } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph implements PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + Graph1::edges(a.asPathNode1(), b.asPathNode1()) or + Graph2::edges(a.asPathNode2(), b.asPathNode2()) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + Graph1::nodes(n.asPathNode1(), key, val) or + Graph2::nodes(n.asPathNode2(), key, val) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or + Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2()) + } + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll index 2fe8ede7f87..48fedd9f466 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll @@ -1,6 +1,6 @@ private import cpp -private import semmle.code.cpp.dataflow.internal.DataFlowPrivate -private import semmle.code.cpp.dataflow.internal.DataFlowUtil +private import DataFlowPrivate +private import DataFlowUtil /** * Gets a function that might be called by `call`. diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 1b969756b09..b7cb98deaf9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1,135 +1,75 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * INTERNAL: Do not use. + * + * Provides an implementation of global (interprocedural) data flow. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic +private import DataFlowImplSpecific::Public +private import DataFlowImplCommonPublic +import DataFlow /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + * An input configuration for data flow using flow state. This signature equals + * `StateConfigSig`, but requires explicit implementation of all predicates. */ -abstract class Configuration extends string { +signature module FullStateConfigSig { bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } + class FlowState; /** * Holds if `source` is a relevant data flow source with the given initial * `state`. */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } + predicate isSource(Node source, FlowState state); /** * Holds if `sink` is a relevant data flow sink accepting `state`. */ - predicate isSink(Node sink, FlowState state) { none() } + predicate isSink(Node sink, FlowState state); /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. */ - predicate isBarrier(Node node) { none() } + predicate isBarrier(Node node); /** * Holds if data flow through `node` is prohibited when the flow state is * `state`. */ - predicate isBarrier(Node node, FlowState state) { none() } + predicate isBarrier(Node node, FlowState state); /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } + predicate isBarrierIn(Node node); /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + predicate isBarrierOut(Node node); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + predicate isAdditionalFlowStep(Node node1, Node node2); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); /** * Holds if an arbitrary number of implicit read steps of content `c` may be * taken at `node`. */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } + predicate allowImplicitRead(Node node, ContentSet c); /** * Gets the virtual dispatch branching limit when calculating field flow. * This can be overridden to a smaller value to improve performance (a * value of 0 disables field flow), or a larger value to get more results. */ - int fieldFlowBranchLimit() { result = 2 } + int fieldFlowBranchLimit(); /** * Gets a data flow configuration feature to add restrictions to the set of @@ -144,1720 +84,685 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ - FlowFeature getAFeature() { none() } + FlowFeature getAFeature(); /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } + predicate sourceGrouping(Node source, string sourceGroup); /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } + predicate sinkGrouping(Node sink, string sinkGroup); /** * Holds if hidden nodes should be included in the data flow graph. * * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). + * is not visualized (as it is in a `path-problem` query). */ - predicate includeHiddenNodes() { none() } + predicate includeHiddenNodes(); +} - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } +/** + * Provides default `FlowState` implementations given a `StateConfigSig`. + */ +module DefaultState { + class FlowState = Unit; - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() + predicate isSource(Node source, FlowState state) { Config::isSource(source) and exists(state) } + + predicate isSink(Node sink, FlowState state) { Config::isSink(sink) and exists(state) } + + predicate isBarrier(Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() } } /** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. + * Constructs a data flow computation given a full input configuration. */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } +module Impl { + private class FlowState = Config::FlowState; - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} + private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + Config::allowImplicitRead(n, _) and hasRead = [false, true] + } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false + private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") } - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) } pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) } pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } + } + + private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + } + + private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + } + + private predicate inBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierIn(n) and + Config::isSource(n, _) + ) + } + + private predicate outBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierOut(n) and + Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate fullBarrier(NodeEx node) { + exists(Node n | node.asNode() = n | + Config::isBarrier(n) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + Config::isBarrierIn(n) and + not Config::isSource(n, _) + or + Config::isBarrierOut(n) and + not Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate stateBarrier(NodeEx node, FlowState state) { + exists(Node n | node.asNode() = n | Config::isBarrier(n, state)) + } + + pragma[nomagic] + private predicate sourceNode(NodeEx node, FlowState state) { + Config::isSource(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + pragma[nomagic] + private predicate sinkNode(NodeEx node, FlowState state) { + Config::isSink(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + /** Provides the relevant barriers for a step from `node1` to `node2`. */ + pragma[inline] + private predicate stepFilter(NodeEx node1, NodeEx node2) { + not outBarrier(node1) and + not inBarrier(node2) and + not fullBarrier(node1) and + not fullBarrier(node2) + } + + /** + * Holds if data can flow in one local step from `node1` to `node2`. + */ + private predicate localFlowStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1) + ) + } + + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2) + ) + } + + private predicate additionalLocalStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) + ) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ + private predicate jumpStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ + private predicate additionalJumpStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate additionalJumpStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + pragma[nomagic] + private predicate readSetEx(NodeEx node1, ContentSet c, NodeEx node2) { + readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and + stepFilter(node1, node2) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + Config::allowImplicitRead(n, c) + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate read(NodeEx node1, Content c, NodeEx node2) { + exists(ContentSet cs | + readSetEx(node1, cs, node2) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate clearsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + clearsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate expectsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + expectsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + pragma[nomagic] + private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } + + pragma[nomagic] + private predicate hasReadStep(Content c) { read(_, c, _) } + + pragma[nomagic] + private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { + store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), + contentType) and + hasReadStep(tc.getContent()) and + stepFilter(node1, node2) + } + + pragma[nomagic] + private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) + } + + pragma[nomagic] + private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) + } + + /** + * Holds if field flow should be used for the given configuration. + */ + private predicate useFieldFlow() { Config::fieldFlowBranchLimit() >= 1 } + + private predicate hasSourceCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate sourceCallCtx(CallContext cc) { + if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny + } + + private predicate hasSinkCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if flow from `p` to a return node of kind `kind` is allowed. + * + * We don't expect a parameter to return stored in itself, unless + * explicitly allowed + */ + bindingset[p, kind] + private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { + exists(ParameterPosition pos | p.isParameterOf(_, pos) | + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + allowParameterReturnInSelfCached(p.asNode()) + ) + } + + private module Stage1 implements StageSig { + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } + + private class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + pragma[assume_small_delta] + private predicate fwdFlow(NodeEx node, Cc cc) { + sourceNode(node, _) and + if hasSourceCallCtx() then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc) | + localFlowStepEx(mid, node) or + additionalLocalFlowStep(mid, node) or + additionalLocalStateStep(mid, _, node, _) ) or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + exists(NodeEx mid | fwdFlow(mid, _) and cc = false | + jumpStepEx(mid, node) or + additionalJumpStep(mid, node) or + additionalJumpStateStep(mid, _, node, _) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) + exists(NodeEx mid | + useFieldFlow() and + fwdFlow(mid, cc) and + storeEx(mid, _, node, _) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) + exists(ContentSet c | + fwdFlowReadSet(c, node, cc) and + fwdFlowConsCandSet(c, _) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) + fwdFlowIn(_, _, _, node) and + cc = true or // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) + fwdFlowOut(_, node, false) and + cc = false or // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) + exists(DataFlowCall call | + fwdFlowOutFromArg(call, node) and + fwdFlowIsEntered(call, cc) ) } + // inline to reduce the number of iterations pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and + private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { + // call context cannot help reduce virtual dispatch + fwdFlow(arg, cc) and + viableParamArgEx(call, p, arg) and + not fullBarrier(p) and ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) + cc = false + or + cc = true and + not reducedViableImplInCallContext(call, _, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil + // call context may help reduce virtual dispatch + exists(DataFlowCallable target | + fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and + target = viableImplInSomeFwdFlowCallContextExt(call) and + cc = true ) - or + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc) { fwdFlowIn(call, _, cc, _) } + + pragma[nomagic] + private predicate fwdFlowInReducedViableImplInSomeCallContext( + DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target + ) { + fwdFlow(arg, true) and + viableParamArgEx(call, p, arg) and + reducedViableImplInCallContext(call, _, _) and + target = p.getEnclosingCallable() and + not fullBarrier(p) + } + + /** + * Gets a viable dispatch target of `call` in the context `ctx`. This is + * restricted to those `call`s for which a context might make a difference, + * and to `ctx`s that are reachable in `fwdFlow`. + */ + pragma[nomagic] + private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { + exists(DataFlowCall ctx | + fwdFlowIsEntered(ctx, _) and + result = viableImplInCallContextExt(call, ctx) + ) + } + + private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + + pragma[nomagic] + private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() + fwdFlow(mid, cc) and + readSetEx(mid, c, node) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node) and + useFieldFlow() and + fwdFlow(mid, _) and + storeEx(mid, tc, node, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `cs` may be interpreted in a read as the target of some store + * into `c`, in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCandSet(ContentSet cs, Content c) { + fwdFlowConsCand(c) and + c = cs.getAReadContent() + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc) { + exists(RetNodeEx ret | + fwdFlow(ret, cc) and + ret.getReturnPosition() = pos + ) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out) { + fwdFlowOut(call, out, true) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2) or + additionalJumpStateStep(node1, state1, _, state2) + | + fwdFlow(node1) + ) + } + + private predicate fwdFlowState(FlowState state) { + sourceNode(_, state) + or + exists(FlowState state0 | + fwdFlowState(state0) and + stateStepFwd(state0, state) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + private predicate revFlow(NodeEx node, boolean toReturn) { + revFlow0(node, toReturn) and + fwdFlow(node) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn) { + exists(FlowState state | + fwdFlow(node) and + sinkNode(node, state) and + fwdFlowState(state) and + if hasSinkCallCtx() then toReturn = true else toReturn = false ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, toReturn) | + localFlowStepEx(node, mid) or + additionalLocalFlowStep(node, mid) or + additionalLocalStateStep(node, _, mid, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, _) and toReturn = false | + jumpStepEx(node, mid) or + additionalJumpStep(node, mid) or + additionalJumpStateStep(node, _, mid, _) ) or // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) + exists(Content c | + revFlowStore(c, node, toReturn) and + revFlowConsCand(c) ) or // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) + exists(NodeEx mid, ContentSet c | + readSetEx(node, c, mid) and + fwdFlowConsCandSet(c, _) and + revFlow(mid, toReturn) ) or // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) + revFlowIn(_, node, false) and + toReturn = false or // flow out of a callable exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) + revFlowOut(pos) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + or + // flow through a callable + exists(DataFlowCall call | + revFlowInToReturn(call, node) and + revFlowIsReturned(call, toReturn) ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c } /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. + * Holds if `c` is the target of a read in the flow covered by `revFlow`. */ pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) + private predicate revFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, ContentSet cs | + fwdFlow(node) and + readSetEx(node, cs, mid) and + fwdFlowConsCandSet(cs, c) and + revFlow(pragma[only_bind_into](mid), _) ) } pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn) and + fwdFlowConsCand(c) and + storeEx(node, tc, mid, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + pragma[nomagic] + additional predicate revFlowIsReadAndStored(Content c) { + revFlowConsCand(c) and + revFlowStore(c, _, _) + } + + pragma[nomagic] + additional predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + fwdFlowReturnPosition(pos, _) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos) { + exists(NodeEx out | + revFlow(out, _) and + viableReturnPosOutNodeCandFwd1(_, pos, out) ) } pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) + additional predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + fwdFlowIn(call, arg, _, p) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate revFlowIn(DataFlowCall call, ArgNodeEx arg, boolean toReturn) { + exists(ParamNodeEx p | + revFlow(p, toReturn) and + viableParamArgNodeCandFwd1(call, p, arg) + ) } pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg) { + revFlowIn(call, arg, true) } /** @@ -1866,896 +771,1717 @@ private module MkStage { * reaching an argument of `call`. */ pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn) { + exists(NodeEx out | + revFlow(out, toReturn) and + fwdFlowOutFromArg(call, out) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2) or + additionalJumpStateStep(node1, state1, node2, state2) + | + revFlow(node1, _) and + revFlow(node2, _) and + fwdFlowState(state1) and + fwdFlowState(state2) + ) + } + + pragma[nomagic] + additional predicate revFlowState(FlowState state) { + exists(NodeEx node | + sinkNode(node, state) and + revFlow(node, _) and + fwdFlowState(state) + ) + or + exists(FlowState state0 | + revFlowState(state0) and + stateStepRev(state, state0) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) + exists(Content c | + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, node2, contentType) and + c = tc.getContent() and + exists(ap1) ) } pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() + predicate readStepCand(NodeEx n1, Content c, NodeEx n2) { + revFlowIsReadAndStored(c) and + read(n1, c, n2) and + revFlow(n2) + } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { + revFlow(node) and + exists(ap) + } + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap) { + revFlow(node, _) and + exists(state) and + exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node) { + revFlow(node, true) and + fwdFlow(node, true) and + not inBarrier(node) and + not outBarrier(node) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(DataFlowCallable c, ReturnKindExt kind | + throughFlowNodeCand(p) and + returnFlowCallableNodeCand(c, kind) and + p.getEnclosingCallable() = c and + exists(ap) and + parameterFlowThroughAllowed(p, kind) ) } pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + throughFlowNodeCand(ret) and + kind = ret.getKind() and + exists(argAp) and + exists(ap) } pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn) and + revFlowInToReturn(call, arg) and + revFlowIsReturned(call, toReturn) ) } additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) + nodes = count(NodeEx node | fwdFlow(node)) and + fields = count(Content f0 | fwdFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b)) or fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) + nodes = count(NodeEx node | revFlow(node, _)) and + fields = count(Content f0 | revFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b)) } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } + /* End: Stage 1 logic. */ } - class CcCall extends Cc { - CcCall() { this = true } + pragma[noinline] + private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + localFlowStepEx(node1, node2) } - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + additionalLocalFlowStep(node1, node2) } - Cc ccNone() { result = false } + pragma[nomagic] + private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { + Stage1::revFlow(out) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) + } - CcCall ccSomeCall() { result = true } + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out + ) { + exists(ReturnPosition pos | + viableReturnPosOutNodeCand1(call, pos, out) and + pos = ret.getReturnPosition() and + kind = pos.getKind() and + Stage1::revFlow(ret) and + not outBarrier(ret) and + not inBarrier(out) + ) + } - class LocalCc = Unit; + pragma[nomagic] + private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg) and + Stage1::revFlow(arg) + } - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { + viableParamArgNodeCand1(call, p, arg) and + Stage1::revFlow(p) and + not outBarrier(arg) and + not inBarrier(p) + } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} + /** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int branch(NodeEx n1) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) + } -private module Level1CallContext { - class Cc = CallContext; + /** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int join(NodeEx n2) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) + } - class CcCall = CallContextCall; + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, ret, kind, out) and + exists(int b, int j | + b = branch(ret) and + j = join(out) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, arg, p) and + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - class CcNoCall = CallContextNoCall; + private signature module StageSig { + class Ap; - Cc ccNone() { result instanceof CallContextAny } + predicate revFlow(NodeEx node); - CcCall ccSomeCall() { result instanceof CallContextSomeCall } + predicate revFlowAp(NodeEx node, Ap ap); + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap); + + predicate callMayFlowThroughRev(DataFlowCall call); + + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap); + + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ); + + predicate readStepCand(NodeEx n1, Content c, NodeEx n2); + } + + private module MkStage { + class ApApprox = PrevStage::Ap; + + signature module StageParam { + class Ap; + + class ApNil extends Ap; + + bindingset[result, ap] + ApApprox getApprox(Ap ap); + + ApNil getApNil(NodeEx node); + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail); + + /** + * An approximation of `Content` that corresponds to the precision level of + * `Ap`, such that the mappings from both `Ap` and `Content` to this type + * are functional. + */ + class ApHeadContent; + + ApHeadContent getHeadContent(Ap ap); + + ApHeadContent projectToHeadContent(Content c); + + class ApOption; + + ApOption apNone(); + + ApOption apSome(Ap ap); + + class Cc; + + class CcCall extends Cc; + + // TODO: member predicate on CcCall + predicate matchesCall(CcCall cc, DataFlowCall call); + + class CcNoCall extends Cc; + + Cc ccNone(); + + CcCall ccSomeCall(); + + class LocalCc; + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc); + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ); + + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ); + + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ); + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap); + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType); + } + + module Stage implements StageSig { + import Param + + /* Begin: Stage logic. */ + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + private predicate revFlowApAlias(NodeEx node, ApApprox apa) { + PrevStage::revFlowAp(node, apa) + } + + pragma[nomagic] + private predicate flowIntoCallApa( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa + ) { + flowIntoCall(call, arg, p, allowsFieldFlow) and + PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and + revFlowApAlias(arg, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowOutOfCallApa( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + ApApprox apa + ) { + flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and + PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and + revFlowApAlias(ret, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + ApApprox argApa, ApApprox apa + ) { + exists(ReturnKindExt kind | + flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + ) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `summaryCtx` and `argAp` record the + * corresponding parameter position and access path of that argument, respectively. + */ + pragma[nomagic] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, ap) + } + + pragma[inline] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + ) { + fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + sourceNode(node, state) and + (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + summaryCtx = TParamNodeNone() and + ap = getApNil(node) and + apa = getApprox(ap) + or + exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + localCc = getLocalCc(mid, cc) + | + localStep(mid, state0, node, state, true, _, localCc) and + ap = ap0 and + apa = apa0 + or + localStep(mid, state0, node, state, false, ap, localCc) and + ap0 instanceof ApNil and + apa = getApprox(ap) + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + jumpStepEx(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, _, nil) and + additionalJumpStep(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, _, nil) and + additionalJumpStateStep(mid, state0, node, state) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + ap = apCons(tc, ap0) and + apa = getApprox(ap) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(ap0, c, ap) and + apa = getApprox(ap) + ) + or + // flow into a callable + fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + if PrevStage::parameterMayFlowThrough(node, apa) + then ( + summaryCtx = TParamNodeSome(node.asNode()) and + argAp = apSome(ap) + ) else ( + summaryCtx = TParamNodeNone() and argAp = apNone() + ) + or + // flow out of a callable + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and + inner = ret.getEnclosingCallable() and + cc = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + or + // flow through a callable + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(DataFlowType contentType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, _) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate readStepCand(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + PrevStage::readStepCand(node1, c, node2) and + apc = projectToHeadContent(c) + } + + bindingset[node1, apc] + pragma[inline_late] + private predicate readStepCand0(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + readStepCand(node1, apc, c, node2) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + apc = getHeadContent(ap) and + readStepCand0(node1, apc, c, node2) + ) + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg( + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + ApApprox argApa, Ap ap, ApApprox apa + ) { + exists(ReturnKindExt kind | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + + pragma[inline] + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + } + + pragma[nomagic] + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap + ) { + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa)) and + PrevStage::parameterMayFlowThrough(p, apa) and + PrevStage::callMayFlowThroughRev(call) + ) + } + + pragma[nomagic] + private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + } + + private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(ap1, c, ap2) + } + + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa) + } + + pragma[nomagic] + private predicate returnFlowsThrough( + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + Ap ap + ) { + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap + ) { + exists(ApApprox argApa | + flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), + allowsFieldFlow, argApa) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + if allowsFieldFlow = false then argAp instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowIntoCallAp( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap + ) { + exists(ApApprox apa | + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + fwdFlow(arg, _, _, _, _, ap, apa) + ) + } + + pragma[nomagic] + private predicate flowOutOfCallAp( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, + Ap ap + ) { + exists(ApApprox apa | + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and + fwdFlow(ret, _, _, _, _, ap, apa) and + pos = ret.getReturnPosition() + ) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink. + * + * The parameter `returnCtx` records whether (and how) the node must be returned + * from the enclosing callable in order to reach a sink, and if so, `returnAp` + * records the access path of the returned value. + */ + pragma[nomagic] + additional predicate revFlow( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + revFlow0(node, state, returnCtx, returnAp, ap) and + fwdFlow(node, state, _, _, _, ap) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + fwdFlow(node, state, _, _, _, ap) and + sinkNode(node, state) and + ( + if hasSinkCallCtx() + then returnCtx = TReturnCtxNoFlowThrough() + else returnCtx = TReturnCtxNone() + ) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, nil) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStepEx(node, mid) and + revFlow(mid, state, _, _, ap) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStep(node, mid) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStateStep(node, state, mid, state0) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowConsCand(ap0, c, ap) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, returnCtx, returnAp, ap0) and + readStepFwd(node, ap, _, mid, ap0) + ) + or + // flow into a callable + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, TReturnCtxNone(), returnAp, ap) and + flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and + (if allowsFieldFlow = false then ap instanceof ApNil else any()) and + returnCtx = TReturnCtxNone() + ) + or + // flow through a callable + exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap) and + if returnFlowsThrough(node, pos, state, _, _, _, ap) + then ( + returnCtx = TReturnCtxMaybeFlowThrough(pos) and + returnAp = apSome(ap) + ) else ( + returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() + ) + ) + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + ReturnCtx returnCtx, ApOption returnAp + ) { + revFlow(mid, state, returnCtx, returnAp, ap0) and + storeStepFwd(node, ap, tc, mid, ap0) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, + ApOption returnAp, Ap ap + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, returnCtx, returnAp, ap) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowParamToReturn( + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap + ) { + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap)) + } + + pragma[nomagic] + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp + ) { + revFlowParamToReturn(p, state, pos, innerReturnAp, ap) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + matchesCall(ccc, call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ) { + exists(Ap ap2, Content c | + PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowConsCand(ap2, c, ap1) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and + readStepFwd(node1, ap1, c, node2, ap2) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + ) + } + + additional predicate revFlow(NodeEx node, FlowState state) { revFlow(node, state, _, _, _) } + + predicate revFlow(NodeEx node, FlowState state, Ap ap) { revFlow(node, state, _, _, ap) } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _, _, _, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) { + revFlow(node, state, ap) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + + private predicate validAp(Ap ap) { + revFlow(_, _, _, _, ap) and ap instanceof ApNil + or + exists(TypedContent head, Ap tail | + consCand(head, tail) and + ap = apCons(head, tail) + ) + } + + additional predicate consCand(TypedContent tc, Ap ap) { + revConsCand(tc, ap) and + validAp(ap) + } + + pragma[nomagic] + private predicate parameterFlowsThroughRev( + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp + ) { + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap) and + parameterFlowThroughAllowed(p, pos.getKind()) + } + + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(ReturnPosition pos | + returnFlowsThrough(_, pos, _, _, p, ap, _) and + parameterFlowsThroughRev(p, ap, pos, _) + ) + } + + pragma[nomagic] + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + parameterFlowsThroughRev(p, argAp, pos, ap) and + kind = pos.getKind() + ) + } + + pragma[nomagic] + private predicate revFlowThroughArg( + DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, + Ap ap + ) { + exists(ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(arg, state, returnCtx, returnAp, ap) and + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap) + ) + } + + additional predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and + fields = count(TypedContent f0 | consCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + states = count(FlowState state | revFlow(_, state, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | + revFlow(n, state, returnCtx, retAp, ap) + ) + } + /* End: Stage logic. */ + } + } + + private module BooleanCallContext { + class Cc extends boolean { + Cc() { this in [true, false] } + } + + class CcCall extends Cc { + CcCall() { this = true } + } + + /** Holds if the call context may be `call`. */ + predicate matchesCall(CcCall cc, DataFlowCall call) { any() } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } - module NoLocalCallContext { class LocalCc = Unit; bindingset[node, cc] LocalCc getLocalCc(NodeEx node, Cc cc) { any() } bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + } + + private module Level1CallContext { + class Cc = CallContext; + + class CcCall = CallContextCall; + + pragma[inline] + predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + module NoLocalCallContext { + class LocalCc = Unit; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + module LocalCallContext { + class LocalCc = LocalCallContext; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() } } - module LocalCallContext { - class LocalCc = LocalCallContext; + private module Stage2Param implements MkStage::StageParam { + private module PrevStage = Stage1; - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) + class Ap extends boolean { + Ap() { this in [true, false] } } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + class ApNil extends Ap { + ApNil() { this = false } } + + bindingset[result, ap] + PrevStage::Ap getApprox(Ap ap) { any() } + + ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + class ApHeadContent = Unit; + + pragma[inline] + ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + + ApHeadContent projectToHeadContent(Content c) { any() } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2) + ) and + exists(ap) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + predicate flowIntoCall = flowIntoCallNodeCand1/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::revFlowIsReadAndStored(c) and + expectsContentEx(node, c) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + PrevStage::revFlowState(state) and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + ap = true and + expectsContentCand(node) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + private module Stage2 implements StageSig { + import MkStage::Stage } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) + private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) + pragma[nomagic] + private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) + private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) or + expectsContentCached(this.asNode(), _) + } } - } - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowEntry(NodeEx node, FlowState state) { + Stage2::revFlow(node, state) and + ( + sourceNode(node, state) + or + jumpStepEx(_, node) + or + additionalJumpStep(_, node) + or + additionalJumpStateStep(_, _, node, state) + or + node instanceof ParamNodeEx + or + node.asNode() instanceof OutNodeExt + or + Stage2::storeStepCand(_, _, _, node, _) + or + Stage2::readStepCand(_, _, node) + or + node instanceof FlowCheckNode + or + exists(FlowState s | + additionalLocalStateStep(_, s, node, state) and + s != state + ) + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state) { + exists(NodeEx next | Stage2::revFlow(next, state) | + jumpStepEx(node, next) or + additionalJumpStep(node, next) or + flowIntoCallNodeCand2(_, node, next, _) or + flowOutOfCallNodeCand2(_, node, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _) or + Stage2::readStepCand(node, _, next) + ) or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s) | + additionalJumpStateStep(node, state, next, s) + or + additionalLocalStateStep(node, state, next, s) and s != state ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } + Stage2::revFlow(node, state) and + node instanceof FlowCheckNode + or + sinkNode(node, state) + } - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false) + or + additionalLocalStateStep(node1, state1, node2, state2) and + Stage2::revFlow(node1, state1, false) and + Stage2::revFlowAlias(node2, state2, false) + } - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, + LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + localFlowEntry(node1, pragma[only_bind_into](state)) and + ( + localFlowStepNodeCand1(node1, node2) and + preservesValue = true and + t = node1.getDataFlowType() and // irrelevant dummy value + Stage2::revFlow(node2, pragma[only_bind_into](state)) + or + additionalLocalFlowStepNodeCand2(node1, state, node2, state) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + exists(NodeEx mid | + localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and + localFlowStepNodeCand1(mid, node2) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state)) + ) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state, mid, _, _, cc) and + additionalLocalFlowStepNodeCand2(mid, state, node2, state) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() + ) ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and + localFlowExit(node2, state1) and + state1 = state2 or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and + state1 != state2 and + preservesValue = false and + t = node2.getDataFlowType() and + callContext.relevantFor(node1.getEnclosingCallable()) and + not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | + isUnreachableInCallCached(node1.asNode(), call) or + isUnreachableInCallCached(node2.asNode(), call) ) + } + } + + private import LocalFlowBigStep + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + predicate projectToHeadContent = getContentApprox/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + import BooleanCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApproxAccessPathFrontNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + predicate flowIntoCall = flowIntoCallNodeCand2/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage3 implements StageSig { + import MkStage::Stage + } + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import BooleanCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and + exists(lcc) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + not clear(node, ap) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage4 implements StageSig { + import MkStage::Stage + } + + /** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ + private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { + exists(AccessPathFront apf | + Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) ) } /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() + private predicate expensiveLen2unfolding(TypedContent tc) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage4::consCand(tc, TFrontNil(t)) and + not expensiveLen2unfolding(tc) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage4::consCand(tc1, TFrontHead(tc2)) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc) + } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) + /** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ + abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} + private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; -private module Stage3 implements StageSig { - import MkStage::Stage -} + AccessPathApproxNil() { this = TNil(t) } -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; + override string toString() { result = concat(": " + ppReprType(t)) } - class Ap = AccessPathFront; + override TypedContent getHead() { none() } - class ApNil = AccessPathFrontNil; + override int len() { result = 0 } - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + override DataFlowType getType() { result = t } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + abstract private class AccessPathApproxCons extends AccessPathApprox { } - class ApHeadContent = Content; + private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + AccessPathApproxConsNil() { this = TConsNil(tc, t) } - ApHeadContent projectToHeadContent(Content c) { result = c } + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } - class ApOption = AccessPathFrontOption; + override TypedContent getHead() { result = tc } - ApOption apNone() { result = TAccessPathFrontNone() } + override int len() { result = 1 } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + override DataFlowType getType() { result = tc.getContainerType() } - import BooleanCallContext + override AccessPathFront getFront() { result = TFrontHead(tc) } - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } } - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } + override TypedContent getHead() { result = tc1 } - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } + override int len() { result = len } - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } + override DataFlowType getType() { result = tc1.getContainerType() } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + override AccessPathFront getFront() { result = TFrontHead(tc1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( result = TConsCons(tc2, _, len - 1) or len = 2 and @@ -2763,1561 +2489,581 @@ private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { or result = TCons1(tc2, len - 1) ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) + } + } + + private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage4::consCand(tc, TFrontNil(t)) and + result = TNil(t) + ) ) - ) + } } -} -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + /** Gets the access path obtained by popping `tc` from `ap`, if any. */ + private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto `ap`. */ + private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) + private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } } -} -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; + private module Stage5Param implements MkStage::StageParam { + private module PrevStage = Stage4; - class Ap = AccessPathApprox; + class Ap = AccessPathApprox; - class ApNil = AccessPathApproxNil; + class ApNil = AccessPathApproxNil; + + pragma[nomagic] + PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + import Level1CallContext + import LocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + } + + private module Stage5 = MkStage::Stage; pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc + private predicate nodeMayUseSummary0( + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + exists(AccessPathApprox apa0 | + Stage5::parameterMayFlowThrough(p, _) and + Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + TAccessPathApproxSome(apa), apa0) ) } pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + private predicate nodeMayUseSummary(NodeEx n, FlowState state, AccessPathApprox apa) { + exists(ParamNodeEx p | + Stage5::parameterMayFlowThrough(p, apa) and + nodeMayUseSummary0(n, p, state, apa) ) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + Stage5::parameterMayFlowThrough(p, ap.getApprox()) and + Stage5::revFlow(p, state, _) + } - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} + /** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ + abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); + } -private module Stage5 = MkStage::Stage; + /** A summary context from which no flow summary can be generated. */ + private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } + } -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} + /** A summary context from which a flow summary can be generated. */ + private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ + private int count1to2unfold(AccessPathApproxCons1 apa) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + ) ) } -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and + private int countNodesUsingAccessPath(AccessPathApprox apa) { result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) + strictcount(NodeEx n, FlowState state | + Stage5::revFlow(n, state, apa) or nodeMayUseSummary(n, state, apa) ) - ) -} + } -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else + /** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ + private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa) { exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and + aps = count1to2unfold(apa) and + nodes = countNodesUsingAccessPath(apa) and accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() + apLimit < aps and + tupleLimit < (aps - 1) * nodes ) } -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() + private AccessPathApprox getATail(AccessPathApprox apa) { + exists(TypedContent head | + apa.pop(head) = result and + Stage5::consCand(head, result) ) } -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" + /** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ + private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { + if apa.getHead().forceHighPrecision() + then unfold = true else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa) and + nodes = countNodesUsingAccessPath(apa) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) + /** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ + pragma[assume_small_delta] + private int countAps(AccessPathApprox apa) { + evalUnfold(apa, false) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa)) or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" + evalUnfold(apa, false) and + result = count1to2unfold(apa) and + not expensiveLen1to2unfolding(apa) or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) + evalUnfold(apa, true) and + result = countPotentialAps(apa) } - private string ppCtx() { - this instanceof PathNodeSink and result = "" + /** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ + language[monotonicAggregates] + pragma[assume_small_delta] + private int countPotentialAps(AccessPathApprox apa) { + apa instanceof AccessPathApproxNil and result = 1 or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) + private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false) and + head = apa.getHead() and + tail.getApprox() = getATail(apa) + ) } or - TCallableSrc() or - TCallableSink() + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + not expensiveLen1to2unfolding(apa) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + expensiveLen1to2unfolding(apa) and + apa.len() = len and + head = apa.getHead() + ) + } - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + private newtype TPathNode = + pragma[assume_small_delta] + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + // A PathNode is introduced by a source ... + Stage5::revFlow(node, state) and + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + pathStep(_, node, state, cc, sc, ap) and + Stage5::revFlow(node, state, ap.getApprox()) + } or + TPathNodeSink(NodeEx node, FlowState state) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() + ) + } or + TPathNodeSourceGroup(string sourceGroup) { + exists(PathNodeImpl source | sourceGroup = source.getSourceGroup()) + } or + TPathNodeSinkGroup(string sinkGroup) { + exists(PathNodeSink sink | sinkGroup = sink.getSinkGroup()) + } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the * tracked object. The final type indicates the type of the tracked object. */ - private class PartialAccessPath extends TPartialAccessPath { + private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() } - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } } - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } } - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + pragma[assume_small_delta] + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + pragma[assume_small_delta] + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } - } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) } } - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) + private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage5::consCand(head1, result.getApprox()) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = + "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } } - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) + private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } + AccessPathCons1() { this = TAccessPathCons1(head, len) } - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + override TypedContent getHead() { result = head } - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) + override AccessPath getTail() { + Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + } - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + override AccessPathFrontHead getFront() { result = TFrontHead(head) } - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } + } + + abstract private class PathNodeImpl extends TPathNode { + /** Gets the `FlowState` of this node. */ + abstract FlowState getState(); + + /** Holds if this node is a source. */ + abstract predicate isSource(); + + abstract PathNodeImpl getASuccessorImpl(); + + private PathNodeImpl getASuccessorIfHidden() { + this.isHidden() and + result = this.getASuccessorImpl() + } + + pragma[nomagic] + private PathNodeImpl getANonHiddenSuccessor0() { + result = this.getASuccessorIfHidden*() and + not result.isHidden() + } + + final PathNodeImpl getANonHiddenSuccessor() { + result = this.getASuccessorImpl().getANonHiddenSuccessor0() and + not this.isHidden() + } + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + not Config::includeHiddenNodes() and ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + ) } - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } + string getSourceGroup() { + this.isSource() and + Config::sourceGrouping(this.getNodeEx().asNode(), result) + } + + predicate isFlowSource() { + this.isSource() and not exists(this.getSourceGroup()) + or + this instanceof PathNodeSourceGroup + } + + predicate isFlowSink() { + this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or + this instanceof PathNodeSinkGroup + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { /** Gets a textual representation of this element. */ string toString() { result = this.getNodeEx().toString() + this.ppAp() } @@ -4341,305 +3087,335 @@ private module FlowExploration { ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + } + + /** Holds if `n` can reach a sink. */ + private predicate directReach(PathNodeImpl n) { + n instanceof PathNodeSink or + n instanceof PathNodeSinkGroup or + directReach(n.getANonHiddenSuccessor()) + } + + /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ + private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } + + /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ + private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { + n1.getANonHiddenSuccessor() = n2 and directReach(n2) + } + + private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } + final Node getNode() { super.getNodeEx().projectToNode() = result } - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) } - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group) } } /** * Provides the query predicates needed to include a graph in a path-problem query. */ - module PartialPathGraph { + module PathGraph implements PathGraphSig { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) + } } - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + /** + * An intermediate flow graph node. This is a tuple consisting of a `Node`, + * a `FlowState`, a `CallContext`, a `SummaryCtx`, and an `AccessPath`. + */ + private class PathNodeMid extends PathNodeImpl, TPathNodeMid { NodeEx node; FlowState state; CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; + SummaryCtx sc; + AccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } CallContext getCallContext() { result = cc } - TSummaryCtx1 getSummaryCtx1() { result = sc1 } + SummaryCtx getSummaryCtx() { result = sc } - TSummaryCtx2 getSummaryCtx2() { result = sc2 } + AccessPath getAp() { result = ap } - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) } - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + } + + predicate isAtSink() { + sinkNode(node, state) and + ap instanceof AccessPathNil and + if hasSinkCallCtx() + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state } } - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + /** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ + private class PathNodeSink extends PathNodeImpl, TPathNodeSink { NodeEx node; FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + PathNodeSink() { this = TPathNodeSink(node, state) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) } - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + override predicate isSource() { sourceNode(node, state) } - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) } + } - RevPartialAccessPath getAp() { result = ap } + private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { + string sourceGroup; - override Configuration getConfiguration() { result = config } + PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup) } - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } + override NodeEx getNodeEx() { none() } - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup } + + override predicate isSource() { none() } + + override string toString() { result = sourceGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 } } - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { + string sinkGroup; + + PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup) } + + override NodeEx getNodeEx() { none() } + + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { none() } + + override predicate isSource() { none() } + + override string toString() { result = sinkGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 + } + } + + private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + LocalCallContext localCC ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and + midnode = mid.getNodeEx() and state = mid.getState() and cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() } - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + /** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) + or + exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + state = mid.getState() and + cc = mid.getCallContext() } pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config + private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + state = mid.getState() and + cc = mid.getCallContext() } - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() + apa = mid.getAp().getApprox() } pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + pathOutOfCallable0(mid, pos, state, innercc, apa) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4648,53 +3424,86 @@ private module FlowExploration { ) } - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) + pragma[noinline] + private NodeEx getAnOutNodeFlow(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa) { + result.asNode() = kind.getAnOutNode(call) and + Stage5::revFlow(result, _, apa) + } + + /** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ + pragma[noinline] + private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa | + pathOutOfCallable1(mid, call, kind, state, cc, apa) and + out = getAnOutNodeFlow(kind, call, apa) ) } + /** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and parameterMatch(ppos, apos) ) } pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) + exists(ParamNodeEx p | + Stage5::revFlow(p, _, apa) and + p.isParameterOf(callable, pos) + ) } - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config + pragma[nomagic] + private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) + ) + } + + /** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ + pragma[nomagic] + private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call + ) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4702,252 +3511,1108 @@ private module FlowExploration { ) } + /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and + exists(RetNodeEx ret | + pathNode(_, ret, state, cc, sc, ap, _) and kind = ret.getKind() and + apa = ap.getApprox() and + parameterFlowThroughAllowed(sc.getParamNode(), kind) + ) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa + ) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa) + ) + } + + /** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ + pragma[noinline] + private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + out = getAnOutNodeFlow(kind, call, apa) + ) + } + + private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _) and + not arg.isHidden() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, + AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _) or + storeEx(n1, _, n2, _) or + readSetEx(n1, _, n2) + ) + } + + pragma[nomagic] + private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { + succ = pred.getANonHiddenSuccessor() and + succNode = succ.getNodeEx() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + hasSuccessor(pragma[only_bind_into](arg), par, p) and + not ret.isHidden() and + pathNode(out0, o, sout, _, _, apout, _) + | + out = out0 or out = out0.projectToSink() + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNodeImpl n) { + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNodeImpl mid | + retReach(mid) and + n.getANonHiddenSuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } + } + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { + exists(PathNodeImpl flowsource, PathNodeImpl flowsink | + source = flowsource and sink = flowsink + | + flowsource.isFlowSource() and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.isFlowSink() + ) + } + + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { + flowsource.isSource() and + flowsource.getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink + } + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + + private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNodeImpl pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = + count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn) + } + + /** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ + predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples + ) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "5 Fwd" and + n = 50 and + Stage5::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and + n = 55 and + Stage5::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) + } + + module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { + exists(NodeEx node1, NodeEx node2 | + jumpStepEx(node1, node2) + or + additionalJumpStep(node1, node2) + or + additionalJumpStateStep(node1, _, node2, _) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c) { + exists(Node n | Config::isSource(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) + } + + private predicate interestingCallableSink(DataFlowCallable c) { + exists(Node n | Config::isSink(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c) { + interestingCallableSrc(c) or + interestingCallableSink(c) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2 | + callableStep(c1, c2) and + ce1 = TCallable(c1) and + ce2 = TCallable(c2) + ) + or + exists(Node n | + ce1 = TCallableSrc() and + Config::isSource(n, _) and + ce2 = TCallable(getNodeEnclosingCallable(n)) + ) + or + exists(Node n | + ce2 = TCallableSink() and + Config::isSink(n, _) and + ce1 = TCallable(getNodeEnclosingCallable(n)) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } + + private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state) or + sinkNode(_, state) or + additionalLocalStateStep(_, state, _, _) or + additionalLocalStateStep(_, _, _, state) or + additionalJumpStateStep(_, state, _, _) or + additionalJumpStateStep(_, _, _, state) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + distSrc(node.getEnclosingCallable()) <= explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap + ) { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(explorationLimit()) + or + revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and + not clearsContentEx(node, ap.getHead()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead()) + ) and + not fullBarrier(node) and + not stateBarrier(node, state) and + distSink(node.getEnclosingCallable()) <= explorationLimit() + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + not fullBarrier(node) and + not stateBarrier(node, state) and + not clearsContentEx(node, ap.getHead().getContent()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead().getContent()) + ) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { result = distSrc(this.getNodeEx().getEnclosingCallable()) } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { result = distSink(this.getNodeEx().getEnclosingCallable()) } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + } + + predicate isSource() { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp()) + } + + predicate isSink() { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + or + additionalLocalFlowStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + partialPathStoreStep(mid, _, _, node, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and + sc3 = mid.getSummaryCtx3() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + or + partialPathOutOfCallable(mid, node, state, cc, ap) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + storeEx(midNode, tc, node, contentType) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { + partialPathStoreStep(_, ap1, tc, _, ap2) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node) and + ap.getHead() = tc and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and ap = mid.getAp() - ) - } + } - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + | + out.asNode() = kind.getAnOutNode(call) + ) + } - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[nomagic] + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + ) { + localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and + ap = mid.getAp() + or + additionalLocalFlowStep(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + jumpStepEx(node, mid.getNodeEx()) and + state = mid.getState() and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and + ap = mid.getAp() + or + additionalJumpStep(node, mid.getNodeEx()) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } + sc3 = mid.getSummaryCtx3() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) + pragma[nomagic] + private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + revPartialPathReadStep(_, ap1, c, _, ap2) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + storeEx(node, tc, midNode, _) and + ap.getHead() = c and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } + + private predicate partialFlow(PartialPathNode source, PartialPathNode node) { + source.isFwdSource() and + node = source.getASuccessor+() + } + + private predicate revPartialFlow(PartialPathNode node, PartialPathNode sink) { + sink.isRevSink() and + node.getASuccessor+() = sink + } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink) and + dist = node.getSinkDistance() + } } } - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll new file mode 100644 index 00000000000..e6bdc74cceb --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl1.qll @@ -0,0 +1,396 @@ +/** + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +private import DataFlowImpl +import DataFlowImplCommonPublic +import FlowStateString + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited. + */ + deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited when + * the flow state is `state` + */ + deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * DEPRECATED: Use `FlowExploration` instead. + * + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + deprecated int explorationLimit() { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (for example in a `path-problem` query). + */ + predicate includeHiddenNodes() { none() } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +/** A bridge class to access the deprecated `isBarrierGuard`. */ +private class BarrierGuardGuardedNodeBridge extends Unit { + abstract predicate guardedNode(Node n, Configuration config); + + abstract predicate guardedNode(Node n, FlowState state, Configuration config); +} + +private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { + deprecated override predicate guardedNode(Node n, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + } + + deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g, state) and + n = g.getAGuardedNode() + ) + } +} + +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) + or + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) + or + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) + or + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 + } + + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) + } + + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } + + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } + + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) + } + + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) + } + + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } +} + +private import Impl as I +import I + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof I::PathNode { + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { result = super.getNode() } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = getState(super.getState()) } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = getConfig(super.getState()) } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getASuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } + + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } + + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } +} + +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink + ) +} + +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config +} + +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } + +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 5d3becc8078..d09fdcfca3e 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -3,15 +3,18 @@ private import DataFlowImplSpecific::Public import Cached module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; + /** Provides `FlowState = string`. */ + module FlowStateString { + /** A state value to track during data flow. */ + class FlowState = string; - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } + /** + * The default state, which is used when the state is unspecified for a source + * or a sink. + */ + class FlowStateEmpty extends FlowState { + FlowStateEmpty() { this = "" } + } } private newtype TFlowFeature = @@ -179,6 +182,7 @@ private module LambdaFlow { boolean toJump, DataFlowCallOption lastCall ) { revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and + not expectsContent(node, _) and if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode then compatibleTypes(t, getNodeDataFlowType(node)) else any() diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll index 9bbc70fbdf9..7da63f6c4fa 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplConsistency.qll @@ -18,6 +18,9 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ predicate uniqueEnclosingCallableExclude(Node n) { none() } + /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ + predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ predicate uniqueNodeLocationExclude(Node n) { none() } @@ -86,6 +89,15 @@ module Consistency { ) } + query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) { + exists(int c | + c = count(call.getEnclosingCallable()) and + c != 1 and + not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and + msg = "Call should have one enclosing callable but has " + c + "." + ) + } + query predicate uniqueType(Node n, string msg) { exists(int c | n instanceof RelevantNode and diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll index 1749de42f2c..f54e3b9a9cb 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll @@ -318,3 +318,12 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu // consistency alerts enough that most of them are interesting. } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index 79d9f85464e..bf5a54cd05d 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -3,10 +3,10 @@ */ private import cpp -private import semmle.code.cpp.dataflow.internal.FlowVar +private import FlowVar private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.controlflow.Guards -private import semmle.code.cpp.dataflow.internal.AddressFlow +private import AddressFlow cached private newtype TNode = diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll index 0c9f556a887..6632a4af18c 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/FlowVar.qll @@ -4,8 +4,8 @@ import cpp private import semmle.code.cpp.controlflow.SSA -private import semmle.code.cpp.dataflow.internal.SubBasicBlocks -private import semmle.code.cpp.dataflow.internal.AddressFlow +private import SubBasicBlocks +private import AddressFlow private import semmle.code.cpp.models.implementations.Iterator private import semmle.code.cpp.models.interfaces.PointerWrapper diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll index 52f09eb7778..9ee0fa3131b 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/SubBasicBlocks.qll @@ -75,13 +75,6 @@ class SubBasicBlock extends ControlFlowNodeBase { ) } - /** - * DEPRECATED: use `getRankInBasicBlock` instead. Note that this predicate - * returns a 0-based position, while `getRankInBasicBlock` returns a 1-based - * position. - */ - deprecated int getPosInBasicBlock(BasicBlock bb) { result = this.getRankInBasicBlock(bb) - 1 } - pragma[noinline] private int getIndexInBasicBlock(BasicBlock bb) { this = bb.getNode(result) } diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll index 6f19ad38d3d..bea9364884c 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll @@ -14,7 +14,7 @@ private import semmle.code.cpp.models.interfaces.Iterator private import semmle.code.cpp.models.interfaces.PointerWrapper private module DataFlow { - import semmle.code.cpp.dataflow.internal.DataFlowUtil + import DataFlowUtil } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll new file mode 100644 index 00000000000..7f96fe5e6fb --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTracking.qll @@ -0,0 +1,64 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ + +import TaintTrackingParameter::Public +private import TaintTrackingParameter::Private + +private module AddTaintDefaults implements + DataFlowInternal::FullStateConfigSig +{ + import Config + + predicate isBarrier(DataFlow::Node node) { + Config::isBarrier(node) or defaultTaintSanitizer(node) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + Config::isAdditionalFlowStep(node1, node2) or + defaultAdditionalTaintStep(node1, node2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + Config::allowImplicitRead(node, c) + or + ( + Config::isSink(node, _) or + Config::isAdditionalFlowStep(node, _) or + Config::isAdditionalFlowStep(node, _, _, _) + ) and + defaultImplicitTaintRead(node, c) + } +} + +/** + * Constructs a standard taint tracking computation. + */ +module Make implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import DataFlowInternal::DefaultState + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} + +/** + * Constructs a taint tracking computation using flow state. + */ +module MakeWithState implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll index 7fd632efb0e..0d73207dad9 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll @@ -2,4 +2,5 @@ import semmle.code.cpp.dataflow.internal.TaintTrackingUtil as Public module Private { import semmle.code.cpp.dataflow.DataFlow::DataFlow as DataFlow + import semmle.code.cpp.dataflow.internal.DataFlowImpl as DataFlowInternal } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow.qll similarity index 72% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow.qll index acb2fbc6808..c14ea8b7e90 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow.qll @@ -8,8 +8,8 @@ * results than the AST-based library in most scenarios. * * Unless configured otherwise, _flow_ means that the exact value of - * the source may reach the sink. We do not track flow across pointer - * dereferences or array indexing. + * the source may reach the sink. To track flow where the exact value + * may not be preserved, import `semmle.code.cpp.dataflow.new.TaintTracking`. * * To use global (interprocedural) data flow, extend the class * `DataFlow::Configuration` as documented on that class. To use local @@ -21,6 +21,11 @@ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow { - import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowImpl + import semmle.code.cpp.ir.dataflow.internal.DataFlow + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1 } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow2.qll similarity index 62% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow2.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow2.qll index 0513bd4ebcb..35c5a34a656 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow2.qll @@ -6,11 +6,15 @@ * `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a * `DataFlow4::Configuration`. * - * See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation. + * See `semmle.code.cpp.dataflow.new.DataFlow` for the full documentation. */ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow2 { - import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowImpl2 + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl2 } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow3.qll similarity index 62% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow3.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow3.qll index 571b75b37c4..e2e402835f2 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow3.qll @@ -6,11 +6,15 @@ * `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a * `DataFlow4::Configuration`. * - * See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation. + * See `semmle.code.cpp.dataflow.new.DataFlow` for the full documentation. */ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow3 { - import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowImpl3 + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl3 } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow4.qll similarity index 62% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow4.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow4.qll index 18c21e554f6..f9209abe1e1 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/DataFlow4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/DataFlow4.qll @@ -6,11 +6,15 @@ * `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a * `DataFlow4::Configuration`. * - * See `semmle.code.cpp.ir.dataflow.DataFlow` for the full documentation. + * See `semmle.code.cpp.dataflow.new.DataFlow` for the full documentation. */ import cpp +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) data flow analyses. + */ module DataFlow4 { - import experimental.semmle.code.cpp.ir.dataflow.internal.DataFlowImpl4 + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl4 } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking.qll similarity index 70% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking.qll index 43064116499..23cef94c1c3 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking.qll @@ -15,9 +15,14 @@ * `TaintTracking::localTaintStep` with arguments of type `DataFlow::Node`. */ -import semmle.code.cpp.ir.dataflow.DataFlow -import semmle.code.cpp.ir.dataflow.DataFlow2 +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.dataflow.new.DataFlow2 +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ module TaintTracking { - import experimental.semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl + import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTracking + import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking2.qll similarity index 68% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking2.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking2.qll index aa9fd392803..2da049cefaf 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking2.qll @@ -8,8 +8,13 @@ * `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and * `TaintTracking2::Configuration` extends `DataFlow2::Configuration`. * - * See `semmle.code.cpp.ir.dataflow.TaintTracking` for the full documentation. + * See `semmle.code.cpp.dataflow.new.TaintTracking` for the full documentation. + */ + +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. */ module TaintTracking2 { - import experimental.semmle.code.cpp.ir.dataflow.internal.tainttracking2.TaintTrackingImpl + import semmle.code.cpp.ir.dataflow.internal.tainttracking2.TaintTrackingImpl } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking3.qll similarity index 68% rename from cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking3.qll rename to cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking3.qll index bcd35ccd02f..113175d8369 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/TaintTracking3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/new/TaintTracking3.qll @@ -8,8 +8,13 @@ * `TaintTracking::Configuration` class extends `DataFlow::Configuration`, and * `TaintTracking2::Configuration` extends `DataFlow2::Configuration`. * - * See `semmle.code.cpp.ir.dataflow.TaintTracking` for the full documentation. + * See `semmle.code.cpp.dataflow.new.TaintTracking` for the full documentation. + */ + +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. */ module TaintTracking3 { - import experimental.semmle.code.cpp.ir.dataflow.internal.tainttracking3.TaintTrackingImpl + import semmle.code.cpp.ir.dataflow.internal.tainttracking3.TaintTrackingImpl } diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll b/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll index fa6589f7e27..c0ffa96297b 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/BuiltInOperations.qll @@ -569,7 +569,8 @@ class BuiltInOperationBuiltInAddressOf extends UnaryOperation, BuiltInOperation, * ``` */ class BuiltInOperationIsTriviallyConstructible extends BuiltInOperation, - @istriviallyconstructibleexpr { + @istriviallyconstructibleexpr +{ override string toString() { result = "__is_trivially_constructible" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyConstructible" } @@ -619,7 +620,8 @@ class BuiltInOperationIsNothrowDestructible extends BuiltInOperation, @isnothrow * bool v = __is_trivially_destructible(MyType); * ``` */ -class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr { +class BuiltInOperationIsTriviallyDestructible extends BuiltInOperation, @istriviallydestructibleexpr +{ override string toString() { result = "__is_trivially_destructible" } override string getAPrimaryQlClass() { result = "BuiltInOperationIsTriviallyDestructible" } @@ -738,7 +740,8 @@ class BuiltInOperationIsLiteralType extends BuiltInOperation, @isliteraltypeexpr * ``` */ class BuiltInOperationHasTrivialMoveConstructor extends BuiltInOperation, - @hastrivialmoveconstructorexpr { + @hastrivialmoveconstructorexpr +{ override string toString() { result = "__has_trivial_move_constructor" } override string getAPrimaryQlClass() { result = "BuiltInOperationHasTrivialMoveConstructor" } @@ -1034,7 +1037,8 @@ class BuiltInOperationIsAggregate extends BuiltInOperation, @isaggregate { * ``` */ class BuiltInOperationHasUniqueObjectRepresentations extends BuiltInOperation, - @hasuniqueobjectrepresentations { + @hasuniqueobjectrepresentations +{ override string toString() { result = "__has_unique_object_representations" } override string getAPrimaryQlClass() { result = "BuiltInOperationHasUniqueObjectRepresentations" } @@ -1107,7 +1111,8 @@ class BuiltInOperationIsLayoutCompatible extends BuiltInOperation, @islayoutcomp * ``` */ class BuiltInOperationIsPointerInterconvertibleBaseOf extends BuiltInOperation, - @ispointerinterconvertiblebaseof { + @ispointerinterconvertiblebaseof +{ override string toString() { result = "__is_pointer_interconvertible_base_of" } override string getAPrimaryQlClass() { diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll index a74a94ae2ba..93aa923a500 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll @@ -719,13 +719,6 @@ class ReferenceToExpr extends Conversion, @reference_to { class PointerDereferenceExpr extends UnaryOperation, @indirect { override string getAPrimaryQlClass() { result = "PointerDereferenceExpr" } - /** - * DEPRECATED: Use getOperand() instead. - * - * Gets the expression that is being dereferenced. - */ - deprecated Expr getExpr() { result = this.getOperand() } - override string getOperator() { result = "*" } override int getPrecedence() { result = 16 } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DataFlow.qll index 2aaa10e0331..32c236fec2c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DataFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/DataFlow.qll @@ -8,8 +8,8 @@ * results than the AST-based library in most scenarios. * * Unless configured otherwise, _flow_ means that the exact value of - * the source may reach the sink. We do not track flow across pointer - * dereferences or array indexing. + * the source may reach the sink. To track flow where the exact value + * may not be preserved, import `semmle.code.cpp.ir.dataflow.TaintTracking`. * * To use global (interprocedural) data flow, extend the class * `DataFlow::Configuration` as documented on that class. To use local @@ -22,5 +22,6 @@ import cpp module DataFlow { - import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl + import semmle.code.cpp.ir.dataflow.internal.DataFlow + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl1 } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/TaintTracking.qll index 7eada0bb244..f3449904420 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/TaintTracking.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/TaintTracking.qll @@ -19,5 +19,6 @@ import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.ir.dataflow.DataFlow2 module TaintTracking { + import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTracking import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll new file mode 100644 index 00000000000..617362ab4f0 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlow.qll @@ -0,0 +1,353 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Make` and `MakeWithState` modules. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic +private import DataFlowImpl + +/** An input configuration for data flow. */ +signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** An input configuration for data flow using flow state. */ +signature module StateConfigSig { + bindingset[this] + class FlowState; + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state); + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state); + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ +signature int explorationLimitSig(); + +/** + * The output of a data flow computation. + */ +signature module DataFlowSig { + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode; + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink); + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink); +} + +/** + * Constructs a standard data flow computation. + */ +module Make implements DataFlowSig { + private module C implements FullStateConfigSig { + import DefaultState + import Config + } + + import Impl +} + +/** + * Constructs a data flow computation using flow state. + */ +module MakeWithState implements DataFlowSig { + private module C implements FullStateConfigSig { + import Config + } + + import Impl +} + +signature class PathNodeSig { + /** Gets a textual representation of this element. */ + string toString(); + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); + + /** Gets the underlying `Node`. */ + Node getNode(); +} + +signature module PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + predicate edges(PathNode a, PathNode b); + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + predicate nodes(PathNode n, string key, string val); + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); +} + +/** + * Constructs a `PathGraph` from two `PathGraph`s by disjoint union. + */ +module MergePathGraph< + PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig Graph1, + PathGraphSig Graph2> +{ + private newtype TPathNode = + TPathNode1(PathNode1 p) or + TPathNode2(PathNode2 p) + + /** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */ + class PathNode extends TPathNode { + /** Gets this as a projection on the first given `PathGraph`. */ + PathNode1 asPathNode1() { this = TPathNode1(result) } + + /** Gets this as a projection on the second given `PathGraph`. */ + PathNode2 asPathNode2() { this = TPathNode2(result) } + + /** Gets a textual representation of this element. */ + string toString() { + result = this.asPathNode1().toString() or + result = this.asPathNode2().toString() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + Node getNode() { + result = this.asPathNode1().getNode() or + result = this.asPathNode2().getNode() + } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph implements PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + Graph1::edges(a.asPathNode1(), b.asPathNode1()) or + Graph2::edges(a.asPathNode2(), b.asPathNode2()) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + Graph1::nodes(n.asPathNode1(), key, val) or + Graph2::nodes(n.asPathNode2(), key, val) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or + Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2()) + } + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index c0bdb656e0e..7bc51e3e2fc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -1,8 +1,8 @@ private import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.DataFlow -private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate -private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import DataFlowPrivate +private import DataFlowUtil private import DataFlowImplCommon as DataFlowImplCommon /** @@ -143,7 +143,7 @@ private module VirtualDispatch { private class DataSensitiveExprCall extends DataSensitiveCall { DataSensitiveExprCall() { not exists(this.getStaticCallTarget()) } - override DataFlow::Node getDispatchValue() { result.asInstruction() = this.getCallTarget() } + override DataFlow::Node getDispatchValue() { result.asOperand() = this.getCallTargetOperand() } override Function resolve() { exists(FunctionInstruction fi | diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 1b969756b09..b7cb98deaf9 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1,135 +1,75 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * INTERNAL: Do not use. + * + * Provides an implementation of global (interprocedural) data flow. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic +private import DataFlowImplSpecific::Public +private import DataFlowImplCommonPublic +import DataFlow /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + * An input configuration for data flow using flow state. This signature equals + * `StateConfigSig`, but requires explicit implementation of all predicates. */ -abstract class Configuration extends string { +signature module FullStateConfigSig { bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } + class FlowState; /** * Holds if `source` is a relevant data flow source with the given initial * `state`. */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } + predicate isSource(Node source, FlowState state); /** * Holds if `sink` is a relevant data flow sink accepting `state`. */ - predicate isSink(Node sink, FlowState state) { none() } + predicate isSink(Node sink, FlowState state); /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. */ - predicate isBarrier(Node node) { none() } + predicate isBarrier(Node node); /** * Holds if data flow through `node` is prohibited when the flow state is * `state`. */ - predicate isBarrier(Node node, FlowState state) { none() } + predicate isBarrier(Node node, FlowState state); /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } + predicate isBarrierIn(Node node); /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + predicate isBarrierOut(Node node); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + predicate isAdditionalFlowStep(Node node1, Node node2); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); /** * Holds if an arbitrary number of implicit read steps of content `c` may be * taken at `node`. */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } + predicate allowImplicitRead(Node node, ContentSet c); /** * Gets the virtual dispatch branching limit when calculating field flow. * This can be overridden to a smaller value to improve performance (a * value of 0 disables field flow), or a larger value to get more results. */ - int fieldFlowBranchLimit() { result = 2 } + int fieldFlowBranchLimit(); /** * Gets a data flow configuration feature to add restrictions to the set of @@ -144,1720 +84,685 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ - FlowFeature getAFeature() { none() } + FlowFeature getAFeature(); /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } + predicate sourceGrouping(Node source, string sourceGroup); /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } + predicate sinkGrouping(Node sink, string sinkGroup); /** * Holds if hidden nodes should be included in the data flow graph. * * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). + * is not visualized (as it is in a `path-problem` query). */ - predicate includeHiddenNodes() { none() } + predicate includeHiddenNodes(); +} - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } +/** + * Provides default `FlowState` implementations given a `StateConfigSig`. + */ +module DefaultState { + class FlowState = Unit; - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() + predicate isSource(Node source, FlowState state) { Config::isSource(source) and exists(state) } + + predicate isSink(Node sink, FlowState state) { Config::isSink(sink) and exists(state) } + + predicate isBarrier(Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() } } /** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. + * Constructs a data flow computation given a full input configuration. */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } +module Impl { + private class FlowState = Config::FlowState; - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} + private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + Config::allowImplicitRead(n, _) and hasRead = [false, true] + } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false + private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") } - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) } pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) } pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } + } + + private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + } + + private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + } + + private predicate inBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierIn(n) and + Config::isSource(n, _) + ) + } + + private predicate outBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierOut(n) and + Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate fullBarrier(NodeEx node) { + exists(Node n | node.asNode() = n | + Config::isBarrier(n) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + Config::isBarrierIn(n) and + not Config::isSource(n, _) + or + Config::isBarrierOut(n) and + not Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate stateBarrier(NodeEx node, FlowState state) { + exists(Node n | node.asNode() = n | Config::isBarrier(n, state)) + } + + pragma[nomagic] + private predicate sourceNode(NodeEx node, FlowState state) { + Config::isSource(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + pragma[nomagic] + private predicate sinkNode(NodeEx node, FlowState state) { + Config::isSink(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + /** Provides the relevant barriers for a step from `node1` to `node2`. */ + pragma[inline] + private predicate stepFilter(NodeEx node1, NodeEx node2) { + not outBarrier(node1) and + not inBarrier(node2) and + not fullBarrier(node1) and + not fullBarrier(node2) + } + + /** + * Holds if data can flow in one local step from `node1` to `node2`. + */ + private predicate localFlowStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1) + ) + } + + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2) + ) + } + + private predicate additionalLocalStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) + ) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ + private predicate jumpStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ + private predicate additionalJumpStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate additionalJumpStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + pragma[nomagic] + private predicate readSetEx(NodeEx node1, ContentSet c, NodeEx node2) { + readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and + stepFilter(node1, node2) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + Config::allowImplicitRead(n, c) + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate read(NodeEx node1, Content c, NodeEx node2) { + exists(ContentSet cs | + readSetEx(node1, cs, node2) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate clearsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + clearsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate expectsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + expectsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + pragma[nomagic] + private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } + + pragma[nomagic] + private predicate hasReadStep(Content c) { read(_, c, _) } + + pragma[nomagic] + private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { + store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), + contentType) and + hasReadStep(tc.getContent()) and + stepFilter(node1, node2) + } + + pragma[nomagic] + private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) + } + + pragma[nomagic] + private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) + } + + /** + * Holds if field flow should be used for the given configuration. + */ + private predicate useFieldFlow() { Config::fieldFlowBranchLimit() >= 1 } + + private predicate hasSourceCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate sourceCallCtx(CallContext cc) { + if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny + } + + private predicate hasSinkCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if flow from `p` to a return node of kind `kind` is allowed. + * + * We don't expect a parameter to return stored in itself, unless + * explicitly allowed + */ + bindingset[p, kind] + private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { + exists(ParameterPosition pos | p.isParameterOf(_, pos) | + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + allowParameterReturnInSelfCached(p.asNode()) + ) + } + + private module Stage1 implements StageSig { + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } + + private class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + pragma[assume_small_delta] + private predicate fwdFlow(NodeEx node, Cc cc) { + sourceNode(node, _) and + if hasSourceCallCtx() then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc) | + localFlowStepEx(mid, node) or + additionalLocalFlowStep(mid, node) or + additionalLocalStateStep(mid, _, node, _) ) or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + exists(NodeEx mid | fwdFlow(mid, _) and cc = false | + jumpStepEx(mid, node) or + additionalJumpStep(mid, node) or + additionalJumpStateStep(mid, _, node, _) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) + exists(NodeEx mid | + useFieldFlow() and + fwdFlow(mid, cc) and + storeEx(mid, _, node, _) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) + exists(ContentSet c | + fwdFlowReadSet(c, node, cc) and + fwdFlowConsCandSet(c, _) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) + fwdFlowIn(_, _, _, node) and + cc = true or // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) + fwdFlowOut(_, node, false) and + cc = false or // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) + exists(DataFlowCall call | + fwdFlowOutFromArg(call, node) and + fwdFlowIsEntered(call, cc) ) } + // inline to reduce the number of iterations pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and + private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { + // call context cannot help reduce virtual dispatch + fwdFlow(arg, cc) and + viableParamArgEx(call, p, arg) and + not fullBarrier(p) and ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) + cc = false + or + cc = true and + not reducedViableImplInCallContext(call, _, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil + // call context may help reduce virtual dispatch + exists(DataFlowCallable target | + fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and + target = viableImplInSomeFwdFlowCallContextExt(call) and + cc = true ) - or + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc) { fwdFlowIn(call, _, cc, _) } + + pragma[nomagic] + private predicate fwdFlowInReducedViableImplInSomeCallContext( + DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target + ) { + fwdFlow(arg, true) and + viableParamArgEx(call, p, arg) and + reducedViableImplInCallContext(call, _, _) and + target = p.getEnclosingCallable() and + not fullBarrier(p) + } + + /** + * Gets a viable dispatch target of `call` in the context `ctx`. This is + * restricted to those `call`s for which a context might make a difference, + * and to `ctx`s that are reachable in `fwdFlow`. + */ + pragma[nomagic] + private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { + exists(DataFlowCall ctx | + fwdFlowIsEntered(ctx, _) and + result = viableImplInCallContextExt(call, ctx) + ) + } + + private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + + pragma[nomagic] + private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() + fwdFlow(mid, cc) and + readSetEx(mid, c, node) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node) and + useFieldFlow() and + fwdFlow(mid, _) and + storeEx(mid, tc, node, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `cs` may be interpreted in a read as the target of some store + * into `c`, in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCandSet(ContentSet cs, Content c) { + fwdFlowConsCand(c) and + c = cs.getAReadContent() + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc) { + exists(RetNodeEx ret | + fwdFlow(ret, cc) and + ret.getReturnPosition() = pos + ) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out) { + fwdFlowOut(call, out, true) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2) or + additionalJumpStateStep(node1, state1, _, state2) + | + fwdFlow(node1) + ) + } + + private predicate fwdFlowState(FlowState state) { + sourceNode(_, state) + or + exists(FlowState state0 | + fwdFlowState(state0) and + stateStepFwd(state0, state) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + private predicate revFlow(NodeEx node, boolean toReturn) { + revFlow0(node, toReturn) and + fwdFlow(node) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn) { + exists(FlowState state | + fwdFlow(node) and + sinkNode(node, state) and + fwdFlowState(state) and + if hasSinkCallCtx() then toReturn = true else toReturn = false ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, toReturn) | + localFlowStepEx(node, mid) or + additionalLocalFlowStep(node, mid) or + additionalLocalStateStep(node, _, mid, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, _) and toReturn = false | + jumpStepEx(node, mid) or + additionalJumpStep(node, mid) or + additionalJumpStateStep(node, _, mid, _) ) or // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) + exists(Content c | + revFlowStore(c, node, toReturn) and + revFlowConsCand(c) ) or // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) + exists(NodeEx mid, ContentSet c | + readSetEx(node, c, mid) and + fwdFlowConsCandSet(c, _) and + revFlow(mid, toReturn) ) or // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) + revFlowIn(_, node, false) and + toReturn = false or // flow out of a callable exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) + revFlowOut(pos) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + or + // flow through a callable + exists(DataFlowCall call | + revFlowInToReturn(call, node) and + revFlowIsReturned(call, toReturn) ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c } /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. + * Holds if `c` is the target of a read in the flow covered by `revFlow`. */ pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) + private predicate revFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, ContentSet cs | + fwdFlow(node) and + readSetEx(node, cs, mid) and + fwdFlowConsCandSet(cs, c) and + revFlow(pragma[only_bind_into](mid), _) ) } pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn) and + fwdFlowConsCand(c) and + storeEx(node, tc, mid, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + pragma[nomagic] + additional predicate revFlowIsReadAndStored(Content c) { + revFlowConsCand(c) and + revFlowStore(c, _, _) + } + + pragma[nomagic] + additional predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + fwdFlowReturnPosition(pos, _) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos) { + exists(NodeEx out | + revFlow(out, _) and + viableReturnPosOutNodeCandFwd1(_, pos, out) ) } pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) + additional predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + fwdFlowIn(call, arg, _, p) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate revFlowIn(DataFlowCall call, ArgNodeEx arg, boolean toReturn) { + exists(ParamNodeEx p | + revFlow(p, toReturn) and + viableParamArgNodeCandFwd1(call, p, arg) + ) } pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg) { + revFlowIn(call, arg, true) } /** @@ -1866,896 +771,1717 @@ private module MkStage { * reaching an argument of `call`. */ pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn) { + exists(NodeEx out | + revFlow(out, toReturn) and + fwdFlowOutFromArg(call, out) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2) or + additionalJumpStateStep(node1, state1, node2, state2) + | + revFlow(node1, _) and + revFlow(node2, _) and + fwdFlowState(state1) and + fwdFlowState(state2) + ) + } + + pragma[nomagic] + additional predicate revFlowState(FlowState state) { + exists(NodeEx node | + sinkNode(node, state) and + revFlow(node, _) and + fwdFlowState(state) + ) + or + exists(FlowState state0 | + revFlowState(state0) and + stateStepRev(state, state0) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) + exists(Content c | + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, node2, contentType) and + c = tc.getContent() and + exists(ap1) ) } pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() + predicate readStepCand(NodeEx n1, Content c, NodeEx n2) { + revFlowIsReadAndStored(c) and + read(n1, c, n2) and + revFlow(n2) + } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { + revFlow(node) and + exists(ap) + } + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap) { + revFlow(node, _) and + exists(state) and + exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node) { + revFlow(node, true) and + fwdFlow(node, true) and + not inBarrier(node) and + not outBarrier(node) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(DataFlowCallable c, ReturnKindExt kind | + throughFlowNodeCand(p) and + returnFlowCallableNodeCand(c, kind) and + p.getEnclosingCallable() = c and + exists(ap) and + parameterFlowThroughAllowed(p, kind) ) } pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + throughFlowNodeCand(ret) and + kind = ret.getKind() and + exists(argAp) and + exists(ap) } pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn) and + revFlowInToReturn(call, arg) and + revFlowIsReturned(call, toReturn) ) } additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) + nodes = count(NodeEx node | fwdFlow(node)) and + fields = count(Content f0 | fwdFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b)) or fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) + nodes = count(NodeEx node | revFlow(node, _)) and + fields = count(Content f0 | revFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b)) } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } + /* End: Stage 1 logic. */ } - class CcCall extends Cc { - CcCall() { this = true } + pragma[noinline] + private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + localFlowStepEx(node1, node2) } - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + additionalLocalFlowStep(node1, node2) } - Cc ccNone() { result = false } + pragma[nomagic] + private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { + Stage1::revFlow(out) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) + } - CcCall ccSomeCall() { result = true } + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out + ) { + exists(ReturnPosition pos | + viableReturnPosOutNodeCand1(call, pos, out) and + pos = ret.getReturnPosition() and + kind = pos.getKind() and + Stage1::revFlow(ret) and + not outBarrier(ret) and + not inBarrier(out) + ) + } - class LocalCc = Unit; + pragma[nomagic] + private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg) and + Stage1::revFlow(arg) + } - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { + viableParamArgNodeCand1(call, p, arg) and + Stage1::revFlow(p) and + not outBarrier(arg) and + not inBarrier(p) + } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} + /** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int branch(NodeEx n1) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) + } -private module Level1CallContext { - class Cc = CallContext; + /** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int join(NodeEx n2) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) + } - class CcCall = CallContextCall; + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, ret, kind, out) and + exists(int b, int j | + b = branch(ret) and + j = join(out) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, arg, p) and + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - class CcNoCall = CallContextNoCall; + private signature module StageSig { + class Ap; - Cc ccNone() { result instanceof CallContextAny } + predicate revFlow(NodeEx node); - CcCall ccSomeCall() { result instanceof CallContextSomeCall } + predicate revFlowAp(NodeEx node, Ap ap); + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap); + + predicate callMayFlowThroughRev(DataFlowCall call); + + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap); + + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ); + + predicate readStepCand(NodeEx n1, Content c, NodeEx n2); + } + + private module MkStage { + class ApApprox = PrevStage::Ap; + + signature module StageParam { + class Ap; + + class ApNil extends Ap; + + bindingset[result, ap] + ApApprox getApprox(Ap ap); + + ApNil getApNil(NodeEx node); + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail); + + /** + * An approximation of `Content` that corresponds to the precision level of + * `Ap`, such that the mappings from both `Ap` and `Content` to this type + * are functional. + */ + class ApHeadContent; + + ApHeadContent getHeadContent(Ap ap); + + ApHeadContent projectToHeadContent(Content c); + + class ApOption; + + ApOption apNone(); + + ApOption apSome(Ap ap); + + class Cc; + + class CcCall extends Cc; + + // TODO: member predicate on CcCall + predicate matchesCall(CcCall cc, DataFlowCall call); + + class CcNoCall extends Cc; + + Cc ccNone(); + + CcCall ccSomeCall(); + + class LocalCc; + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc); + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ); + + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ); + + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ); + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap); + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType); + } + + module Stage implements StageSig { + import Param + + /* Begin: Stage logic. */ + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + private predicate revFlowApAlias(NodeEx node, ApApprox apa) { + PrevStage::revFlowAp(node, apa) + } + + pragma[nomagic] + private predicate flowIntoCallApa( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa + ) { + flowIntoCall(call, arg, p, allowsFieldFlow) and + PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and + revFlowApAlias(arg, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowOutOfCallApa( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + ApApprox apa + ) { + flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and + PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and + revFlowApAlias(ret, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + ApApprox argApa, ApApprox apa + ) { + exists(ReturnKindExt kind | + flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + ) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `summaryCtx` and `argAp` record the + * corresponding parameter position and access path of that argument, respectively. + */ + pragma[nomagic] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, ap) + } + + pragma[inline] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + ) { + fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + sourceNode(node, state) and + (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + summaryCtx = TParamNodeNone() and + ap = getApNil(node) and + apa = getApprox(ap) + or + exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + localCc = getLocalCc(mid, cc) + | + localStep(mid, state0, node, state, true, _, localCc) and + ap = ap0 and + apa = apa0 + or + localStep(mid, state0, node, state, false, ap, localCc) and + ap0 instanceof ApNil and + apa = getApprox(ap) + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + jumpStepEx(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, _, nil) and + additionalJumpStep(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, _, nil) and + additionalJumpStateStep(mid, state0, node, state) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + ap = apCons(tc, ap0) and + apa = getApprox(ap) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(ap0, c, ap) and + apa = getApprox(ap) + ) + or + // flow into a callable + fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + if PrevStage::parameterMayFlowThrough(node, apa) + then ( + summaryCtx = TParamNodeSome(node.asNode()) and + argAp = apSome(ap) + ) else ( + summaryCtx = TParamNodeNone() and argAp = apNone() + ) + or + // flow out of a callable + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and + inner = ret.getEnclosingCallable() and + cc = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + or + // flow through a callable + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(DataFlowType contentType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, _) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate readStepCand(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + PrevStage::readStepCand(node1, c, node2) and + apc = projectToHeadContent(c) + } + + bindingset[node1, apc] + pragma[inline_late] + private predicate readStepCand0(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + readStepCand(node1, apc, c, node2) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + apc = getHeadContent(ap) and + readStepCand0(node1, apc, c, node2) + ) + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg( + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + ApApprox argApa, Ap ap, ApApprox apa + ) { + exists(ReturnKindExt kind | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + + pragma[inline] + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + } + + pragma[nomagic] + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap + ) { + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa)) and + PrevStage::parameterMayFlowThrough(p, apa) and + PrevStage::callMayFlowThroughRev(call) + ) + } + + pragma[nomagic] + private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + } + + private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(ap1, c, ap2) + } + + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa) + } + + pragma[nomagic] + private predicate returnFlowsThrough( + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + Ap ap + ) { + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap + ) { + exists(ApApprox argApa | + flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), + allowsFieldFlow, argApa) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + if allowsFieldFlow = false then argAp instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowIntoCallAp( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap + ) { + exists(ApApprox apa | + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + fwdFlow(arg, _, _, _, _, ap, apa) + ) + } + + pragma[nomagic] + private predicate flowOutOfCallAp( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, + Ap ap + ) { + exists(ApApprox apa | + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and + fwdFlow(ret, _, _, _, _, ap, apa) and + pos = ret.getReturnPosition() + ) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink. + * + * The parameter `returnCtx` records whether (and how) the node must be returned + * from the enclosing callable in order to reach a sink, and if so, `returnAp` + * records the access path of the returned value. + */ + pragma[nomagic] + additional predicate revFlow( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + revFlow0(node, state, returnCtx, returnAp, ap) and + fwdFlow(node, state, _, _, _, ap) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + fwdFlow(node, state, _, _, _, ap) and + sinkNode(node, state) and + ( + if hasSinkCallCtx() + then returnCtx = TReturnCtxNoFlowThrough() + else returnCtx = TReturnCtxNone() + ) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, nil) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStepEx(node, mid) and + revFlow(mid, state, _, _, ap) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStep(node, mid) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStateStep(node, state, mid, state0) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowConsCand(ap0, c, ap) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, returnCtx, returnAp, ap0) and + readStepFwd(node, ap, _, mid, ap0) + ) + or + // flow into a callable + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, TReturnCtxNone(), returnAp, ap) and + flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and + (if allowsFieldFlow = false then ap instanceof ApNil else any()) and + returnCtx = TReturnCtxNone() + ) + or + // flow through a callable + exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap) and + if returnFlowsThrough(node, pos, state, _, _, _, ap) + then ( + returnCtx = TReturnCtxMaybeFlowThrough(pos) and + returnAp = apSome(ap) + ) else ( + returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() + ) + ) + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + ReturnCtx returnCtx, ApOption returnAp + ) { + revFlow(mid, state, returnCtx, returnAp, ap0) and + storeStepFwd(node, ap, tc, mid, ap0) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, + ApOption returnAp, Ap ap + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, returnCtx, returnAp, ap) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowParamToReturn( + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap + ) { + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap)) + } + + pragma[nomagic] + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp + ) { + revFlowParamToReturn(p, state, pos, innerReturnAp, ap) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + matchesCall(ccc, call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ) { + exists(Ap ap2, Content c | + PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowConsCand(ap2, c, ap1) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and + readStepFwd(node1, ap1, c, node2, ap2) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + ) + } + + additional predicate revFlow(NodeEx node, FlowState state) { revFlow(node, state, _, _, _) } + + predicate revFlow(NodeEx node, FlowState state, Ap ap) { revFlow(node, state, _, _, ap) } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _, _, _, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) { + revFlow(node, state, ap) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + + private predicate validAp(Ap ap) { + revFlow(_, _, _, _, ap) and ap instanceof ApNil + or + exists(TypedContent head, Ap tail | + consCand(head, tail) and + ap = apCons(head, tail) + ) + } + + additional predicate consCand(TypedContent tc, Ap ap) { + revConsCand(tc, ap) and + validAp(ap) + } + + pragma[nomagic] + private predicate parameterFlowsThroughRev( + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp + ) { + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap) and + parameterFlowThroughAllowed(p, pos.getKind()) + } + + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(ReturnPosition pos | + returnFlowsThrough(_, pos, _, _, p, ap, _) and + parameterFlowsThroughRev(p, ap, pos, _) + ) + } + + pragma[nomagic] + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + parameterFlowsThroughRev(p, argAp, pos, ap) and + kind = pos.getKind() + ) + } + + pragma[nomagic] + private predicate revFlowThroughArg( + DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, + Ap ap + ) { + exists(ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(arg, state, returnCtx, returnAp, ap) and + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap) + ) + } + + additional predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and + fields = count(TypedContent f0 | consCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + states = count(FlowState state | revFlow(_, state, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | + revFlow(n, state, returnCtx, retAp, ap) + ) + } + /* End: Stage logic. */ + } + } + + private module BooleanCallContext { + class Cc extends boolean { + Cc() { this in [true, false] } + } + + class CcCall extends Cc { + CcCall() { this = true } + } + + /** Holds if the call context may be `call`. */ + predicate matchesCall(CcCall cc, DataFlowCall call) { any() } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } - module NoLocalCallContext { class LocalCc = Unit; bindingset[node, cc] LocalCc getLocalCc(NodeEx node, Cc cc) { any() } bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + } + + private module Level1CallContext { + class Cc = CallContext; + + class CcCall = CallContextCall; + + pragma[inline] + predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + module NoLocalCallContext { + class LocalCc = Unit; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + module LocalCallContext { + class LocalCc = LocalCallContext; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() } } - module LocalCallContext { - class LocalCc = LocalCallContext; + private module Stage2Param implements MkStage::StageParam { + private module PrevStage = Stage1; - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) + class Ap extends boolean { + Ap() { this in [true, false] } } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + class ApNil extends Ap { + ApNil() { this = false } } + + bindingset[result, ap] + PrevStage::Ap getApprox(Ap ap) { any() } + + ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + class ApHeadContent = Unit; + + pragma[inline] + ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + + ApHeadContent projectToHeadContent(Content c) { any() } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2) + ) and + exists(ap) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + predicate flowIntoCall = flowIntoCallNodeCand1/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::revFlowIsReadAndStored(c) and + expectsContentEx(node, c) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + PrevStage::revFlowState(state) and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + ap = true and + expectsContentCand(node) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + private module Stage2 implements StageSig { + import MkStage::Stage } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) + private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) + pragma[nomagic] + private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) + private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) or + expectsContentCached(this.asNode(), _) + } } - } - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowEntry(NodeEx node, FlowState state) { + Stage2::revFlow(node, state) and + ( + sourceNode(node, state) + or + jumpStepEx(_, node) + or + additionalJumpStep(_, node) + or + additionalJumpStateStep(_, _, node, state) + or + node instanceof ParamNodeEx + or + node.asNode() instanceof OutNodeExt + or + Stage2::storeStepCand(_, _, _, node, _) + or + Stage2::readStepCand(_, _, node) + or + node instanceof FlowCheckNode + or + exists(FlowState s | + additionalLocalStateStep(_, s, node, state) and + s != state + ) + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state) { + exists(NodeEx next | Stage2::revFlow(next, state) | + jumpStepEx(node, next) or + additionalJumpStep(node, next) or + flowIntoCallNodeCand2(_, node, next, _) or + flowOutOfCallNodeCand2(_, node, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _) or + Stage2::readStepCand(node, _, next) + ) or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s) | + additionalJumpStateStep(node, state, next, s) + or + additionalLocalStateStep(node, state, next, s) and s != state ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } + Stage2::revFlow(node, state) and + node instanceof FlowCheckNode + or + sinkNode(node, state) + } - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false) + or + additionalLocalStateStep(node1, state1, node2, state2) and + Stage2::revFlow(node1, state1, false) and + Stage2::revFlowAlias(node2, state2, false) + } - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, + LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + localFlowEntry(node1, pragma[only_bind_into](state)) and + ( + localFlowStepNodeCand1(node1, node2) and + preservesValue = true and + t = node1.getDataFlowType() and // irrelevant dummy value + Stage2::revFlow(node2, pragma[only_bind_into](state)) + or + additionalLocalFlowStepNodeCand2(node1, state, node2, state) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + exists(NodeEx mid | + localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and + localFlowStepNodeCand1(mid, node2) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state)) + ) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state, mid, _, _, cc) and + additionalLocalFlowStepNodeCand2(mid, state, node2, state) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() + ) ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and + localFlowExit(node2, state1) and + state1 = state2 or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and + state1 != state2 and + preservesValue = false and + t = node2.getDataFlowType() and + callContext.relevantFor(node1.getEnclosingCallable()) and + not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | + isUnreachableInCallCached(node1.asNode(), call) or + isUnreachableInCallCached(node2.asNode(), call) ) + } + } + + private import LocalFlowBigStep + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + predicate projectToHeadContent = getContentApprox/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + import BooleanCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApproxAccessPathFrontNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + predicate flowIntoCall = flowIntoCallNodeCand2/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage3 implements StageSig { + import MkStage::Stage + } + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import BooleanCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and + exists(lcc) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + not clear(node, ap) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage4 implements StageSig { + import MkStage::Stage + } + + /** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ + private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { + exists(AccessPathFront apf | + Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) ) } /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() + private predicate expensiveLen2unfolding(TypedContent tc) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage4::consCand(tc, TFrontNil(t)) and + not expensiveLen2unfolding(tc) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage4::consCand(tc1, TFrontHead(tc2)) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc) + } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) + /** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ + abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} + private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; -private module Stage3 implements StageSig { - import MkStage::Stage -} + AccessPathApproxNil() { this = TNil(t) } -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; + override string toString() { result = concat(": " + ppReprType(t)) } - class Ap = AccessPathFront; + override TypedContent getHead() { none() } - class ApNil = AccessPathFrontNil; + override int len() { result = 0 } - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + override DataFlowType getType() { result = t } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + abstract private class AccessPathApproxCons extends AccessPathApprox { } - class ApHeadContent = Content; + private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + AccessPathApproxConsNil() { this = TConsNil(tc, t) } - ApHeadContent projectToHeadContent(Content c) { result = c } + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } - class ApOption = AccessPathFrontOption; + override TypedContent getHead() { result = tc } - ApOption apNone() { result = TAccessPathFrontNone() } + override int len() { result = 1 } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + override DataFlowType getType() { result = tc.getContainerType() } - import BooleanCallContext + override AccessPathFront getFront() { result = TFrontHead(tc) } - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } } - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } + override TypedContent getHead() { result = tc1 } - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } + override int len() { result = len } - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } + override DataFlowType getType() { result = tc1.getContainerType() } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + override AccessPathFront getFront() { result = TFrontHead(tc1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( result = TConsCons(tc2, _, len - 1) or len = 2 and @@ -2763,1561 +2489,581 @@ private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { or result = TCons1(tc2, len - 1) ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) + } + } + + private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage4::consCand(tc, TFrontNil(t)) and + result = TNil(t) + ) ) - ) + } } -} -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + /** Gets the access path obtained by popping `tc` from `ap`, if any. */ + private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto `ap`. */ + private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) + private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } } -} -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; + private module Stage5Param implements MkStage::StageParam { + private module PrevStage = Stage4; - class Ap = AccessPathApprox; + class Ap = AccessPathApprox; - class ApNil = AccessPathApproxNil; + class ApNil = AccessPathApproxNil; + + pragma[nomagic] + PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + import Level1CallContext + import LocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + } + + private module Stage5 = MkStage::Stage; pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc + private predicate nodeMayUseSummary0( + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + exists(AccessPathApprox apa0 | + Stage5::parameterMayFlowThrough(p, _) and + Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + TAccessPathApproxSome(apa), apa0) ) } pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + private predicate nodeMayUseSummary(NodeEx n, FlowState state, AccessPathApprox apa) { + exists(ParamNodeEx p | + Stage5::parameterMayFlowThrough(p, apa) and + nodeMayUseSummary0(n, p, state, apa) ) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + Stage5::parameterMayFlowThrough(p, ap.getApprox()) and + Stage5::revFlow(p, state, _) + } - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} + /** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ + abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); + } -private module Stage5 = MkStage::Stage; + /** A summary context from which no flow summary can be generated. */ + private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } + } -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} + /** A summary context from which a flow summary can be generated. */ + private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ + private int count1to2unfold(AccessPathApproxCons1 apa) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + ) ) } -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and + private int countNodesUsingAccessPath(AccessPathApprox apa) { result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) + strictcount(NodeEx n, FlowState state | + Stage5::revFlow(n, state, apa) or nodeMayUseSummary(n, state, apa) ) - ) -} + } -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else + /** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ + private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa) { exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and + aps = count1to2unfold(apa) and + nodes = countNodesUsingAccessPath(apa) and accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() + apLimit < aps and + tupleLimit < (aps - 1) * nodes ) } -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() + private AccessPathApprox getATail(AccessPathApprox apa) { + exists(TypedContent head | + apa.pop(head) = result and + Stage5::consCand(head, result) ) } -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" + /** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ + private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { + if apa.getHead().forceHighPrecision() + then unfold = true else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa) and + nodes = countNodesUsingAccessPath(apa) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) + /** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ + pragma[assume_small_delta] + private int countAps(AccessPathApprox apa) { + evalUnfold(apa, false) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa)) or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" + evalUnfold(apa, false) and + result = count1to2unfold(apa) and + not expensiveLen1to2unfolding(apa) or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) + evalUnfold(apa, true) and + result = countPotentialAps(apa) } - private string ppCtx() { - this instanceof PathNodeSink and result = "" + /** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ + language[monotonicAggregates] + pragma[assume_small_delta] + private int countPotentialAps(AccessPathApprox apa) { + apa instanceof AccessPathApproxNil and result = 1 or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) + private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false) and + head = apa.getHead() and + tail.getApprox() = getATail(apa) + ) } or - TCallableSrc() or - TCallableSink() + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + not expensiveLen1to2unfolding(apa) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + expensiveLen1to2unfolding(apa) and + apa.len() = len and + head = apa.getHead() + ) + } - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + private newtype TPathNode = + pragma[assume_small_delta] + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + // A PathNode is introduced by a source ... + Stage5::revFlow(node, state) and + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + pathStep(_, node, state, cc, sc, ap) and + Stage5::revFlow(node, state, ap.getApprox()) + } or + TPathNodeSink(NodeEx node, FlowState state) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() + ) + } or + TPathNodeSourceGroup(string sourceGroup) { + exists(PathNodeImpl source | sourceGroup = source.getSourceGroup()) + } or + TPathNodeSinkGroup(string sinkGroup) { + exists(PathNodeSink sink | sinkGroup = sink.getSinkGroup()) + } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the * tracked object. The final type indicates the type of the tracked object. */ - private class PartialAccessPath extends TPartialAccessPath { + private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() } - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } } - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } } - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + pragma[assume_small_delta] + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + pragma[assume_small_delta] + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } - } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) } } - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) + private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage5::consCand(head1, result.getApprox()) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = + "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } } - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) + private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } + AccessPathCons1() { this = TAccessPathCons1(head, len) } - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + override TypedContent getHead() { result = head } - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) + override AccessPath getTail() { + Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + } - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + override AccessPathFrontHead getFront() { result = TFrontHead(head) } - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } + } + + abstract private class PathNodeImpl extends TPathNode { + /** Gets the `FlowState` of this node. */ + abstract FlowState getState(); + + /** Holds if this node is a source. */ + abstract predicate isSource(); + + abstract PathNodeImpl getASuccessorImpl(); + + private PathNodeImpl getASuccessorIfHidden() { + this.isHidden() and + result = this.getASuccessorImpl() + } + + pragma[nomagic] + private PathNodeImpl getANonHiddenSuccessor0() { + result = this.getASuccessorIfHidden*() and + not result.isHidden() + } + + final PathNodeImpl getANonHiddenSuccessor() { + result = this.getASuccessorImpl().getANonHiddenSuccessor0() and + not this.isHidden() + } + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + not Config::includeHiddenNodes() and ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + ) } - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } + string getSourceGroup() { + this.isSource() and + Config::sourceGrouping(this.getNodeEx().asNode(), result) + } + + predicate isFlowSource() { + this.isSource() and not exists(this.getSourceGroup()) + or + this instanceof PathNodeSourceGroup + } + + predicate isFlowSink() { + this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or + this instanceof PathNodeSinkGroup + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { /** Gets a textual representation of this element. */ string toString() { result = this.getNodeEx().toString() + this.ppAp() } @@ -4341,305 +3087,335 @@ private module FlowExploration { ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + } + + /** Holds if `n` can reach a sink. */ + private predicate directReach(PathNodeImpl n) { + n instanceof PathNodeSink or + n instanceof PathNodeSinkGroup or + directReach(n.getANonHiddenSuccessor()) + } + + /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ + private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } + + /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ + private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { + n1.getANonHiddenSuccessor() = n2 and directReach(n2) + } + + private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } + final Node getNode() { super.getNodeEx().projectToNode() = result } - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) } - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group) } } /** * Provides the query predicates needed to include a graph in a path-problem query. */ - module PartialPathGraph { + module PathGraph implements PathGraphSig { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) + } } - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + /** + * An intermediate flow graph node. This is a tuple consisting of a `Node`, + * a `FlowState`, a `CallContext`, a `SummaryCtx`, and an `AccessPath`. + */ + private class PathNodeMid extends PathNodeImpl, TPathNodeMid { NodeEx node; FlowState state; CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; + SummaryCtx sc; + AccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } CallContext getCallContext() { result = cc } - TSummaryCtx1 getSummaryCtx1() { result = sc1 } + SummaryCtx getSummaryCtx() { result = sc } - TSummaryCtx2 getSummaryCtx2() { result = sc2 } + AccessPath getAp() { result = ap } - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) } - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + } + + predicate isAtSink() { + sinkNode(node, state) and + ap instanceof AccessPathNil and + if hasSinkCallCtx() + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state } } - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + /** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ + private class PathNodeSink extends PathNodeImpl, TPathNodeSink { NodeEx node; FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + PathNodeSink() { this = TPathNodeSink(node, state) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) } - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + override predicate isSource() { sourceNode(node, state) } - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) } + } - RevPartialAccessPath getAp() { result = ap } + private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { + string sourceGroup; - override Configuration getConfiguration() { result = config } + PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup) } - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } + override NodeEx getNodeEx() { none() } - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup } + + override predicate isSource() { none() } + + override string toString() { result = sourceGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 } } - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { + string sinkGroup; + + PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup) } + + override NodeEx getNodeEx() { none() } + + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { none() } + + override predicate isSource() { none() } + + override string toString() { result = sinkGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 + } + } + + private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + LocalCallContext localCC ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and + midnode = mid.getNodeEx() and state = mid.getState() and cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() } - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + /** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) + or + exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + state = mid.getState() and + cc = mid.getCallContext() } pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config + private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + state = mid.getState() and + cc = mid.getCallContext() } - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() + apa = mid.getAp().getApprox() } pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + pathOutOfCallable0(mid, pos, state, innercc, apa) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4648,53 +3424,86 @@ private module FlowExploration { ) } - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) + pragma[noinline] + private NodeEx getAnOutNodeFlow(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa) { + result.asNode() = kind.getAnOutNode(call) and + Stage5::revFlow(result, _, apa) + } + + /** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ + pragma[noinline] + private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa | + pathOutOfCallable1(mid, call, kind, state, cc, apa) and + out = getAnOutNodeFlow(kind, call, apa) ) } + /** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and parameterMatch(ppos, apos) ) } pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) + exists(ParamNodeEx p | + Stage5::revFlow(p, _, apa) and + p.isParameterOf(callable, pos) + ) } - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config + pragma[nomagic] + private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) + ) + } + + /** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ + pragma[nomagic] + private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call + ) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4702,252 +3511,1108 @@ private module FlowExploration { ) } + /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and + exists(RetNodeEx ret | + pathNode(_, ret, state, cc, sc, ap, _) and kind = ret.getKind() and + apa = ap.getApprox() and + parameterFlowThroughAllowed(sc.getParamNode(), kind) + ) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa + ) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa) + ) + } + + /** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ + pragma[noinline] + private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + out = getAnOutNodeFlow(kind, call, apa) + ) + } + + private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _) and + not arg.isHidden() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, + AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _) or + storeEx(n1, _, n2, _) or + readSetEx(n1, _, n2) + ) + } + + pragma[nomagic] + private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { + succ = pred.getANonHiddenSuccessor() and + succNode = succ.getNodeEx() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + hasSuccessor(pragma[only_bind_into](arg), par, p) and + not ret.isHidden() and + pathNode(out0, o, sout, _, _, apout, _) + | + out = out0 or out = out0.projectToSink() + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNodeImpl n) { + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNodeImpl mid | + retReach(mid) and + n.getANonHiddenSuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } + } + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { + exists(PathNodeImpl flowsource, PathNodeImpl flowsink | + source = flowsource and sink = flowsink + | + flowsource.isFlowSource() and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.isFlowSink() + ) + } + + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { + flowsource.isSource() and + flowsource.getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink + } + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + + private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNodeImpl pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = + count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn) + } + + /** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ + predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples + ) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "5 Fwd" and + n = 50 and + Stage5::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and + n = 55 and + Stage5::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) + } + + module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { + exists(NodeEx node1, NodeEx node2 | + jumpStepEx(node1, node2) + or + additionalJumpStep(node1, node2) + or + additionalJumpStateStep(node1, _, node2, _) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c) { + exists(Node n | Config::isSource(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) + } + + private predicate interestingCallableSink(DataFlowCallable c) { + exists(Node n | Config::isSink(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c) { + interestingCallableSrc(c) or + interestingCallableSink(c) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2 | + callableStep(c1, c2) and + ce1 = TCallable(c1) and + ce2 = TCallable(c2) + ) + or + exists(Node n | + ce1 = TCallableSrc() and + Config::isSource(n, _) and + ce2 = TCallable(getNodeEnclosingCallable(n)) + ) + or + exists(Node n | + ce2 = TCallableSink() and + Config::isSink(n, _) and + ce1 = TCallable(getNodeEnclosingCallable(n)) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } + + private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state) or + sinkNode(_, state) or + additionalLocalStateStep(_, state, _, _) or + additionalLocalStateStep(_, _, _, state) or + additionalJumpStateStep(_, state, _, _) or + additionalJumpStateStep(_, _, _, state) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + distSrc(node.getEnclosingCallable()) <= explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap + ) { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(explorationLimit()) + or + revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and + not clearsContentEx(node, ap.getHead()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead()) + ) and + not fullBarrier(node) and + not stateBarrier(node, state) and + distSink(node.getEnclosingCallable()) <= explorationLimit() + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + not fullBarrier(node) and + not stateBarrier(node, state) and + not clearsContentEx(node, ap.getHead().getContent()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead().getContent()) + ) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { result = distSrc(this.getNodeEx().getEnclosingCallable()) } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { result = distSink(this.getNodeEx().getEnclosingCallable()) } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + } + + predicate isSource() { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp()) + } + + predicate isSink() { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + or + additionalLocalFlowStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + partialPathStoreStep(mid, _, _, node, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and + sc3 = mid.getSummaryCtx3() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + or + partialPathOutOfCallable(mid, node, state, cc, ap) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + storeEx(midNode, tc, node, contentType) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { + partialPathStoreStep(_, ap1, tc, _, ap2) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node) and + ap.getHead() = tc and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and ap = mid.getAp() - ) - } + } - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + | + out.asNode() = kind.getAnOutNode(call) + ) + } - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[nomagic] + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + ) { + localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and + ap = mid.getAp() + or + additionalLocalFlowStep(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + jumpStepEx(node, mid.getNodeEx()) and + state = mid.getState() and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and + ap = mid.getAp() + or + additionalJumpStep(node, mid.getNodeEx()) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } + sc3 = mid.getSummaryCtx3() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) + pragma[nomagic] + private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + revPartialPathReadStep(_, ap1, c, _, ap2) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + storeEx(node, tc, midNode, _) and + ap.getHead() = c and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } + + private predicate partialFlow(PartialPathNode source, PartialPathNode node) { + source.isFwdSource() and + node = source.getASuccessor+() + } + + private predicate revPartialFlow(PartialPathNode node, PartialPathNode sink) { + sink.isRevSink() and + node.getASuccessor+() = sink + } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink) and + dist = node.getSinkDistance() + } } } - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll new file mode 100644 index 00000000000..e6bdc74cceb --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl1.qll @@ -0,0 +1,396 @@ +/** + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +private import DataFlowImpl +import DataFlowImplCommonPublic +import FlowStateString + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited. + */ + deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited when + * the flow state is `state` + */ + deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * DEPRECATED: Use `FlowExploration` instead. + * + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + deprecated int explorationLimit() { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (for example in a `path-problem` query). + */ + predicate includeHiddenNodes() { none() } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +/** A bridge class to access the deprecated `isBarrierGuard`. */ +private class BarrierGuardGuardedNodeBridge extends Unit { + abstract predicate guardedNode(Node n, Configuration config); + + abstract predicate guardedNode(Node n, FlowState state, Configuration config); +} + +private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { + deprecated override predicate guardedNode(Node n, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + } + + deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g, state) and + n = g.getAGuardedNode() + ) + } +} + +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) + or + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) + or + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) + or + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 + } + + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) + } + + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } + + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } + + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) + } + + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) + } + + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } +} + +private import Impl as I +import I + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof I::PathNode { + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { result = super.getNode() } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = getState(super.getState()) } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = getConfig(super.getState()) } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getASuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } + + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } + + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } +} + +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink + ) +} + +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config +} + +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } + +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 1b969756b09..e6bdc74cceb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 5d3becc8078..d09fdcfca3e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -3,15 +3,18 @@ private import DataFlowImplSpecific::Public import Cached module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; + /** Provides `FlowState = string`. */ + module FlowStateString { + /** A state value to track during data flow. */ + class FlowState = string; - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } + /** + * The default state, which is used when the state is unspecified for a source + * or a sink. + */ + class FlowStateEmpty extends FlowState { + FlowStateEmpty() { this = "" } + } } private newtype TFlowFeature = @@ -179,6 +182,7 @@ private module LambdaFlow { boolean toJump, DataFlowCallOption lastCall ) { revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and + not expectsContent(node, _) and if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode then compatibleTypes(t, getNodeDataFlowType(node)) else any() diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll index 9bbc70fbdf9..7da63f6c4fa 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImplConsistency.qll @@ -18,6 +18,9 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ predicate uniqueEnclosingCallableExclude(Node n) { none() } + /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ + predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ predicate uniqueNodeLocationExclude(Node n) { none() } @@ -86,6 +89,15 @@ module Consistency { ) } + query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) { + exists(int c | + c = count(call.getEnclosingCallable()) and + c != 1 and + not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and + msg = "Call should have one enclosing callable but has " + c + "." + ) + } + query predicate uniqueType(Node n, string msg) { exists(int c | n instanceof RelevantNode and diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll index e068f81f542..9d69856e20b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll @@ -1,8 +1,276 @@ -private import cpp +private import cpp as Cpp private import DataFlowUtil private import semmle.code.cpp.ir.IR private import DataFlowDispatch private import DataFlowImplConsistency +private import semmle.code.cpp.ir.internal.IRCppLanguage +private import SsaInternals as Ssa +private import DataFlowImplCommon as DataFlowImplCommon + +cached +private module Cached { + cached + module Nodes0 { + cached + newtype TIRDataFlowNode0 = + TInstructionNode0(Instruction i) { + not Ssa::ignoreInstruction(i) and + not exists(Operand op | + not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op) + ) and + // We exclude `void`-typed instructions because they cannot contain data. + // However, if the instruction is a glvalue, and their type is `void`, then the result + // type of the instruction is really `void*`, and thus we still want to have a dataflow + // node for it. + (not i.getResultType() instanceof VoidType or i.isGLValue()) + } or + TMultipleUseOperandNode0(Operand op) { + not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op)) + } or + TSingleUseOperandNode0(Operand op) { + not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op)) + } + } + + /** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ + pragma[nomagic] + cached + int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { + DataFlowImplCommon::forceCachingInSameStage() and + exists( + ParameterNode switchee, SwitchInstruction switch, ConditionOperand op, DataFlowCall call + | + DataFlowImplCommon::viableParamArg(call, p, arg) and + DataFlowImplCommon::viableParamArg(call, switchee, _) and + switch.getExpressionOperand() = op and + getAdditionalFlowIntoCallNodeTermStep+(switchee, operandNode(op)) and + result = countNumberOfBranchesUsingParameter(switch, p) + ) + } +} + +import Cached +private import Nodes0 + +class Node0Impl extends TIRDataFlowNode0 { + /** + * INTERNAL: Do not use. + */ + Declaration getEnclosingCallable() { none() } // overridden in subclasses + + /** Gets the function to which this node belongs, if any. */ + Declaration getFunction() { none() } // overridden in subclasses + + /** + * Gets the type of this node. + * + * If `isGLValue()` holds, then the type of this node + * should be thought of as "pointer to `getType()`". + */ + DataFlowType getType() { none() } // overridden in subclasses + + /** Gets the instruction corresponding to this node, if any. */ + Instruction asInstruction() { result = this.(InstructionNode0).getInstruction() } + + /** Gets the operands corresponding to this node, if any. */ + Operand asOperand() { result = this.(OperandNode0).getOperand() } + + /** INTERNAL: Do not use. */ + string toStringImpl() { + none() // overridden by subclasses + } + + /** Gets a textual representation of this node. */ + final string toString() { result = this.toStringImpl() } + + /** Holds if the value of this node is a glvalue */ + predicate isGLValue() { none() } // overridden in subclasses +} + +/** + * Gets the type of the operand `op`. + * + * The boolean `isGLValue` is true if the operand represents a glvalue. In that case, + * the returned type should be thought of as a pointer type whose base type is given + * by this predicate. + */ +DataFlowType getOperandType(Operand op, boolean isGLValue) { + Ssa::getLanguageType(op).hasType(result, isGLValue) +} + +/** + * Gets the type of the instruction `instr`. + * + * The boolean `isGLValue` is true if the operand represents a glvalue. In that case, + * the returned type should be thought of as a pointer type whose base type is given + * by this predicate. + */ +DataFlowType getInstructionType(Instruction instr, boolean isGLValue) { + Ssa::getResultLanguageType(instr).hasType(result, isGLValue) +} + +/** + * An instruction, viewed as a node in a data flow graph. + */ +abstract class InstructionNode0 extends Node0Impl { + Instruction instr; + + /** Gets the instruction corresponding to this node. */ + Instruction getInstruction() { result = instr } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = instr.getEnclosingFunction() } + + override DataFlowType getType() { result = getInstructionType(instr, _) } + + override string toStringImpl() { + // This predicate is overridden in subclasses. This default implementation + // does not use `Instruction.toString` because that's expensive to compute. + result = instr.getOpcode().toString() + } + + final override predicate isGLValue() { exists(getInstructionType(instr, true)) } +} + +/** + * An instruction without an operand that is used only once, viewed as a node in a data flow graph. + */ +private class InstructionInstructionNode0 extends InstructionNode0, TInstructionNode0 { + InstructionInstructionNode0() { this = TInstructionNode0(instr) } +} + +/** + * An instruction with an operand that is used only once, viewed as a node in a data flow graph. + */ +private class SingleUseOperandInstructionNode0 extends InstructionNode0, TSingleUseOperandNode0 { + SingleUseOperandInstructionNode0() { + exists(Operand op | + this = TSingleUseOperandNode0(op) and + instr = Ssa::getIRRepresentationOfOperand(op) + ) + } +} + +/** + * An operand, viewed as a node in a data flow graph. + */ +abstract class OperandNode0 extends Node0Impl { + Operand op; + + /** Gets the operand corresponding to this node. */ + Operand getOperand() { result = op } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = op.getUse().getEnclosingFunction() } + + override DataFlowType getType() { result = getOperandType(op, _) } + + override string toStringImpl() { result = op.toString() } + + final override predicate isGLValue() { exists(getOperandType(op, true)) } +} + +/** + * An operand that is used multiple times, viewed as a node in a data flow graph. + */ +private class MultipleUseOperandNode0 extends OperandNode0, TMultipleUseOperandNode0 { + MultipleUseOperandNode0() { this = TMultipleUseOperandNode0(op) } +} + +/** + * An operand that is used only once, viewed as a node in a data flow graph. + */ +private class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0 { + SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) } +} + +/** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an operand in the IR + * after `index` number of loads. + * + * Note: Unlike `RawIndirectOperand`, a value of type `IndirectOperand` may + * be an `OperandNode`. + */ +class IndirectOperand extends Node { + Operand operand; + int indirectionIndex; + + IndirectOperand() { + this.(RawIndirectOperand).getOperand() = operand and + this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex + or + this.(OperandNode).getOperand() = + Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex) + } + + /** Gets the underlying operand. */ + Operand getOperand() { result = operand } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + /** + * Holds if this `IndirectOperand` is represented directly in the IR instead of + * a `RawIndirectionOperand` with operand `op` and indirection index `index`. + */ + predicate isIRRepresentationOf(Operand op, int index) { + this instanceof OperandNode and + ( + op = operand and + index = indirectionIndex + ) + } +} + +/** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an instruction in the IR + * after `index` number of loads. + * + * Note: Unlike `RawIndirectInstruction`, a value of type `IndirectInstruction` may + * be an `InstructionNode`. + */ +class IndirectInstruction extends Node { + Instruction instr; + int indirectionIndex; + + IndirectInstruction() { + this.(RawIndirectInstruction).getInstruction() = instr and + this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex + or + this.(InstructionNode).getInstruction() = + Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex) + } + + /** Gets the underlying instruction. */ + Instruction getInstruction() { result = instr } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + /** + * Holds if this `IndirectInstruction` is represented directly in the IR instead of + * a `RawIndirectionInstruction` with instruction `i` and indirection index `index`. + */ + predicate isIRRepresentationOf(Instruction i, int index) { + this instanceof InstructionNode and + ( + i = instr and + index = indirectionIndex + ) + } +} /** Gets the callable in which this node occurs. */ DataFlowCallable nodeGetEnclosingCallable(Node n) { result = n.getEnclosingCallable() } @@ -22,7 +290,7 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos) * to the callable. Instance arguments (`this` pointer) and read side effects * on parameters are also included. */ -abstract class ArgumentNode extends OperandNode { +abstract class ArgumentNode extends Node { /** * Holds if this argument occurs at the given position in the given call. * The instance argument is considered to have index `-1`. @@ -37,7 +305,7 @@ abstract class ArgumentNode extends OperandNode { * A data flow node that occurs as the argument to a call, or an * implicit `this` pointer argument. */ -private class PrimaryArgumentNode extends ArgumentNode { +private class PrimaryArgumentNode extends ArgumentNode, OperandNode { override ArgumentOperand op; PrimaryArgumentNode() { exists(CallInstruction call | op = call.getAnArgumentOperand()) } @@ -45,50 +313,13 @@ private class PrimaryArgumentNode extends ArgumentNode { override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { op = call.getArgumentOperand(pos.(DirectPosition).getIndex()) } - - override string toString() { - exists(Expr unconverted | - unconverted = op.getDef().getUnconvertedResultExpression() and - result = unconverted.toString() - ) - or - // Certain instructions don't map to an unconverted result expression. For these cases - // we fall back to a simpler naming scheme. This can happen in IR-generated constructors. - not exists(op.getDef().getUnconvertedResultExpression()) and - ( - result = "Argument " + op.(PositionalArgumentOperand).getIndex() - or - op instanceof ThisArgumentOperand and result = "Argument this" - ) - } } -/** - * A data flow node representing the read side effect of a call on a - * specific parameter. - */ -private class SideEffectArgumentNode extends ArgumentNode { - override SideEffectOperand op; - ReadSideEffectInstruction read; - - SideEffectArgumentNode() { op = read.getSideEffectOperand() } - - override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) { - read.getPrimaryInstruction() = call and - pos.(IndirectionPosition).getIndex() = read.getIndex() - } - - override string toString() { - result = read.getArgumentDef().getUnconvertedResultExpression().toString() + " indirection" - or - // Some instructions don't map to an unconverted result expression. For these cases - // we fall back to a simpler naming scheme. This can happen in IR-generated constructors. - not exists(read.getArgumentDef().getUnconvertedResultExpression()) and - ( - if read.getIndex() = -1 - then result = "Argument this indirection" - else result = "Argument " + read.getIndex() + " indirection" - ) +private class SideEffectArgumentNode extends ArgumentNode, SideEffectOperandNode { + override predicate argumentOf(DataFlowCall dfCall, ArgumentPosition pos) { + this.getCallInstruction() = dfCall and + pos.(IndirectionPosition).getArgumentIndex() = this.getArgumentIndex() and + pos.(IndirectionPosition).getIndirectionIndex() = super.getIndirectionIndex() } } @@ -119,30 +350,45 @@ class DirectPosition extends Position, TDirectPosition { } class IndirectionPosition extends Position, TIndirectionPosition { - int index; + int argumentIndex; + int indirectionIndex; - IndirectionPosition() { this = TIndirectionPosition(index) } + IndirectionPosition() { this = TIndirectionPosition(argumentIndex, indirectionIndex) } override string toString() { - index = -1 and - result = "this" - or - index != -1 and - result = index.toString() + if argumentIndex = -1 + then if indirectionIndex > 0 then result = "this indirection" else result = "this" + else + if indirectionIndex > 0 + then result = argumentIndex.toString() + " indirection" + else result = argumentIndex.toString() } - int getIndex() { result = index } + int getArgumentIndex() { result = argumentIndex } + + int getIndirectionIndex() { result = indirectionIndex } } newtype TPosition = TDirectPosition(int index) { exists(any(CallInstruction c).getArgument(index)) } or - TIndirectionPosition(int index) { - exists(ReadSideEffectInstruction instr | instr.getIndex() = index) + TIndirectionPosition(int argumentIndex, int indirectionIndex) { + hasOperandAndIndex(_, any(CallInstruction call).getArgumentOperand(argumentIndex), + indirectionIndex) } private newtype TReturnKind = - TNormalReturnKind() or - TIndirectReturnKind(ParameterIndex index) + TNormalReturnKind(int index) { + exists(IndirectReturnNode return | + return.isNormalReturn() and + index = return.getIndirectionIndex() - 1 // We subtract one because the return loads the value. + ) + } or + TIndirectReturnKind(int argumentIndex, int indirectionIndex) { + exists(IndirectReturnNode return | + return.isParameterReturn(argumentIndex) and + indirectionIndex = return.getIndirectionIndex() + ) + } /** * A return kind. A return kind describes how a value can be returned @@ -154,53 +400,171 @@ class ReturnKind extends TReturnKind { } private class NormalReturnKind extends ReturnKind, TNormalReturnKind { - override string toString() { result = "return" } + int index; + + NormalReturnKind() { this = TNormalReturnKind(index) } + + override string toString() { result = "indirect return" } } private class IndirectReturnKind extends ReturnKind, TIndirectReturnKind { - ParameterIndex index; + int argumentIndex; + int indirectionIndex; - IndirectReturnKind() { this = TIndirectReturnKind(index) } + IndirectReturnKind() { this = TIndirectReturnKind(argumentIndex, indirectionIndex) } - override string toString() { result = "outparam[" + index.toString() + "]" } + override string toString() { result = "indirect outparam[" + argumentIndex.toString() + "]" } } /** A data flow node that occurs as the result of a `ReturnStmt`. */ -class ReturnNode extends InstructionNode { - Instruction primary; - - ReturnNode() { - exists(ReturnValueInstruction ret | instr = ret and primary = ret) - or - exists(ReturnIndirectionInstruction rii | instr = rii and primary = rii) - } - +class ReturnNode extends Node instanceof IndirectReturnNode { /** Gets the kind of this returned value. */ abstract ReturnKind getKind(); } -class ReturnValueNode extends ReturnNode { - override ReturnValueInstruction primary; - - override ReturnKind getKind() { result = TNormalReturnKind() } +pragma[nomagic] +private predicate finalParameterNodeHasArgumentAndIndex( + FinalParameterNode node, int argumentIndex, int indirectionIndex +) { + node.getArgumentIndex() = argumentIndex and + node.getIndirectionIndex() = indirectionIndex } -class ReturnIndirectionNode extends ReturnNode { - override ReturnIndirectionInstruction primary; - +class ReturnIndirectionNode extends IndirectReturnNode, ReturnNode { override ReturnKind getKind() { - exists(int index | - primary.hasIndex(index) and - result = TIndirectReturnKind(index) + exists(Operand op, int indirectionIndex | + hasOperandAndIndex(this, pragma[only_bind_into](op), pragma[only_bind_into](indirectionIndex)) + | + exists(ReturnValueInstruction return | + op = return.getReturnAddressOperand() and + result = TNormalReturnKind(indirectionIndex - 1) + ) + ) + or + exists(int argumentIndex, int indirectionIndex | + finalParameterNodeHasArgumentAndIndex(this, argumentIndex, indirectionIndex) and + result = TIndirectReturnKind(argumentIndex, indirectionIndex) ) } } +private Operand fullyConvertedCallStepImpl(Operand op) { + not exists(getANonConversionUse(op)) and + exists(Instruction instr | + conversionFlow(op, instr, _, _) and + result = getAUse(instr) + ) +} + +private Operand fullyConvertedCallStep(Operand op) { + result = unique( | | fullyConvertedCallStepImpl(op)) +} + +/** + * Gets the instruction that uses this operand, if the instruction is not + * ignored for dataflow purposes. + */ +private Instruction getUse(Operand op) { + result = op.getUse() and + not Ssa::ignoreInstruction(result) +} + +/** Gets a use of the instruction `instr` that is not ignored for dataflow purposes. */ +Operand getAUse(Instruction instr) { + result = instr.getAUse() and + not Ssa::ignoreOperand(result) +} + +/** + * Gets a use of `operand` that is: + * - not ignored for dataflow purposes, and + * - not a conversion-like instruction. + */ +private Instruction getANonConversionUse(Operand operand) { + result = getUse(operand) and + not conversionFlow(_, result, _, _) +} + +/** + * Gets an operand that represents the use of the value of `call` following + * a sequence of conversion-like instructions. + * + * Note that `operand` is not functionally determined by `call` since there + * can be multiple sequences of disjoint conversions following a call. For example, + * consider an example like: + * ```cpp + * long f(); + * int y; + * long x = (long)(y = (int)f()); + * ``` + * in this case, there'll be a long-to-int conversion on `f()` before the value is assigned to `y`, + * and there will be an int-to-long conversion on `(int)f()` before the value is assigned to `x`. + */ +private predicate operandForFullyConvertedCallImpl(Operand operand, CallInstruction call) { + exists(getANonConversionUse(operand)) and + ( + operand = getAUse(call) + or + operand = fullyConvertedCallStep*(getAUse(call)) + ) +} + +/** + * Gets the operand that represents the use of the value of `call` following + * a sequence of conversion-like instructions, if a unique operand exists. + */ +predicate operandForFullyConvertedCall(Operand operand, CallInstruction call) { + operand = unique(Operand cand | operandForFullyConvertedCallImpl(cand, call)) +} + +private predicate instructionForFullyConvertedCallWithConversions( + Instruction instr, CallInstruction call +) { + instr = + getUse(unique(Operand operand | + operand = fullyConvertedCallStep*(getAUse(call)) and + not exists(fullyConvertedCallStep(operand)) + )) +} + +/** + * Gets the instruction that represents the first use of the value of `call` following + * a sequence of conversion-like instructions. + * + * This predicate only holds if there is no suitable operand (i.e., no operand of a non- + * conversion instruction) to use to represent the value of `call` after conversions. + */ +predicate instructionForFullyConvertedCall(Instruction instr, CallInstruction call) { + // Only pick an instruction for the call if we cannot pick a unique operand. + not operandForFullyConvertedCall(_, call) and + ( + // If there is no use of the call then we pick the call instruction + not instructionForFullyConvertedCallWithConversions(_, call) and + instr = call + or + // Otherwise, flow to the first instruction that defines multiple operands. + instructionForFullyConvertedCallWithConversions(instr, call) + ) +} + +/** Holds if `node` represents the output node for `call`. */ +private predicate simpleOutNode(Node node, CallInstruction call) { + operandForFullyConvertedCall(node.asOperand(), call) + or + instructionForFullyConvertedCall(node.asInstruction(), call) +} + /** A data flow node that represents the output of a call. */ -class OutNode extends InstructionNode { +class OutNode extends Node { OutNode() { - instr instanceof CallInstruction or - instr instanceof WriteSideEffectInstruction + // Return values not hidden behind indirections + simpleOutNode(this, _) + or + // Return values hidden behind indirections + this instanceof IndirectReturnOutNode + or + // Modified arguments hidden behind indirections + this instanceof IndirectArgumentOutNode } /** Gets the underlying call. */ @@ -209,20 +573,28 @@ class OutNode extends InstructionNode { abstract ReturnKind getReturnKind(); } -private class CallOutNode extends OutNode { - override CallInstruction instr; +private class DirectCallOutNode extends OutNode { + CallInstruction call; - override DataFlowCall getCall() { result = instr } + DirectCallOutNode() { simpleOutNode(this, call) } - override ReturnKind getReturnKind() { result instanceof NormalReturnKind } + override DataFlowCall getCall() { result = call } + + override ReturnKind getReturnKind() { result = TNormalReturnKind(0) } } -private class SideEffectOutNode extends OutNode { - override WriteSideEffectInstruction instr; +private class IndirectCallOutNode extends OutNode, IndirectReturnOutNode { + override DataFlowCall getCall() { result = this.getCallInstruction() } - override DataFlowCall getCall() { result = instr.getPrimaryInstruction() } + override ReturnKind getReturnKind() { result = TNormalReturnKind(this.getIndirectionIndex()) } +} - override ReturnKind getReturnKind() { result = TIndirectReturnKind(instr.getIndex()) } +private class SideEffectOutNode extends OutNode, IndirectArgumentOutNode { + override DataFlowCall getCall() { result = this.getCallInstruction() } + + override ReturnKind getReturnKind() { + result = TIndirectReturnKind(this.getArgumentIndex(), this.getIndirectionIndex()) + } } /** @@ -230,13 +602,8 @@ private class SideEffectOutNode extends OutNode { * `kind`. */ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { - // There should be only one `OutNode` for a given `(call, kind)` pair. Showing the optimizer that - // this is true helps it make better decisions downstream, especially in virtual dispatch. - result = - unique(OutNode outNode | - outNode.getCall() = call and - outNode.getReturnKind() = kind - ) + result.getCall() = call and + result.getReturnKind() = kind } /** @@ -245,22 +612,26 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) { * global or static variable. */ predicate jumpStep(Node n1, Node n2) { - exists(GlobalOrNamespaceVariable v | - v = - n1.asInstruction() - .(StoreInstruction) - .getResultAddress() - .(VariableAddressInstruction) - .getAstVariable() and - v = n2.asVariable() + exists(Cpp::GlobalOrNamespaceVariable v | + exists(Ssa::GlobalUse globalUse | + v = globalUse.getVariable() and + n1.(FinalGlobalValue).getGlobalUse() = globalUse + | + globalUse.getIndirectionIndex() = 1 and + v = n2.asVariable() + or + v = n2.asIndirectVariable(globalUse.getIndirectionIndex()) + ) or - v = - n2.asInstruction() - .(LoadInstruction) - .getSourceAddress() - .(VariableAddressInstruction) - .getAstVariable() and - v = n1.asVariable() + exists(Ssa::GlobalDef globalDef | + v = globalDef.getVariable() and + n2.(InitialGlobalValue).getGlobalDef() = globalDef + | + globalDef.getIndirectionIndex() = 1 and + v = n1.asVariable() + or + v = n1.asIndirectVariable(globalDef.getIndirectionIndex()) + ) ) } @@ -269,24 +640,94 @@ predicate jumpStep(Node n1, Node n2) { * Thus, `node2` references an object with a field `f` that contains the * value of `node1`. */ -predicate storeStep(StoreNodeInstr node1, FieldContent f, StoreNodeInstr node2) { - exists(FieldAddressInstruction fai | - node1.getInstruction() = fai and - node2.getInstruction() = fai.getObjectAddress() and - f.getField() = fai.getField() +predicate storeStep(Node node1, Content c, PostFieldUpdateNode node2) { + exists(int indirectionIndex1, int numberOfLoads, StoreInstruction store | + nodeHasInstruction(node1, store, pragma[only_bind_into](indirectionIndex1)) and + node2.getIndirectionIndex() = 1 and + numberOfLoadsFromOperand(node2.getFieldAddress(), store.getDestinationAddressOperand(), + numberOfLoads) + | + exists(FieldContent fc | fc = c | + fc.getField() = node2.getUpdatedField() and + fc.getIndirectionIndex() = 1 + indirectionIndex1 + numberOfLoads + ) + or + exists(UnionContent uc | uc = c | + uc.getAField() = node2.getUpdatedField() and + uc.getIndirectionIndex() = 1 + indirectionIndex1 + numberOfLoads + ) ) } +/** + * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like + * operations and exactly `n` `LoadInstruction` operations. + */ +private predicate numberOfLoadsFromOperandRec(Operand operandFrom, Operand operandTo, int ind) { + exists(Instruction load | Ssa::isDereference(load, operandFrom) | + operandTo = operandFrom and ind = 0 + or + numberOfLoadsFromOperand(load.getAUse(), operandTo, ind - 1) + ) + or + exists(Operand op, Instruction instr | + instr = op.getDef() and + conversionFlow(operandFrom, instr, _, _) and + numberOfLoadsFromOperand(op, operandTo, ind) + ) +} + +/** + * Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like + * operations and exactly `n` `LoadInstruction` operations. + */ +private predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n) { + numberOfLoadsFromOperandRec(operandFrom, operandTo, n) + or + not Ssa::isDereference(_, operandFrom) and + not conversionFlow(operandFrom, _, _, _) and + operandFrom = operandTo and + n = 0 +} + +// Needed to join on both an operand and an index at the same time. +pragma[noinline] +predicate nodeHasOperand(Node node, Operand operand, int indirectionIndex) { + node.asOperand() = operand and indirectionIndex = 0 + or + hasOperandAndIndex(node, operand, indirectionIndex) +} + +// Needed to join on both an instruction and an index at the same time. +pragma[noinline] +predicate nodeHasInstruction(Node node, Instruction instr, int indirectionIndex) { + node.asInstruction() = instr and indirectionIndex = 0 + or + hasInstructionAndIndex(node, instr, indirectionIndex) +} + /** * Holds if data can flow from `node1` to `node2` via a read of `f`. * Thus, `node1` references an object with a field `f` whose value ends up in * `node2`. */ -predicate readStep(ReadNode node1, FieldContent f, ReadNode node2) { - exists(FieldAddressInstruction fai | - node1.getInstruction() = fai.getObjectAddress() and - node2.getInstruction() = fai and - f.getField() = fai.getField() +predicate readStep(Node node1, Content c, Node node2) { + exists(FieldAddress fa1, Operand operand, int numberOfLoads, int indirectionIndex2 | + nodeHasOperand(node2, operand, indirectionIndex2) and + // The `1` here matches the `node2.getIndirectionIndex() = 1` conjunct + // in `storeStep`. + nodeHasOperand(node1, fa1.getObjectAddressOperand(), 1) and + numberOfLoadsFromOperand(fa1, operand, numberOfLoads) + | + exists(FieldContent fc | fc = c | + fc.getField() = fa1.getField() and + fc.getIndirectionIndex() = indirectionIndex2 + numberOfLoads + ) + or + exists(UnionContent uc | uc = c | + uc.getAField() = fa1.getField() and + uc.getIndirectionIndex() = indirectionIndex2 + numberOfLoads + ) ) } @@ -304,20 +745,20 @@ predicate clearsContent(Node n, Content c) { predicate expectsContent(Node n, ContentSet c) { none() } /** Gets the type of `n` used for type pruning. */ -IRType getNodeType(Node n) { +DataFlowType getNodeType(Node n) { suppressUnusedNode(n) and - result instanceof IRVoidType // stub implementation + result instanceof VoidType // stub implementation } /** Gets a string representation of a type returned by `getNodeType`. */ -string ppReprType(IRType t) { none() } // stub implementation +string ppReprType(DataFlowType t) { none() } // stub implementation /** * Holds if `t1` and `t2` are compatible, that is, whether data can flow from * a node of type `t1` to a node of type `t2`. */ pragma[inline] -predicate compatibleTypes(IRType t1, IRType t2) { +predicate compatibleTypes(DataFlowType t1, DataFlowType t2) { any() // stub implementation } @@ -337,11 +778,11 @@ class CastNode extends Node { * data-flow library discards call contexts and inserts a node in the big-step * relation used for human-readable path explanations. */ -class DataFlowCallable = Declaration; +class DataFlowCallable = Cpp::Declaration; class DataFlowExpr = Expr; -class DataFlowType = IRType; +class DataFlowType = Type; /** A function call relevant for data flow. */ class DataFlowCall extends CallInstruction { @@ -369,15 +810,13 @@ class Unit extends TUnit { /** Holds if `n` should be hidden from path explanations. */ predicate nodeIsHidden(Node n) { - n instanceof OperandNode and not n instanceof ArgumentNode + n instanceof OperandNode and + not n instanceof ArgumentNode and + not n.asOperand() instanceof StoreValueOperand or - StoreNodeFlow::flowThrough(n, _) and - not StoreNodeFlow::flowOutOf(n, _) and - not StoreNodeFlow::flowInto(_, n) + n instanceof FinalGlobalValue or - ReadNodeFlow::flowThrough(n, _) and - not ReadNodeFlow::flowOutOf(n, _) and - not ReadNodeFlow::flowInto(_, n) + n instanceof InitialGlobalValue } class LambdaCallKind = Unit; @@ -400,12 +839,63 @@ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preserves */ predicate allowParameterReturnInSelf(ParameterNode p) { none() } +private predicate fieldHasApproxName(Field f, string s) { + s = f.getName().charAt(0) and + // Reads and writes of union fields are tracked using `UnionContent`. + not f.getDeclaringType() instanceof Cpp::Union +} + +private predicate unionHasApproxName(Cpp::Union u, string s) { s = u.getName().charAt(0) } + +cached +private newtype TContentApprox = + TFieldApproxContent(string s) { fieldHasApproxName(_, s) } or + TUnionApproxContent(string s) { unionHasApproxName(_, s) } + /** An approximated `Content`. */ -class ContentApprox = Unit; +class ContentApprox extends TContentApprox { + string toString() { none() } // overridden in subclasses +} + +private class FieldApproxContent extends ContentApprox, TFieldApproxContent { + string s; + + FieldApproxContent() { this = TFieldApproxContent(s) } + + Field getAField() { fieldHasApproxName(result, s) } + + string getPrefix() { result = s } + + final override string toString() { result = s } +} + +private class UnionApproxContent extends ContentApprox, TUnionApproxContent { + string s; + + UnionApproxContent() { this = TUnionApproxContent(s) } + + Cpp::Union getAUnion() { unionHasApproxName(result, s) } + + string getPrefix() { result = s } + + final override string toString() { result = s } +} /** Gets an approximated value for content `c`. */ pragma[inline] -ContentApprox getContentApprox(Content c) { any() } +ContentApprox getContentApprox(Content c) { + exists(string prefix, Field f | + prefix = result.(FieldApproxContent).getPrefix() and + f = c.(FieldContent).getField() and + fieldHasApproxName(f, prefix) + ) + or + exists(string prefix, Cpp::Union u | + prefix = result.(UnionApproxContent).getPrefix() and + u = c.(UnionContent).getUnion() and + unionHasApproxName(u, prefix) + ) +} private class MyConsistencyConfiguration extends Consistency::ConsistencyConfiguration { override predicate argHasPostUpdateExclude(ArgumentNode n) { @@ -414,3 +904,113 @@ private class MyConsistencyConfiguration extends Consistency::ConsistencyConfigu any() } } + +/** + * Gets the basic block of `node`. + */ +IRBlock getBasicBlock(Node node) { + node.asInstruction().getBlock() = result + or + node.asOperand().getUse().getBlock() = result + or + node.(SsaPhiNode).getPhiNode().getBasicBlock() = result + or + node.(RawIndirectOperand).getOperand().getUse().getBlock() = result + or + node.(RawIndirectInstruction).getInstruction().getBlock() = result + or + result = getBasicBlock(node.(PostUpdateNode).getPreUpdateNode()) +} + +/** + * A local flow relation that includes both local steps, read steps and + * argument-to-return flow through summarized functions. + */ +private predicate localFlowStepWithSummaries(Node node1, Node node2) { + localFlowStep(node1, node2) + or + readStep(node1, _, node2) + or + DataFlowImplCommon::argumentValueFlowsThrough(node1, _, node2) +} + +/** Holds if `node` flows to a node that is used in a `SwitchInstruction`. */ +private predicate localStepsToSwitch(Node node) { + node.asOperand() = any(SwitchInstruction switch).getExpressionOperand() + or + exists(Node succ | + localStepsToSwitch(succ) and + localFlowStepWithSummaries(node, succ) + ) +} + +/** + * Holds if `node` is part of a path from a `ParameterNode` to an operand + * of a `SwitchInstruction`. + */ +private predicate localStepsFromParameterToSwitch(Node node) { + localStepsToSwitch(node) and + ( + node instanceof ParameterNode + or + exists(Node prev | + localStepsFromParameterToSwitch(prev) and + localFlowStepWithSummaries(prev, node) + ) + ) +} + +/** + * The local flow relation `localFlowStepWithSummaries` pruned to only + * include steps that are part of a path from a `ParameterNode` to an + * operand of a `SwitchInstruction`. + */ +private predicate getAdditionalFlowIntoCallNodeTermStep(Node node1, Node node2) { + localStepsFromParameterToSwitch(node1) and + localStepsFromParameterToSwitch(node2) and + localFlowStepWithSummaries(node1, node2) +} + +/** Gets the `IRVariable` associated with the parameter node `p`. */ +pragma[nomagic] +private IRVariable getIRVariableForParameterNode(ParameterNode p) { + result = p.(DirectParameterNode).getIRVariable() + or + result.getAst() = p.(IndirectParameterNode).getParameter() +} + +/** Holds if `v` is the source variable corresponding to the parameter represented by `p`. */ +pragma[nomagic] +private predicate parameterNodeHasSourceVariable(ParameterNode p, Ssa::SourceIRVariable v) { + v.getIRVariable() = getIRVariableForParameterNode(p) and + exists(Position pos | p.isParameterOf(_, pos) | + pos instanceof DirectPosition and + v.getIndirection() = 1 + or + pos.(IndirectionPosition).getIndirectionIndex() + 1 = v.getIndirection() + ) +} + +private EdgeKind caseOrDefaultEdge() { + result instanceof CaseEdge or + result instanceof DefaultEdge +} + +/** + * Gets the number of switch branches that that read from (or write to) the parameter `p`. + */ +private int countNumberOfBranchesUsingParameter(SwitchInstruction switch, ParameterNode p) { + exists(Ssa::SourceVariable sv | + parameterNodeHasSourceVariable(p, sv) and + // Count the number of cases that use the parameter. We do this by finding the phi node + // that merges the uses/defs of the parameter. There might be multiple such phi nodes, so + // we pick the one with the highest edge count. + result = + max(SsaPhiNode phi | + switch.getSuccessor(caseOrDefaultEdge()).getBlock().dominanceFrontier() = getBasicBlock(phi) and + phi.getSourceVariable() = sv + | + strictcount(phi.getAnInput()) + ) + ) +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 184472c91a7..714e5bd3b49 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -11,80 +11,121 @@ private import semmle.code.cpp.ir.IR private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.models.interfaces.DataFlow private import DataFlowPrivate +private import ModelUtil private import SsaInternals as Ssa +private import DataFlowImplCommon as DataFlowImplCommon +/** + * The IR dataflow graph consists of the following nodes: + * - `Node0`, which injects most instructions and operands directly into the dataflow graph. + * - `VariableNode`, which is used to model flow through global variables. + * - `PostFieldUpdateNode`, which is used to model the state of a field after a value has been stored + * into an address after a number of loads. + * - `SsaPhiNode`, which represents phi nodes as computed by the shared SSA library. + * - `IndirectArgumentOutNode`, which represents the value of an argument (and its indirections) after + * it leaves a function call. + * - `RawIndirectOperand`, which represents the value of `operand` after loading the address a number + * of times. + * - `RawIndirectInstruction`, which represents the value of `instr` after loading the address a number + * of times. + */ cached -private module Cached { - /** - * The IR dataflow graph consists of the following nodes: - * - `InstructionNode`, which represents an `Instruction` in the graph. - * - `OperandNode`, which represents an `Operand` in the graph. - * - `VariableNode`, which is used to model global variables. - * - Two kinds of `StoreNode`s: - * 1. `StoreNodeInstr`, which represents the value of an address computed by an `Instruction` that - * has been updated by a write operation. - * 2. `StoreNodeOperand`, which represents the value of an address in an `ArgumentOperand` after a - * function call that may have changed the value. - * - `ReadNode`, which represents the result of reading a field of an object. - * - `SsaPhiNode`, which represents phi nodes as computed by the shared SSA library. - * - * The following section describes how flow is generally transferred between these nodes: - * - Flow between `InstructionNode`s and `OperandNode`s follow the def-use information as computed by - * the IR. Because the IR compute must-alias information for memory operands, we only follow def-use - * flow for register operands. - * - Flow can enter a `StoreNode` in two ways (both done in `StoreNode.flowInto`): - * 1. Flow is transferred from a `StoreValueOperand` to a `StoreNodeInstr`. Flow will then proceed - * along the chain of addresses computed by `StoreNodeInstr.getInner` to identify field writes - * and call `storeStep` accordingly (i.e., for an expression like `a.b.c = x`, we visit `c`, then - * `b`, then `a`). - * 2. Flow is transferred from a `WriteSideEffectInstruction` to a `StoreNodeOperand` after flow - * returns to a caller. Flow will then proceed to the defining instruction of the operand (because - * the `StoreNodeInstr` computed by `StoreNodeOperand.getInner()` is the `StoreNode` containing - * the defining instruction), and then along the chain computed by `StoreNodeInstr.getInner` like - * above. - * In both cases, flow leaves a `StoreNode` once the entire chain has been traversed, and the shared - * SSA library is used to find the next use of the variable at the end of the chain. - * - Flow can enter a `ReadNode` through an `OperandNode` that represents an address of some variable. - * Flow will then proceed along the chain of addresses computed by `ReadNode.getOuter` (i.e., for an - * expression like `use(a.b.c)` we visit `a`, then `b`, then `c`) and call `readStep` accordingly. - * Once the entire chain has been traversed, flow is transferred to the load instruction that reads - * the final address of the chain. - * - Flow can enter a `SsaPhiNode` from an `InstructionNode`, a `StoreNode` or another `SsaPhiNode` - * (in `toPhiNode`), depending on which node provided the previous definition of the underlying - * variable. Flow leaves a `SsaPhiNode` (in `fromPhiNode`) by using the shared SSA library to - * determine the next use of the variable. - */ - cached - newtype TIRDataFlowNode = - TInstructionNode(Instruction i) or - TOperandNode(Operand op) or - TVariableNode(Variable var) or - TStoreNodeInstr(Instruction i) { Ssa::explicitWrite(_, _, i) } or - TStoreNodeOperand(ArgumentOperand op) { Ssa::explicitWrite(_, _, op.getDef()) } or - TReadNode(Instruction i) { needsPostReadNode(i) } or - TSsaPhiNode(Ssa::PhiNode phi) - - cached - predicate localFlowStepCached(Node nodeFrom, Node nodeTo) { - simpleLocalFlowStep(nodeFrom, nodeTo) - } - - private predicate needsPostReadNode(Instruction iFrom) { - // If the instruction generates an address that flows to a load. - Ssa::addressFlowTC(iFrom, Ssa::getSourceAddress(_)) and - ( - // And it is either a field address - iFrom instanceof FieldAddressInstruction - or - // Or it is instruction that either uses or is used for an address that needs a post read node. - exists(Instruction mid | needsPostReadNode(mid) | - Ssa::addressFlow(mid, iFrom) or Ssa::addressFlow(iFrom, mid) - ) +private newtype TIRDataFlowNode = + TNode0(Node0Impl node) { DataFlowImplCommon::forceCachingInSameStage() } or + TVariableNode(Variable var, int indirectionIndex) { + indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(var.getUnspecifiedType())] + } or + TPostFieldUpdateNode(FieldAddress operand, int indirectionIndex) { + indirectionIndex = + [1 .. Ssa::countIndirectionsForCppType(operand.getObjectAddress().getResultLanguageType())] + } or + TSsaPhiNode(Ssa::PhiNode phi) or + TIndirectArgumentOutNode(ArgumentOperand operand, int indirectionIndex) { + Ssa::isModifiableByCall(operand, indirectionIndex) + } or + TRawIndirectOperand(Operand op, int indirectionIndex) { + Ssa::hasRawIndirectOperand(op, indirectionIndex) + } or + TRawIndirectInstruction(Instruction instr, int indirectionIndex) { + Ssa::hasRawIndirectInstruction(instr, indirectionIndex) + } or + TFinalParameterNode(Parameter p, int indirectionIndex) { + exists(Ssa::FinalParameterUse use | + use.getParameter() = p and + use.getIndirectionIndex() = indirectionIndex and + parameterIsRedefined(p) ) - } + } or + TFinalGlobalValue(Ssa::GlobalUse globalUse) or + TInitialGlobalValue(Ssa::GlobalDef globalUse) + +/** + * Holds if the value of `*p` (or `**p`, `***p`, etc.) is redefined somewhere in the body + * of the enclosing function of `p`. + * + * Only parameters satisfying this predicate will generate a `FinalParameterNode` transferring + * flow out of the function. + */ +private predicate parameterIsRedefined(Parameter p) { + exists(Ssa::Def def | + def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() = p and + def.getIndirectionIndex() = 0 and + def.getIndirection() > 1 and + not def.getValue().asInstruction() instanceof InitializeParameterInstruction + ) } -private import Cached +/** + * An operand that is defined by a `FieldAddressInstruction`. + */ +class FieldAddress extends Operand { + FieldAddressInstruction fai; + + FieldAddress() { fai = this.getDef() } + + /** Gets the field associated with this instruction. */ + Field getField() { result = fai.getField() } + + /** Gets the instruction whose result provides the address of the object containing the field. */ + Instruction getObjectAddress() { result = fai.getObjectAddress() } + + /** Gets the operand that provides the address of the object containing the field. */ + Operand getObjectAddressOperand() { result = fai.getObjectAddressOperand() } +} + +/** + * Holds if `opFrom` is an operand whose value flows to the result of `instrTo`. + * + * `isPointerArith` is `true` if `instrTo` is a `PointerArithmeticInstruction` and `opFrom` + * is the left operand. + * + * `additional` is `true` if the conversion is supplied by an implementation of the + * `Indirection` class. It is sometimes useful to exclude such conversions. + */ +predicate conversionFlow( + Operand opFrom, Instruction instrTo, boolean isPointerArith, boolean additional +) { + isPointerArith = false and + ( + additional = false and + ( + instrTo.(CopyValueInstruction).getSourceValueOperand() = opFrom + or + instrTo.(ConvertInstruction).getUnaryOperand() = opFrom + or + instrTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom + or + instrTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom + ) + or + additional = true and + Ssa::isAdditionalConversionFlow(opFrom, instrTo) + ) + or + isPointerArith = true and + additional = false and + instrTo.(PointerArithmeticInstruction).getLeftOperand() = opFrom +} /** * A node in a data flow graph. @@ -102,8 +143,16 @@ class Node extends TIRDataFlowNode { /** Gets the function to which this node belongs, if any. */ Declaration getFunction() { none() } // overridden in subclasses - /** Gets the type of this node. */ - IRType getType() { none() } // overridden in subclasses + /** Holds if this node represents a glvalue. */ + predicate isGLValue() { none() } + + /** + * Gets the type of this node. + * + * If `isGLValue()` holds, then the type of this node + * should be thought of as "pointer to `getType()`". + */ + DataFlowType getType() { none() } // overridden in subclasses /** Gets the instruction corresponding to this node, if any. */ Instruction asInstruction() { result = this.(InstructionNode).getInstruction() } @@ -124,12 +173,38 @@ class Node extends TIRDataFlowNode { */ Expr asExpr() { result = this.(ExprNode).getExpr() } + /** + * Gets the non-conversion expression that's indirectly tracked by this node + * under `index` number of indirections. + */ + Expr asIndirectExpr(int index) { result = this.(IndirectExprNode).getExpr(index) } + + /** + * Gets the non-conversion expression that's indirectly tracked by this node + * behind a number of indirections. + */ + Expr asIndirectExpr() { result = this.asIndirectExpr(_) } + /** * Gets the expression corresponding to this node, if any. The returned * expression may be a `Conversion`. */ Expr asConvertedExpr() { result = this.(ExprNode).getConvertedExpr() } + /** + * Gets the expression that's indirectly tracked by this node + * behind `index` number of indirections. + */ + Expr asIndirectConvertedExpr(int index) { + result = this.(IndirectExprNode).getConvertedExpr(index) + } + + /** + * Gets the expression that's indirectly tracked by this node behind a + * number of indirections. + */ + Expr asIndirectConvertedExpr() { result = this.asIndirectConvertedExpr(_) } + /** * Gets the argument that defines this `DefinitionByReferenceNode`, if any. * This predicate should be used instead of `asExpr` when referring to the @@ -137,16 +212,111 @@ class Node extends TIRDataFlowNode { * in `f(&x)`, this predicate will have `&x` as its result for the `Node` * that represents the new value of `x`. */ - Expr asDefiningArgument() { result = this.(DefinitionByReferenceNode).getArgument() } + Expr asDefiningArgument() { result = this.asDefiningArgument(_) } + + /** + * Gets the argument that defines this `DefinitionByReferenceNode`, if any. + * + * Unlike `Node::asDefiningArgument/0`, this predicate gets the node representing + * the value of the `index`'th indirection after leaving a function. For example, + * in: + * ```cpp + * void f(int**); + * ... + * int** x = ...; + * f(x); + * ``` + * The node `n` such that `n.asDefiningArgument(1)` is the argument `x` will + * contain the value of `*x` after `f` has returned, and the node `n` such that + * `n.asDefiningArgument(2)` is the argument `x` will contain the value of `**x` + * after the `f` has returned. + */ + Expr asDefiningArgument(int index) { + // Subtract one because `DefinitionByReferenceNode` is defined to be in + // the range `[0 ... n - 1]` for some `n` instead of `[1 ... n]`. + this.(DefinitionByReferenceNode).getIndirectionIndex() = index - 1 and + result = this.(DefinitionByReferenceNode).getArgument() + } + + /** + * Gets the the argument going into a function for a node that represents + * the indirect value of the argument after `index` loads. For example, in: + * ```cpp + * void f(int**); + * ... + * int** x = ...; + * f(x); + * ``` + * The node `n` such that `n.asIndirectArgument(1)` represents the value of + * `*x` going into `f`, and the node `n` such that `n.asIndirectArgument(2)` + * represents the value of `**x` going into `f`. + */ + Expr asIndirectArgument(int index) { + this.(SideEffectOperandNode).getIndirectionIndex() = index and + result = this.(SideEffectOperandNode).getArgument() + } + + /** + * Gets the the argument going into a function for a node that represents + * the indirect value of the argument after any non-zero number of loads. + */ + Expr asIndirectArgument() { result = this.asIndirectArgument(_) } /** Gets the positional parameter corresponding to this node, if any. */ - Parameter asParameter() { result = this.(ExplicitParameterNode).getParameter() } + Parameter asParameter() { + exists(int indirectionIndex | result = this.asParameter(indirectionIndex) | + if result.getUnspecifiedType() instanceof ReferenceType + then indirectionIndex = 1 + else indirectionIndex = 0 + ) + } + + /** + * Gets the uninitialized local variable corresponding to this node, if + * any. + */ + LocalVariable asUninitialized() { result = this.(UninitializedNode).getLocalVariable() } + + /** + * Gets the positional parameter corresponding to the node that represents + * the value of the parameter after `index` number of loads, if any. For + * example, in: + * ```cpp + * void f(int** x) { ... } + * ``` + * - The node `n` such that `n.asParameter(0)` is the parameter `x` represents + * the value of `x`. + * - The node `n` such that `n.asParameter(1)` is the parameter `x` represents + * the value of `*x`. + * - The node `n` such that `n.asParameter(2)` is the parameter `x` represents + * the value of `**x`. + */ + Parameter asParameter(int index) { + index = 0 and + result = this.(ExplicitParameterNode).getParameter() + or + this.(IndirectParameterNode).getIndirectionIndex() = index and + result = this.(IndirectParameterNode).getParameter() + } /** * Gets the variable corresponding to this node, if any. This can be used for * modeling flow in and out of global variables. */ - Variable asVariable() { result = this.(VariableNode).getVariable() } + Variable asVariable() { this = TVariableNode(result, 1) } + + /** + * Gets the `indirectionIndex`'th indirection of this node's underlying variable, if any. + * + * This can be used for modeling flow in and out of global variables. + */ + Variable asIndirectVariable(int indirectionIndex) { + indirectionIndex > 1 and + this = TVariableNode(result, indirectionIndex) + } + + /** Gets an indirection of this node's underlying variable, if any. */ + Variable asIndirectVariable() { result = this.asIndirectVariable(_) } /** * Gets the expression that is partially defined by this node, if any. @@ -161,10 +331,16 @@ class Node extends TIRDataFlowNode { /** * Gets an upper bound on the type of this node. */ - IRType getTypeBound() { result = this.getType() } + DataFlowType getTypeBound() { result = this.getType() } /** Gets the location of this element. */ - Location getLocation() { none() } // overridden by subclasses + cached + final Location getLocation() { result = this.getLocationImpl() } + + /** INTERNAL: Do not use. */ + Location getLocationImpl() { + none() // overridden by subclasses + } /** * Holds if this element is at the specified location. @@ -180,245 +356,141 @@ class Node extends TIRDataFlowNode { } /** Gets a textual representation of this element. */ - string toString() { none() } // overridden by subclasses + cached + final string toString() { + result = toExprString(this) + or + not exists(toExprString(this)) and + result = this.toStringImpl() + } + + /** INTERNAL: Do not use. */ + string toStringImpl() { + none() // overridden by subclasses + } +} + +private string toExprString(Node n) { + result = n.asExpr().toString() + or + result = n.asIndirectExpr().toString() + " indirection" +} + +/** + * A class that lifts pre-SSA dataflow nodes to regular dataflow nodes. + */ +private class Node0 extends Node, TNode0 { + Node0Impl node; + + Node0() { this = TNode0(node) } + + override Declaration getEnclosingCallable() { result = node.getEnclosingCallable() } + + override Declaration getFunction() { result = node.getFunction() } + + override DataFlowType getType() { result = node.getType() } + + override predicate isGLValue() { node.isGLValue() } } /** * An instruction, viewed as a node in a data flow graph. */ -class InstructionNode extends Node, TInstructionNode { +class InstructionNode extends Node0 { + override InstructionNode0 node; Instruction instr; - InstructionNode() { this = TInstructionNode(instr) } + InstructionNode() { instr = node.getInstruction() } /** Gets the instruction corresponding to this node. */ Instruction getInstruction() { result = instr } - override Declaration getEnclosingCallable() { result = this.getFunction() } + override Location getLocationImpl() { + if exists(instr.getAst().getLocation()) + then result = instr.getAst().getLocation() + else result instanceof UnknownDefaultLocation + } - override Declaration getFunction() { result = instr.getEnclosingFunction() } - - override IRType getType() { result = instr.getResultIRType() } - - override Location getLocation() { result = instr.getLocation() } - - override string toString() { - // This predicate is overridden in subclasses. This default implementation - // does not use `Instruction.toString` because that's expensive to compute. - result = this.getInstruction().getOpcode().toString() + override string toStringImpl() { + if instr.(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable + then result = "this" + else result = instr.getAst().toString() } } /** * An operand, viewed as a node in a data flow graph. */ -class OperandNode extends Node, TOperandNode { +class OperandNode extends Node, Node0 { + override OperandNode0 node; Operand op; - OperandNode() { this = TOperandNode(op) } + OperandNode() { op = node.getOperand() } /** Gets the operand corresponding to this node. */ Operand getOperand() { result = op } - override Declaration getEnclosingCallable() { result = this.getFunction() } + override Location getLocationImpl() { + if exists(op.getDef().getAst().getLocation()) + then result = op.getDef().getAst().getLocation() + else result instanceof UnknownDefaultLocation + } - override Declaration getFunction() { result = op.getUse().getEnclosingFunction() } + override string toStringImpl() { + if op.getDef().(InitializeParameterInstruction).getIRVariable() instanceof IRThisVariable + then result = "this" + else result = op.getDef().getAst().toString() + } +} - override IRType getType() { result = op.getIRType() } - - override Location getLocation() { result = op.getLocation() } - - override string toString() { result = this.getOperand().toString() } +/** + * INTERNAL: Do not use. + * + * Returns `t`, but stripped of the outermost pointer, reference, etc. + * + * For example, `stripPointers(int*&)` is `int*` and `stripPointers(int*)` is `int`. + */ +Type stripPointer(Type t) { + result = any(Ssa::Indirection ind | ind.getType() = t).getBaseType() + or + result = t.(PointerToMemberType).getBaseType() + or + result = t.(FunctionPointerIshType).getBaseType() } /** * INTERNAL: do not use. * - * A `StoreNode` is a node that has been (or is about to be) the - * source or target of a `storeStep`. + * The node representing the value of a field after it has been updated. */ -abstract private class StoreNode extends Node { - /** Holds if this node should receive flow from `addr`. */ - abstract predicate flowInto(Instruction addr); +class PostFieldUpdateNode extends TPostFieldUpdateNode, PartialDefinitionNode { + int indirectionIndex; + FieldAddress fieldAddress; + + PostFieldUpdateNode() { this = TPostFieldUpdateNode(fieldAddress, indirectionIndex) } + + override Declaration getFunction() { result = fieldAddress.getUse().getEnclosingFunction() } override Declaration getEnclosingCallable() { result = this.getFunction() } - /** Holds if this `StoreNode` is the root of the address computation used by a store operation. */ - predicate isTerminal() { - not exists(this.getInner()) and - not storeStep(this, _, _) + FieldAddress getFieldAddress() { result = fieldAddress } + + Field getUpdatedField() { result = fieldAddress.getField() } + + int getIndirectionIndex() { result = indirectionIndex } + + override Node getPreUpdateNode() { + hasOperandAndIndex(result, pragma[only_bind_into](fieldAddress).getObjectAddressOperand(), + indirectionIndex) } - /** Gets the store operation that uses the address computed by this `StoreNode`. */ - abstract Instruction getStoreInstruction(); - - /** Holds if the store operation associated with this `StoreNode` overwrites the entire variable. */ - final predicate isCertain() { Ssa::explicitWrite(true, this.getStoreInstruction(), _) } - - /** - * Gets the `StoreNode` that computes the address used by this `StoreNode`. - */ - abstract StoreNode getInner(); - - /** The inverse of `StoreNode.getInner`. */ - final StoreNode getOuter() { result.getInner() = this } -} - -class StoreNodeInstr extends StoreNode, TStoreNodeInstr { - Instruction instr; - - StoreNodeInstr() { this = TStoreNodeInstr(instr) } - - override predicate flowInto(Instruction addr) { this.getInstruction() = addr } - - /** Gets the underlying instruction. */ - Instruction getInstruction() { result = instr } - - override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } - - override IRType getType() { result = this.getInstruction().getResultIRType() } - - override Location getLocation() { result = this.getInstruction().getLocation() } - - override string toString() { - result = instructionNode(this.getInstruction()).toString() + " [store]" + override Expr getDefinedExpr() { + result = fieldAddress.getObjectAddress().getUnconvertedResultExpression() } - override Instruction getStoreInstruction() { - Ssa::explicitWrite(_, result, this.getInstruction()) - } + override Location getLocationImpl() { result = fieldAddress.getLocation() } - override StoreNodeInstr getInner() { - Ssa::addressFlow(result.getInstruction(), this.getInstruction()) - } -} - -/** - * To avoid having `PostUpdateNode`s with multiple pre-update nodes (which can cause performance - * problems) we attach the `PostUpdateNode` that represent output arguments to an operand instead of - * an instruction. - * - * To see why we need this, consider the expression `b->set(new C())`. The IR of this expression looks - * like (simplified): - * ``` - * r1(glval) = FunctionAddress[set] : - * r2(glval) = FunctionAddress[operator new] : - * r3(unsigned long) = Constant[8] : - * r4(void *) = Call[operator new] : func:r2, 0:r3 - * r5(C *) = Convert : r4 - * r6(glval) = FunctionAddress[C] : - * v1(void) = Call[C] : func:r6, this:r5 - * v2(void) = Call[set] : func:r1, this:r0, 0:r5 - * ``` - * - * Notice that both the call to `C` and the call to `set` will have an argument that is the - * result of calling `operator new` (i.e., `r4`). If we only have `PostUpdateNode`s that are - * instructions, both `PostUpdateNode`s would have `r4` as their pre-update node. - * - * We avoid this issue by having a `PostUpdateNode` for each argument, and let the pre-update node of - * each `PostUpdateNode` be the argument _operand_, instead of the defining instruction. - */ -class StoreNodeOperand extends StoreNode, TStoreNodeOperand { - ArgumentOperand operand; - - StoreNodeOperand() { this = TStoreNodeOperand(operand) } - - override predicate flowInto(Instruction addr) { this.getOperand().getDef() = addr } - - /** Gets the underlying operand. */ - Operand getOperand() { result = operand } - - override Declaration getFunction() { result = operand.getDef().getEnclosingFunction() } - - override IRType getType() { result = operand.getIRType() } - - override Location getLocation() { result = operand.getLocation() } - - override string toString() { result = operandNode(this.getOperand()).toString() + " [store]" } - - override WriteSideEffectInstruction getStoreInstruction() { - Ssa::explicitWrite(_, result, operand.getDef()) - } - - /** - * The result of `StoreNodeOperand.getInner` is the `StoreNodeInstr` representation the instruction - * that defines this operand. This means the graph of `getInner` looks like this: - * ``` - * I---I---I - * \ \ \ - * O O O - * ``` - * where each `StoreNodeOperand` "hooks" into the chain computed by `StoreNodeInstr.getInner`. - * This means that the chain of `getInner` calls on the argument `&o.f` on an expression - * like `func(&o.f)` is: - * ``` - * r4---r3---r2 - * \ - * 0:r4 - * ``` - * where the IR for `func(&o.f)` looks like (simplified): - * ``` - * r1(glval) = FunctionAddress[func] : - * r2(glval) = VariableAddress[o] : - * r3(glval) = FieldAddress[f] : r2 - * r4(int *) = CopyValue : r3 - * v1(void) = Call[func] : func:r1, 0:r4 - * ``` - */ - override StoreNodeInstr getInner() { operand.getDef() = result.getInstruction() } -} - -/** - * INTERNAL: do not use. - * - * A `ReadNode` is a node that has been (or is about to be) the - * source or target of a `readStep`. - */ -class ReadNode extends Node, TReadNode { - Instruction i; - - ReadNode() { this = TReadNode(i) } - - /** Gets the underlying instruction. */ - Instruction getInstruction() { result = i } - - override Declaration getEnclosingCallable() { result = this.getFunction() } - - override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } - - override IRType getType() { result = this.getInstruction().getResultIRType() } - - override Location getLocation() { result = this.getInstruction().getLocation() } - - override string toString() { - result = instructionNode(this.getInstruction()).toString() + " [read]" - } - - /** Gets a load instruction that uses the address computed by this read node. */ - final Instruction getALoadInstruction() { - Ssa::addressFlowTC(this.getInstruction(), Ssa::getSourceAddress(result)) - } - - /** - * Gets a read node with an underlying instruction that is used by this - * underlying instruction to compute an address of a load instruction. - */ - final ReadNode getInner() { Ssa::addressFlow(result.getInstruction(), this.getInstruction()) } - - /** The inverse of `ReadNode.getInner`. */ - final ReadNode getOuter() { result.getInner() = this } - - /** Holds if this read node computes a value that will not be used for any future read nodes. */ - final predicate isTerminal() { - not exists(this.getOuter()) and - not readStep(this, _, _) - } - - /** Holds if this read node computes a value that has not yet been used for any read operations. */ - final predicate isInitial() { - not exists(this.getInner()) and - not readStep(_, _, this) - } + override string toStringImpl() { result = this.getPreUpdateNode() + " [post update]" } } /** @@ -438,48 +510,697 @@ class SsaPhiNode extends Node, TSsaPhiNode { override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() } - override IRType getType() { result instanceof IRVoidType } - - override Location getLocation() { result = phi.getBasicBlock().getLocation() } - - /** Holds if this phi node has input from the `rnk`'th write operation in block `block`. */ - final predicate hasInputAtRankInBlock(IRBlock block, int rnk) { - this.hasInputAtRankInBlock(block, rnk, _) + override DataFlowType getType() { + exists(Ssa::SourceVariable sv | + this.getPhiNode().definesAt(sv, _, _, _) and + result = sv.getType() + ) } + override predicate isGLValue() { phi.getSourceVariable().isGLValue() } + + final override Location getLocationImpl() { result = phi.getBasicBlock().getLocation() } + + override string toStringImpl() { result = "Phi" } + /** - * Holds if this phi node has input from the definition `input` (which is the `rnk`'th write - * operation in block `block`). + * Gets a node that is used as input to this phi node. + * `fromBackEdge` is true if data flows along a back-edge, + * and `false` otherwise. */ - cached - final predicate hasInputAtRankInBlock(IRBlock block, int rnk, Ssa::Definition input) { - Ssa::phiHasInputFromBlock(phi, input, _) and input.definesAt(_, block, rnk) + final Node getAnInput(boolean fromBackEdge) { + localFlowStep(result, this) and + if phi.getBasicBlock().dominates(getBasicBlock(result)) + then fromBackEdge = true + else fromBackEdge = false } - override string toString() { result = "Phi" } + /** Gets a node that is used as input to this phi node. */ + final Node getAnInput() { result = this.getAnInput(_) } + + /** Gets the source variable underlying this phi node. */ + Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() } +} + +/** + * INTERNAL: do not use. + * + * A node representing a value after leaving a function. + */ +class SideEffectOperandNode extends Node, IndirectOperand { + CallInstruction call; + int argumentIndex; + + SideEffectOperandNode() { operand = call.getArgumentOperand(argumentIndex) } + + CallInstruction getCallInstruction() { result = call } + + Operand getAddressOperand() { result = operand } + + int getArgumentIndex() { result = argumentIndex } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = call.getEnclosingFunction() } + + Expr getArgument() { result = call.getArgument(argumentIndex).getUnconvertedResultExpression() } +} + +/** + * INTERNAL: do not use. + * + * A node representing the value of a global variable just before returning + * from a function body. + */ +class FinalGlobalValue extends Node, TFinalGlobalValue { + Ssa::GlobalUse globalUse; + + FinalGlobalValue() { this = TFinalGlobalValue(globalUse) } + + /** Gets the underlying SSA use. */ + Ssa::GlobalUse getGlobalUse() { result = globalUse } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() } + + override DataFlowType getType() { + exists(int indirectionIndex | + indirectionIndex = globalUse.getIndirectionIndex() and + result = getTypeImpl(globalUse.getUnspecifiedType(), indirectionIndex - 1) + ) + } + + final override Location getLocationImpl() { result = globalUse.getLocation() } + + override string toStringImpl() { result = globalUse.toString() } +} + +/** + * INTERNAL: do not use. + * + * A node representing the value of a global variable just after entering + * a function body. + */ +class InitialGlobalValue extends Node, TInitialGlobalValue { + Ssa::GlobalDef globalDef; + + InitialGlobalValue() { this = TInitialGlobalValue(globalDef) } + + /** Gets the underlying SSA definition. */ + Ssa::GlobalDef getGlobalDef() { result = globalDef } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = globalDef.getIRFunction().getFunction() } + + final override predicate isGLValue() { globalDef.getIndirectionIndex() = 0 } + + override DataFlowType getType() { + exists(DataFlowType type | + type = globalDef.getUnspecifiedType() and + if this.isGLValue() + then result = type + else result = getTypeImpl(type, globalDef.getIndirectionIndex() - 1) + ) + } + + final override Location getLocationImpl() { result = globalDef.getLocation() } + + override string toStringImpl() { result = globalDef.toString() } +} + +/** + * INTERNAL: do not use. + * + * A node representing an indirection of a parameter. + */ +class IndirectParameterNode extends Node, IndirectInstruction { + InitializeParameterInstruction init; + + IndirectParameterNode() { this.getInstruction() = init } + + int getArgumentIndex() { init.hasIndex(result) } + + /** Gets the parameter whose indirection is initialized. */ + Parameter getParameter() { result = init.getParameter() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } + + override Location getLocationImpl() { result = this.getParameter().getLocation() } + + override string toStringImpl() { + result = this.getParameter().toString() + " indirection" + or + not exists(this.getParameter()) and + result = "this indirection" + } +} + +/** + * INTERNAL: do not use. + * + * A node representing the indirection of a value that is + * about to be returned from a function. + */ +class IndirectReturnNode extends Node { + IndirectReturnNode() { + this instanceof FinalParameterNode + or + this.(IndirectOperand).getOperand() = any(ReturnValueInstruction ret).getReturnAddressOperand() + } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + /** + * Holds if this node represents the value that is returned to the caller + * through a `return` statement. + */ + predicate isNormalReturn() { this instanceof IndirectOperand } + + /** + * Holds if this node represents the value that is returned to the caller + * by writing to the `argumentIndex`'th argument of the call. + */ + predicate isParameterReturn(int argumentIndex) { + this.(FinalParameterNode).getArgumentIndex() = argumentIndex + } + + /** Gets the indirection index of this indirect return node. */ + int getIndirectionIndex() { + result = this.(FinalParameterNode).getIndirectionIndex() + or + result = this.(IndirectOperand).getIndirectionIndex() + } +} + +/** + * INTERNAL: do not use. + * + * A node representing the indirection of a value after it + * has been returned from a function. + */ +class IndirectArgumentOutNode extends Node, TIndirectArgumentOutNode, PartialDefinitionNode { + ArgumentOperand operand; + int indirectionIndex; + + IndirectArgumentOutNode() { this = TIndirectArgumentOutNode(operand, indirectionIndex) } + + int getIndirectionIndex() { result = indirectionIndex } + + int getArgumentIndex() { + exists(CallInstruction call | call.getArgumentOperand(result) = operand) + } + + Operand getAddressOperand() { result = operand } + + CallInstruction getCallInstruction() { result.getAnArgumentOperand() = operand } + + Function getStaticCallTarget() { result = this.getCallInstruction().getStaticCallTarget() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override Declaration getFunction() { result = this.getCallInstruction().getEnclosingFunction() } + + override Node getPreUpdateNode() { hasOperandAndIndex(result, operand, indirectionIndex) } + + override string toStringImpl() { + // This string should be unique enough to be helpful but common enough to + // avoid storing too many different strings. + result = this.getStaticCallTarget().getName() + " output argument" + or + not exists(this.getStaticCallTarget()) and + result = "output argument" + } + + override Location getLocationImpl() { result = operand.getLocation() } + + override Expr getDefinedExpr() { result = operand.getDef().getUnconvertedResultExpression() } +} + +pragma[nomagic] +predicate indirectReturnOutNodeOperand0(CallInstruction call, Operand operand, int indirectionIndex) { + Ssa::hasRawIndirectInstruction(call, indirectionIndex) and + operandForFullyConvertedCall(operand, call) +} + +pragma[nomagic] +predicate indirectReturnOutNodeInstruction0( + CallInstruction call, Instruction instr, int indirectionIndex +) { + Ssa::hasRawIndirectInstruction(call, indirectionIndex) and + instructionForFullyConvertedCall(instr, call) +} + +/** + * Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and + * `operand` represents a use of the fully converted value of `call`. + */ +private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) { + indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and + hasOperandAndIndex(node, operand, indirectionIndex) +} + +/** + * Holds if `node` is an indirect instruction with columns `(instr, indirectionIndex)`, and + * `instr` represents a use of the fully converted value of `call`. + * + * Note that `hasOperand(node, _, _, _)` implies `not hasInstruction(node, _, _, _)`. + */ +private predicate hasInstruction( + Node node, CallInstruction call, int indirectionIndex, Instruction instr +) { + indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and + hasInstructionAndIndex(node, instr, indirectionIndex) +} + +/** + * INTERNAL: do not use. + * + * A node representing the indirect value of a function call (i.e., a value hidden + * behind a number of indirections). + */ +class IndirectReturnOutNode extends Node { + CallInstruction call; + int indirectionIndex; + + IndirectReturnOutNode() { + // Annoyingly, we need to pick the fully converted value as the output of the function to + // make flow through in the shared dataflow library work correctly. + hasOperand(this, call, indirectionIndex, _) + or + hasInstruction(this, call, indirectionIndex, _) + } + + CallInstruction getCallInstruction() { result = call } + + int getIndirectionIndex() { result = indirectionIndex } + + /** Gets the operand associated with this node, if any. */ + Operand getOperand() { hasOperand(this, call, indirectionIndex, result) } + + /** Gets the instruction associated with this node, if any. */ + Instruction getInstruction() { hasInstruction(this, call, indirectionIndex, result) } +} + +/** + * An `IndirectReturnOutNode` which is used as a destination of a store operation. + * When it's used for a store operation it's useful to have this be a `PostUpdateNode` for + * the shared dataflow library's flow-through mechanism to detect flow in cases such as: + * ```cpp + * struct MyInt { + * int i; + * int& getRef() { return i; } + * }; + * ... + * MyInt mi; + * mi.getRef() = source(); // this is detected as a store to `i` via flow-through. + * sink(mi.i); + * ``` + */ +private class PostIndirectReturnOutNode extends IndirectReturnOutNode, PostUpdateNode { + PostIndirectReturnOutNode() { + any(StoreInstruction store).getDestinationAddressOperand() = this.getOperand() + } + + override Node getPreUpdateNode() { result = this } +} + +/** + * INTERNAL: Do not use. + * + * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. + */ +private Type getTypeImpl0(Type t, int indirectionIndex) { + indirectionIndex = 0 and + result = t + or + indirectionIndex > 0 and + exists(Type stripped | + stripped = stripPointer(t.stripTopLevelSpecifiers()) and + // We need to avoid the case where `stripPointer(t) = t` (which can happen on + // iterators that specify a `value_type` that is the iterator itself). Such a type + // would create an infinite loop otherwise. For these cases we simply don't produce + // a result for `getTypeImpl`. + stripped.getUnspecifiedType() != t.getUnspecifiedType() and + result = getTypeImpl0(stripped, indirectionIndex - 1) + ) +} + +/** + * INTERNAL: Do not use. + * + * Returns `t`, but stripped of the outer-most `indirectionIndex` number of indirections. + * + * If `indirectionIndex` cannot be stripped off `t`, an `UnknownType` is returned. + */ +bindingset[indirectionIndex] +Type getTypeImpl(Type t, int indirectionIndex) { + result = getTypeImpl0(t, indirectionIndex) + or + // If we cannot produce the right type we return an error type. + // This can sometimes happen when we don't know the real + // type of a void pointer. + not exists(getTypeImpl0(t, indirectionIndex)) and + result instanceof UnknownType +} + +/** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an operand in the IR + * after `index` number of loads. + */ +class RawIndirectOperand extends Node, TRawIndirectOperand { + Operand operand; + int indirectionIndex; + + RawIndirectOperand() { this = TRawIndirectOperand(operand, indirectionIndex) } + + /** Gets the underlying instruction. */ + Operand getOperand() { result = operand } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { result = this.getOperand().getDef().getEnclosingFunction() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override DataFlowType getType() { + exists(int sub, DataFlowType type, boolean isGLValue | + type = getOperandType(operand, isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getOperand().getLocation()) + then result = this.getOperand().getLocation() + else result instanceof UnknownDefaultLocation + } + + override string toStringImpl() { + result = instructionNode(this.getOperand().getDef()).toStringImpl() + " indirection" + } +} + +/** + * INTERNAL: do not use. + * + * A node representing the value of an update parameter + * just before reaching the end of a function. + */ +class FinalParameterNode extends Node, TFinalParameterNode { + Parameter p; + int indirectionIndex; + + FinalParameterNode() { this = TFinalParameterNode(p, indirectionIndex) } + + /** Gets the parameter associated with this final use. */ + Parameter getParameter() { result = p } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + /** Gets the argument index associated with this final use. */ + final int getArgumentIndex() { result = p.getIndex() } + + override Declaration getFunction() { result = p.getFunction() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override DataFlowType getType() { result = getTypeImpl(p.getUnspecifiedType(), indirectionIndex) } + + final override Location getLocationImpl() { + // Parameters can have multiple locations. When there's a unique location we use + // that one, but if multiple locations exist we default to an unknown location. + result = unique( | | p.getLocation()) + or + not exists(unique( | | p.getLocation())) and + result instanceof UnknownDefaultLocation + } + + override string toStringImpl() { + if indirectionIndex > 1 then result = p.toString() + " indirection" else result = p.toString() + } +} + +/** + * The value of an uninitialized local variable, viewed as a node in a data + * flow graph. + */ +class UninitializedNode extends Node { + LocalVariable v; + + UninitializedNode() { + exists(Ssa::Def def | + def.getIndirectionIndex() = 0 and + def.getValue().asInstruction() instanceof UninitializedInstruction and + Ssa::nodeToDefOrUse(this, def, _) and + v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst() + ) + } + + /** Gets the uninitialized local variable corresponding to this node. */ + LocalVariable getLocalVariable() { result = v } +} + +/** + * INTERNAL: Do not use. + * + * A node that represents the indirect value of an instruction in the IR + * after `index` number of loads. + */ +class RawIndirectInstruction extends Node, TRawIndirectInstruction { + Instruction instr; + int indirectionIndex; + + RawIndirectInstruction() { this = TRawIndirectInstruction(instr, indirectionIndex) } + + /** Gets the underlying instruction. */ + Instruction getInstruction() { result = instr } + + /** Gets the underlying indirection index. */ + int getIndirectionIndex() { result = indirectionIndex } + + override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } + + override Declaration getEnclosingCallable() { result = this.getFunction() } + + override DataFlowType getType() { + exists(int sub, DataFlowType type, boolean isGLValue | + type = getInstructionType(instr, isGLValue) and + if isGLValue = true then sub = 1 else sub = 0 + | + result = getTypeImpl(type.getUnspecifiedType(), indirectionIndex - sub) + ) + } + + final override Location getLocationImpl() { + if exists(this.getInstruction().getLocation()) + then result = this.getInstruction().getLocation() + else result instanceof UnknownDefaultLocation + } + + override string toStringImpl() { + result = instructionNode(this.getInstruction()).toStringImpl() + " indirection" + } +} + +/** Holds if `node` is an `OperandNode` that should map `node.asExpr()` to `e`. */ +predicate exprNodeShouldBeOperand(OperandNode node, Expr e) { + exists(Instruction def | + unique( | | getAUse(def)) = node.getOperand() and + e = def.getConvertedResultExpression() + ) +} + +private predicate indirectExprNodeShouldBeIndirectOperand0( + VariableAddressInstruction instr, RawIndirectOperand node, Expr e +) { + instr = node.getOperand().getDef() and + e = instr.getAst().(Expr).getUnconverted() +} + +/** Holds if `node` should be an `IndirectOperand` that maps `node.asIndirectExpr()` to `e`. */ +private predicate indirectExprNodeShouldBeIndirectOperand(RawIndirectOperand node, Expr e) { + exists(Instruction instr | instr = node.getOperand().getDef() | + exists(Expr e0 | + indirectExprNodeShouldBeIndirectOperand0(instr, node, e0) and + e = e0.getFullyConverted() + ) + or + not indirectExprNodeShouldBeIndirectOperand0(_, node, _) and + e = instr.getConvertedResultExpression() + ) +} + +private predicate exprNodeShouldBeIndirectOutNode(IndirectArgumentOutNode node, Expr e) { + exists(CallInstruction call | + call.getStaticCallTarget() instanceof Constructor and + e = call.getConvertedResultExpression() and + call.getThisArgumentOperand() = node.getAddressOperand() + ) +} + +/** Holds if `node` should be an instruction node that maps `node.asExpr()` to `e`. */ +predicate exprNodeShouldBeInstruction(Node node, Expr e) { + not exprNodeShouldBeOperand(_, e) and + not exprNodeShouldBeIndirectOutNode(_, e) and + ( + e = node.asInstruction().getConvertedResultExpression() + or + // The instruction that contains the result of an `AssignOperation` is + // the unloaded left operand (see the comments in `TranslatedAssignOperation`). + // That means that for cases like + // ```cpp + // int x = ...; + // x += 1; + // ``` + // the result of `x += 1` is the `VariableAddressInstruction` that represents `x`. But + // that instruction doesn't receive the flow from this `AssignOperation`. So instead we + // map the operation to the `AddInstruction`. + node.asInstruction().getAst() = e.(AssignOperation) + or + // Same story for `CrementOperation`s (cf. the comments in the subclasses + // of `TranslatedCrementOperation`). + node.asInstruction().getAst() = e.(CrementOperation) + ) +} + +/** Holds if `node` should be an `IndirectInstruction` that maps `node.asIndirectExpr()` to `e`. */ +predicate indirectExprNodeShouldBeIndirectInstruction(IndirectInstruction node, Expr e) { + exists(Instruction instr | + instr = node.getInstruction() and not indirectExprNodeShouldBeIndirectOperand(_, e) + | + e = instr.(VariableAddressInstruction).getAst().(Expr).getFullyConverted() + or + not instr instanceof VariableAddressInstruction and + e = instr.getConvertedResultExpression() + ) +} + +abstract private class ExprNodeBase extends Node { + /** + * Gets the expression corresponding to this node, if any. The returned + * expression may be a `Conversion`. + */ + abstract Expr getConvertedExpr(); + + /** Gets the non-conversion expression corresponding to this node, if any. */ + abstract Expr getExpr(); +} + +private class InstructionExprNode extends ExprNodeBase, InstructionNode { + InstructionExprNode() { exprNodeShouldBeInstruction(this, _) } + + final override Expr getConvertedExpr() { exprNodeShouldBeInstruction(this, result) } + + final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() } + + final override string toStringImpl() { result = this.getConvertedExpr().toString() } +} + +private class OperandExprNode extends ExprNodeBase, OperandNode { + OperandExprNode() { exprNodeShouldBeOperand(this, _) } + + final override Expr getConvertedExpr() { exprNodeShouldBeOperand(this, result) } + + final override Expr getExpr() { result = this.getConvertedExpr().getUnconverted() } + + final override string toStringImpl() { result = this.getConvertedExpr().toString() } +} + +abstract private class IndirectExprNodeBase extends Node { + /** + * Gets the expression corresponding to this node, if any. The returned + * expression may be a `Conversion`. + */ + abstract Expr getConvertedExpr(int indirectionIndex); + + /** Gets the non-conversion expression corresponding to this node, if any. */ + abstract Expr getExpr(int indirectionIndex); +} + +private class IndirectOperandIndirectExprNode extends IndirectExprNodeBase, RawIndirectOperand { + IndirectOperandIndirectExprNode() { indirectExprNodeShouldBeIndirectOperand(this, _) } + + final override Expr getConvertedExpr(int index) { + this.getIndirectionIndex() = index and + indirectExprNodeShouldBeIndirectOperand(this, result) + } + + final override Expr getExpr(int index) { + this.getIndirectionIndex() = index and + result = this.getConvertedExpr(index).getUnconverted() + } +} + +private class IndirectInstructionIndirectExprNode extends IndirectExprNodeBase, + RawIndirectInstruction +{ + IndirectInstructionIndirectExprNode() { indirectExprNodeShouldBeIndirectInstruction(this, _) } + + final override Expr getConvertedExpr(int index) { + this.getIndirectionIndex() = index and + indirectExprNodeShouldBeIndirectInstruction(this, result) + } + + final override Expr getExpr(int index) { + this.getIndirectionIndex() = index and + result = this.getConvertedExpr(index).getUnconverted() + } +} + +private class IndirectArgumentOutExprNode extends ExprNodeBase, IndirectArgumentOutNode { + IndirectArgumentOutExprNode() { exprNodeShouldBeIndirectOutNode(this, _) } + + final override Expr getConvertedExpr() { exprNodeShouldBeIndirectOutNode(this, result) } + + final override Expr getExpr() { result = this.getConvertedExpr() } } /** * An expression, viewed as a node in a data flow graph. */ -class ExprNode extends InstructionNode { - ExprNode() { exists(instr.getConvertedResultExpression()) } - +class ExprNode extends Node instanceof ExprNodeBase { /** * Gets the non-conversion expression corresponding to this node, if any. If * this node strictly (in the sense of `getConvertedExpr`) corresponds to a * `Conversion`, then the result is that `Conversion`'s non-`Conversion` base * expression. */ - Expr getExpr() { result = instr.getUnconvertedResultExpression() } + Expr getExpr() { result = super.getExpr() } /** * Gets the expression corresponding to this node, if any. The returned * expression may be a `Conversion`. */ - Expr getConvertedExpr() { result = instr.getConvertedResultExpression() } + Expr getConvertedExpr() { result = super.getConvertedExpr() } +} - override string toString() { result = this.asConvertedExpr().toString() } +/** + * An indirect expression, viewed as a node in a data flow graph. + */ +class IndirectExprNode extends Node instanceof IndirectExprNodeBase { + /** + * Gets the non-conversion expression corresponding to this node, if any. If + * this node strictly (in the sense of `getConvertedExpr`) corresponds to a + * `Conversion`, then the result is that `Conversion`'s non-`Conversion` base + * expression. + */ + Expr getExpr(int indirectionIndex) { result = super.getExpr(indirectionIndex) } + + /** + * Gets the expression corresponding to this node, if any. The returned + * expression may be a `Conversion`. + */ + Expr getConvertedExpr(int indirectionIndex) { result = super.getConvertedExpr(indirectionIndex) } } /** @@ -491,12 +1212,12 @@ class ExprNode extends InstructionNode { * `ExplicitParameterNode`, `ThisParameterNode`, or * `ParameterIndirectionNode`. */ -class ParameterNode extends InstructionNode { +class ParameterNode extends Node { ParameterNode() { // To avoid making this class abstract, we enumerate its values here - instr instanceof InitializeParameterInstruction + this.asInstruction() instanceof InitializeParameterInstruction or - instr instanceof InitializeIndirectionInstruction + this instanceof IndirectParameterNode } /** @@ -507,10 +1228,20 @@ class ParameterNode extends InstructionNode { predicate isParameterOf(Function f, ParameterPosition pos) { none() } // overridden by subclasses } -/** An explicit positional parameter, not including `this` or `...`. */ -private class ExplicitParameterNode extends ParameterNode { +/** An explicit positional parameter, including `this`, but not `...`. */ +class DirectParameterNode extends InstructionNode { override InitializeParameterInstruction instr; + /** + * INTERNAL: Do not use. + * + * Gets the `IRVariable` that this parameter references. + */ + IRVariable getIRVariable() { result = instr.getIRVariable() } +} + +/** An explicit positional parameter, not including `this` or `...`. */ +private class ExplicitParameterNode extends ParameterNode, DirectParameterNode { ExplicitParameterNode() { exists(instr.getParameter()) } override predicate isParameterOf(Function f, ParameterPosition pos) { @@ -520,36 +1251,45 @@ private class ExplicitParameterNode extends ParameterNode { /** Gets the `Parameter` associated with this node. */ Parameter getParameter() { result = instr.getParameter() } - override string toString() { result = instr.getParameter().toString() } + override string toStringImpl() { result = instr.getParameter().toString() } } /** An implicit `this` parameter. */ -class ThisParameterNode extends ParameterNode { - override InitializeParameterInstruction instr; - +class ThisParameterNode extends ParameterNode, DirectParameterNode { ThisParameterNode() { instr.getIRVariable() instanceof IRThisVariable } override predicate isParameterOf(Function f, ParameterPosition pos) { pos.(DirectPosition).getIndex() = -1 and instr.getEnclosingFunction() = f } - override string toString() { result = "this" } + override string toStringImpl() { result = "this" } +} + +pragma[noinline] +private predicate indirectPositionHasArgumentIndexAndIndex( + IndirectionPosition pos, int argumentIndex, int indirectionIndex +) { + pos.getArgumentIndex() = argumentIndex and + pos.getIndirectionIndex() = indirectionIndex +} + +pragma[noinline] +private predicate indirectParameterNodeHasArgumentIndexAndIndex( + IndirectParameterNode node, int argumentIndex, int indirectionIndex +) { + node.getArgumentIndex() = argumentIndex and + node.getIndirectionIndex() = indirectionIndex } /** A synthetic parameter to model the pointed-to object of a pointer parameter. */ -class ParameterIndirectionNode extends ParameterNode { - override InitializeIndirectionInstruction instr; - +class ParameterIndirectionNode extends ParameterNode instanceof IndirectParameterNode { override predicate isParameterOf(Function f, ParameterPosition pos) { - exists(int index | - instr.getEnclosingFunction() = f and - instr.hasIndex(index) - | - pos.(IndirectionPosition).getIndex() = index + IndirectParameterNode.super.getEnclosingCallable() = f and + exists(int argumentIndex, int indirectionIndex | + indirectPositionHasArgumentIndexAndIndex(pos, argumentIndex, indirectionIndex) and + indirectParameterNodeHasArgumentIndexAndIndex(this, argumentIndex, indirectionIndex) ) } - - override string toString() { result = "*" + instr.getIRVariable().toString() } } /** @@ -570,7 +1310,7 @@ abstract class PostUpdateNode extends Node { */ abstract Node getPreUpdateNode(); - override string toString() { result = this.getPreUpdateNode() + " [post update]" } + final override DataFlowType getType() { result = this.getPreUpdateNode().getType() } } /** @@ -590,36 +1330,6 @@ abstract private class PartialDefinitionNode extends PostUpdateNode { abstract Expr getDefinedExpr(); } -private class FieldPartialDefinitionNode extends PartialDefinitionNode, StoreNodeInstr { - FieldPartialDefinitionNode() { - this.getInstruction() = any(FieldAddressInstruction fai).getObjectAddress() - } - - override Node getPreUpdateNode() { result.asInstruction() = this.getInstruction() } - - override Expr getDefinedExpr() { result = this.getInstruction().getUnconvertedResultExpression() } - - override string toString() { result = PartialDefinitionNode.super.toString() } -} - -private class NonPartialDefinitionPostUpdate extends PostUpdateNode, StoreNodeInstr { - NonPartialDefinitionPostUpdate() { not this instanceof PartialDefinitionNode } - - override Node getPreUpdateNode() { result.asInstruction() = this.getInstruction() } - - override string toString() { result = PostUpdateNode.super.toString() } -} - -private class ArgumentPostUpdateNode extends PartialDefinitionNode, StoreNodeOperand { - override ArgumentNode getPreUpdateNode() { result.asOperand() = operand } - - override Expr getDefinedExpr() { - result = this.getOperand().getDef().getUnconvertedResultExpression() - } - - override string toString() { result = PartialDefinitionNode.super.toString() } -} - /** * A node that represents the value of a variable after a function call that * may have changed the variable because it's passed by reference. @@ -630,33 +1340,13 @@ private class ArgumentPostUpdateNode extends PartialDefinitionNode, StoreNodeOpe * returned. This node will have its `getArgument()` equal to `&x` and its * `getVariableAccess()` equal to `x`. */ -class DefinitionByReferenceNode extends InstructionNode { - override WriteSideEffectInstruction instr; - +class DefinitionByReferenceNode extends IndirectArgumentOutNode { /** Gets the unconverted argument corresponding to this node. */ - Expr getArgument() { - result = - instr - .getPrimaryInstruction() - .(CallInstruction) - .getArgument(instr.getIndex()) - .getUnconvertedResultExpression() - } + Expr getArgument() { result = this.getAddressOperand().getDef().getUnconvertedResultExpression() } /** Gets the parameter through which this value is assigned. */ Parameter getParameter() { - exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex())) - } - - override string toString() { - // This string should be unique enough to be helpful but common enough to - // avoid storing too many different strings. - result = - instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget().getName() + - " output argument" - or - not exists(instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget()) and - result = "output argument" + result = this.getCallInstruction().getStaticCallTarget().getParameter(this.getArgumentIndex()) } } @@ -667,12 +1357,16 @@ class DefinitionByReferenceNode extends InstructionNode { */ class VariableNode extends Node, TVariableNode { Variable v; + int indirectionIndex; - VariableNode() { this = TVariableNode(v) } + VariableNode() { this = TVariableNode(v, indirectionIndex) } /** Gets the variable corresponding to this node. */ Variable getVariable() { result = v } + /** Gets the indirection index of this node. */ + int getIndirectionIndex() { result = indirectionIndex } + override Declaration getFunction() { none() } override Declaration getEnclosingCallable() { @@ -684,11 +1378,23 @@ class VariableNode extends Node, TVariableNode { result = v } - override IRType getType() { result.getCanonicalLanguageType().hasUnspecifiedType(v.getType(), _) } + override DataFlowType getType() { + result = getTypeImpl(v.getUnspecifiedType(), indirectionIndex - 1) + } - override Location getLocation() { result = v.getLocation() } + final override Location getLocationImpl() { + // Certain variables (such as parameters) can have multiple locations. + // When there's a unique location we use that one, but if multiple locations + // exist we default to an unknown location. + result = unique( | | v.getLocation()) + or + not exists(unique( | | v.getLocation())) and + result instanceof UnknownDefaultLocation + } - override string toString() { result = v.toString() } + override string toStringImpl() { + if indirectionIndex = 1 then result = v.toString() else result = v.toString() + " indirection" + } } /** @@ -731,7 +1437,9 @@ DefinitionByReferenceNode definitionByReferenceNodeFromArgument(Expr argument) { } /** Gets the `VariableNode` corresponding to the variable `v`. */ -VariableNode variableNode(Variable v) { result.getVariable() = v } +VariableNode variableNode(Variable v) { + result.getVariable() = v and result.getIndirectionIndex() = 1 +} /** * DEPRECATED: See UninitializedNode. @@ -741,260 +1449,150 @@ VariableNode variableNode(Variable v) { result.getVariable() = v } */ Node uninitializedNode(LocalVariable v) { none() } -/** - * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local - * (intra-procedural) step. - */ -predicate localFlowStep = localFlowStepCached/2; - -/** - * INTERNAL: do not use. - * - * This is the local flow predicate that's used as a building block in global - * data flow. It may have less flow than the `localFlowStep` predicate. - */ -predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { - // Operand -> Instruction flow - simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) - or - // Instruction -> Operand flow - simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand()) - or - // Flow into, through, and out of store nodes - StoreNodeFlow::flowInto(nodeFrom.asInstruction(), nodeTo) - or - StoreNodeFlow::flowThrough(nodeFrom, nodeTo) - or - StoreNodeFlow::flowOutOf(nodeFrom, nodeTo) - or - // Flow into, through, and out of read nodes - ReadNodeFlow::flowInto(nodeFrom, nodeTo) - or - ReadNodeFlow::flowThrough(nodeFrom, nodeTo) - or - ReadNodeFlow::flowOutOf(nodeFrom, nodeTo) - or - // Adjacent-def-use and adjacent-use-use flow - adjacentDefUseFlow(nodeFrom, nodeTo) +pragma[noinline] +predicate hasOperandAndIndex(IndirectOperand indirectOperand, Operand operand, int indirectionIndex) { + indirectOperand.getOperand() = operand and + indirectOperand.getIndirectionIndex() = indirectionIndex } -private predicate adjacentDefUseFlow(Node nodeFrom, Node nodeTo) { - // Flow that isn't already covered by field flow out of store/read nodes. - not nodeFrom.asInstruction() = any(StoreNode pun).getStoreInstruction() and - not nodeFrom.asInstruction() = any(ReadNode pun).getALoadInstruction() and - ( - //Def-use flow +pragma[noinline] +predicate hasInstructionAndIndex( + IndirectInstruction indirectInstr, Instruction instr, int indirectionIndex +) { + indirectInstr.getInstruction() = instr and + indirectInstr.getIndirectionIndex() = indirectionIndex +} + +cached +private module Cached { + /** + * Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local + * (intra-procedural) step. + */ + cached + predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) } + + private predicate indirectionOperandFlow(RawIndirectOperand nodeFrom, Node nodeTo) { + // Reduce the indirection count by 1 if we're passing through a `LoadInstruction`. + exists(int ind, LoadInstruction load | + hasOperandAndIndex(nodeFrom, load.getSourceAddressOperand(), ind) and + nodeHasInstruction(nodeTo, load, ind - 1) + ) + or + // If an operand flows to an instruction, then the indirection of + // the operand also flows to the indirection of the instruction. + exists(Operand operand, Instruction instr, int indirectionIndex | + simpleInstructionLocalFlowStep(operand, instr) and + hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex)) + ) + or + // If there's indirect flow to an operand, then there's also indirect + // flow to the operand after applying some pointer arithmetic. + exists(PointerArithmeticInstruction pointerArith, int indirectionIndex | + hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), + pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex)) + ) + } + + private predicate indirectionInstructionFlow( + RawIndirectInstruction nodeFrom, IndirectOperand nodeTo + ) { + // If there's flow from an instruction to an operand, then there's also flow from the + // indirect instruction to the indirect operand. + exists(Operand operand, Instruction instr, int indirectionIndex | + simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand)) + | + hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex)) + ) + } + + /** + * INTERNAL: do not use. + * + * This is the local flow predicate that's used as a building block in global + * data flow. It may have less flow than the `localFlowStep` predicate. + */ + cached + predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { + // Post update node -> Node flow + Ssa::ssaFlow(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo) + or + // Def-use/Use-use flow Ssa::ssaFlow(nodeFrom, nodeTo) or - // Use-use flow through stores. - exists(Instruction loadAddress, Node store | - loadAddress = Ssa::getSourceAddressFromNode(nodeFrom) and - Ssa::explicitWrite(_, store.asInstruction(), loadAddress) and - Ssa::ssaFlow(store, nodeTo) - ) - ) -} - -/** - * INTERNAL: Do not use. - */ -module ReadNodeFlow { - /** Holds if the read node `nodeTo` should receive flow from `nodeFrom`. */ - predicate flowInto(Node nodeFrom, ReadNode nodeTo) { - nodeTo.isInitial() and - ( - // If we entered through an address operand. - nodeFrom.asOperand().getDef() = nodeTo.getInstruction() - or - // If we entered flow through a memory-producing instruction. - // This can happen if we have flow to an `InitializeParameterIndirection` through - // a `ReadSideEffectInstruction`. - exists(Instruction load, Instruction def | - def = nodeFrom.asInstruction() and - def = Ssa::getSourceValueOperand(load).getAnyDef() and - not def = any(StoreNode store).getStoreInstruction() and - pragma[only_bind_into](nodeTo).getALoadInstruction() = load - ) - ) - } - - /** - * Holds if the read node `nodeTo` should receive flow from the read node `nodeFrom`. - * - * This happens when `readFrom` is _not_ the source of a `readStep`, and `nodeTo` is - * the `ReadNode` that represents an address that directly depends on `nodeFrom`. - */ - predicate flowThrough(ReadNode nodeFrom, ReadNode nodeTo) { - not readStep(nodeFrom, _, _) and - nodeFrom.getOuter() = nodeTo - } - - /** - * Holds if flow should leave the read node `nFrom` and enter the node `nodeTo`. - * This happens either because there is use-use flow from one of the variables used in - * the read operation, or because we have traversed all the field dereferences in the - * read operation. - */ - predicate flowOutOf(ReadNode nFrom, Node nodeTo) { - // Use-use flow to another use of the same variable instruction - Ssa::ssaFlow(nFrom, nodeTo) + // Operand -> Instruction flow + simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction()) or - not exists(nFrom.getInner()) and - exists(Node store | - Ssa::explicitWrite(_, store.asInstruction(), nFrom.getInstruction()) and - Ssa::ssaFlow(store, nodeTo) + // Instruction -> Operand flow + exists(Instruction iFrom, Operand opTo | + iFrom = nodeFrom.asInstruction() and opTo = nodeTo.asOperand() + | + simpleOperandLocalFlowStep(iFrom, opTo) and + // Omit when the instruction node also represents the operand. + not iFrom = Ssa::getIRRepresentationOfOperand(opTo) ) or - // Flow out of read nodes and into memory instructions if we cannot move any further through - // read nodes. - nFrom.isTerminal() and - ( - exists(Instruction load | - load = nodeTo.asInstruction() and - Ssa::getSourceAddress(load) = nFrom.getInstruction() + // Phi node -> Node flow + Ssa::fromPhiNode(nodeFrom, nodeTo) + or + // Indirect operand -> (indirect) instruction flow + indirectionOperandFlow(nodeFrom, nodeTo) + or + // Indirect instruction -> indirect operand flow + indirectionInstructionFlow(nodeFrom, nodeTo) + or + // Flow through modeled functions + modelFlow(nodeFrom, nodeTo) + or + // Reverse flow: data that flows from the definition node back into the indirection returned + // by a function. This allows data to flow 'in' through references returned by a modeled + // function such as `operator[]`. + exists(Operand address, int indirectionIndex | + nodeHasOperand(nodeTo.(IndirectReturnOutNode), address, indirectionIndex) + | + exists(StoreInstruction store | + nodeHasInstruction(nodeFrom, store, indirectionIndex - 1) and + store.getDestinationAddressOperand() = address ) or - exists(CallInstruction call, int i | - call.getArgument(i) = nodeTo.asInstruction() and - call.getArgument(i) = nFrom.getInstruction() + Ssa::outNodeHasAddressAndIndex(nodeFrom, address, indirectionIndex) + ) + } + + private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) { + // Treat all conversions as flow, even conversions between different numeric types. + conversionFlow(opFrom, iTo, false, _) + or + iTo.(CopyInstruction).getSourceValueOperand() = opFrom + } + + private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) { + not opTo instanceof MemoryOperand and + opTo.getDef() = iFrom + } + + private predicate modelFlow(Node nodeFrom, Node nodeTo) { + exists( + CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut + | + call.getStaticCallTarget() = func and + func.hasDataFlow(modelIn, modelOut) + | + nodeFrom = callInput(call, modelIn) and + nodeTo = callOutput(call, modelOut) + or + exists(int d | + nodeFrom = callInput(call, modelIn, d) and + nodeTo = callOutput(call, modelOut, d) ) ) } } -/** - * INTERNAL: Do not use. - */ -module StoreNodeFlow { - /** Holds if the store node `nodeTo` should receive flow from `nodeFrom`. */ - predicate flowInto(Instruction instrFrom, StoreNode nodeTo) { - nodeTo.flowInto(Ssa::getDestinationAddress(instrFrom)) - } - - /** - * Holds if the store node `nodeTo` should receive flow from `nodeFom`. - * - * This happens when `nodeFrom` is _not_ the source of a `storeStep`, and `nodeFrom` is - * the `Storenode` that represents an address that directly depends on `nodeTo`. - */ - predicate flowThrough(StoreNode nodeFrom, StoreNode nodeTo) { - // Flow through a post update node that doesn't need a store step. - not storeStep(nodeFrom, _, _) and - nodeTo.getOuter() = nodeFrom - } - - /** - * Holds if flow should leave the store node `nodeFrom` and enter the node `nodeTo`. - * This happens because we have traversed an entire chain of field dereferences - * after a store operation. - */ - predicate flowOutOf(StoreNodeInstr nFrom, Node nodeTo) { - nFrom.isTerminal() and - Ssa::ssaFlow(nFrom, nodeTo) - } -} - -private predicate simpleOperandLocalFlowStep(Instruction iFrom, Operand opTo) { - // Propagate flow from an instruction to its exact uses. - // We do this for all instruction/operand pairs, except when the operand is the - // side effect operand of a ReturnIndirectionInstruction, or the load operand of a LoadInstruction. - // This is because we get these flows through the shared SSA library already, and including this - // flow here will create multiple dataflow paths which creates a blowup in stage 3 of dataflow. - ( - not any(ReturnIndirectionInstruction ret).getSideEffectOperand() = opTo and - not any(LoadInstruction load).getSourceValueOperand() = opTo and - not any(ReturnValueInstruction ret).getReturnValueOperand() = opTo - ) and - opTo.getDef() = iFrom -} - -pragma[noinline] -private predicate getAddressType(LoadInstruction load, Type t) { - exists(Instruction address | - address = load.getSourceAddress() and - t = address.getResultType() - ) -} - -/** - * Like the AST dataflow library, we want to conflate the address and value of a reference. This class - * represents the `LoadInstruction` that is generated from a reference dereference. - */ -private class ReferenceDereferenceInstruction extends LoadInstruction { - ReferenceDereferenceInstruction() { - exists(ReferenceType ref | - getAddressType(this, ref) and - this.getResultType() = ref.getBaseType() - ) - } -} - -private predicate simpleInstructionLocalFlowStep(Operand opFrom, Instruction iTo) { - iTo.(CopyInstruction).getSourceValueOperand() = opFrom - or - iTo.(PhiInstruction).getAnInputOperand() = opFrom - or - // Treat all conversions as flow, even conversions between different numeric types. - iTo.(ConvertInstruction).getUnaryOperand() = opFrom - or - iTo.(CheckedConvertOrNullInstruction).getUnaryOperand() = opFrom - or - iTo.(InheritanceConversionInstruction).getUnaryOperand() = opFrom - or - // Conflate references and values like in AST dataflow. - iTo.(ReferenceDereferenceInstruction).getSourceAddressOperand() = opFrom - or - // Flow through modeled functions - modelFlow(opFrom, iTo) -} - -private predicate modelFlow(Operand opFrom, Instruction iTo) { - exists( - CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut - | - call.getStaticCallTarget() = func and - func.hasDataFlow(modelIn, modelOut) - | - ( - modelOut.isReturnValue() and - iTo = call - or - // TODO: Add write side effects for return values - modelOut.isReturnValueDeref() and - iTo = call - or - exists(int index, WriteSideEffectInstruction outNode | - modelOut.isParameterDerefOrQualifierObject(index) and - iTo = outNode and - outNode = getSideEffectFor(call, index) - ) - ) and - ( - exists(int index | - modelIn.isParameterOrQualifierAddress(index) and - opFrom = call.getArgumentOperand(index) - ) - or - exists(int index, ReadSideEffectInstruction read | - modelIn.isParameterDerefOrQualifierObject(index) and - read = getSideEffectFor(call, index) and - opFrom = read.getSideEffectOperand() - ) - ) - ) -} - -/** - * Holds if the result is a side effect for instruction `call` on argument - * index `argument`. This helper predicate makes it easy to join on both of - * these columns at once, avoiding pathological join orders in case the - * argument index should get joined first. - */ -pragma[noinline] -SideEffectInstruction getSideEffectFor(CallInstruction call, int argument) { - call = result.getPrimaryInstruction() and - argument = result.(IndexedInstruction).getIndex() -} +import Cached /** * Holds if data flows from `source` to `sink` in zero or more local @@ -1012,21 +1610,170 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) { localFlow(instructionNode(e1), instructionNode(e2)) } +cached +private module ExprFlowCached { + /** + * Holds if `n` is an indirect operand of a `PointerArithmeticInstruction`, and + * `e` is the result of loading from the `PointerArithmeticInstruction`. + */ + private predicate isIndirectBaseOfArrayAccess(IndirectOperand n, Expr e) { + exists(LoadInstruction load, PointerArithmeticInstruction pai | + pai = load.getSourceAddress() and + pai.getLeftOperand() = n.getOperand() and + n.getIndirectionIndex() = 1 and + e = load.getConvertedResultExpression() + ) + } + + /** + * Gets the expression associated with node `n`, if any. + * + * Unlike `n.asExpr()`, this predicate will also get the + * expression `*(x + i)` when `n` is the indirect node + * for `x`. This ensures that an assignment in a long chain + * of assignments in a macro expansion is properly mapped + * to the previous assignment. For example, in: + * ```cpp + * *x = source(); + * use(x[0]); + * use(x[1]); + * ... + * use(x[i]); + * use(x[i+1]); + * ... + * use(x[N]); + * ``` + * To see what the problem would be if `asExpr(n)` was replaced + * with `n.asExpr()`, consider the transitive closure over + * `localStepFromNonExpr` in `localStepsToExpr`. We start at `n2` + * for which `n.asExpr()` exists. For example, `n2` in the above + * example could be a `x[i]` in any of the `use(x[i])` above. + * + * We then step to a dataflow predecessor of `n2`. In the above + * code fragment, thats the indirect node corresponding to `x` in + * `x[i-1]`. Since this doesn't have a result for `Node::asExpr()` + * we continue with the recursion until we reach `*x = source()` + * which does have a result for `Node::asExpr()`. + * + * If `N` is very large this blows up. + * + * To fix this, we map the indirect node corresponding to `x` to + * in `x[i - 1]` to the `x[i - 1]` expression. This ensures that + * `x[i]` steps to the expression `x[i - 1]` without traversing the + * entire chain. + */ + private Expr asExpr(Node n) { + isIndirectBaseOfArrayAccess(n, result) + or + not isIndirectBaseOfArrayAccess(n, _) and + result = n.asExpr() + } + + /** + * Holds if `asExpr(n1)` doesn't have a result and `n1` flows to `n2` in a single + * dataflow step. + */ + private predicate localStepFromNonExpr(Node n1, Node n2) { + not exists(asExpr(n1)) and + localFlowStep(n1, n2) + } + + /** + * Holds if `asExpr(n1)` doesn't have a result, `asExpr(n2) = e2` and + * `n2` is the first node reachable from `n1` such that `asExpr(n2)` exists. + */ + pragma[nomagic] + private predicate localStepsToExpr(Node n1, Node n2, Expr e2) { + localStepFromNonExpr*(n1, n2) and + e2 = asExpr(n2) + } + + /** + * Holds if `asExpr(n1) = e1` and `asExpr(n2) = e2` and `n2` is the first node + * reachable from `n1` such that `asExpr(n2)` exists. + */ + private predicate localExprFlowSingleExprStep(Node n1, Expr e1, Node n2, Expr e2) { + exists(Node mid | + localFlowStep(n1, mid) and + localStepsToExpr(mid, n2, e2) and + e1 = asExpr(n1) + ) + } + + /** + * Holds if `asExpr(n1) = e1` and `e1 != e2` and `n2` is the first reachable node from + * `n1` such that `asExpr(n2) = e2`. + */ + private predicate localExprFlowStepImpl(Node n1, Expr e1, Node n2, Expr e2) { + exists(Node n, Expr e | localExprFlowSingleExprStep(n1, e1, n, e) | + // If `n.asExpr()` and `n1.asExpr()` both resolve to the same node (which can + // happen if `n2` is the node attached to a conversion of `e1`), then we recursively + // perform another expression step. + if e1 = e + then localExprFlowStepImpl(n, e, n2, e2) + else ( + // If we manage to step to a different expression we're done. + e2 = e and + n2 = n + ) + ) + } + + /** Holds if data can flow from `e1` to `e2` in one local (intra-procedural) step. */ + cached + predicate localExprFlowStep(Expr e1, Expr e2) { localExprFlowStepImpl(_, e1, _, e2) } +} + +import ExprFlowCached + +/** + * Holds if data can flow from `e1` to `e2` in one or more + * local (intra-procedural) steps. + */ +pragma[inline] +private predicate localExprFlowPlus(Expr e1, Expr e2) = fastTC(localExprFlowStep/2)(e1, e2) + /** * Holds if data can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. */ pragma[inline] -predicate localExprFlow(Expr e1, Expr e2) { localFlow(exprNode(e1), exprNode(e2)) } +predicate localExprFlow(Expr e1, Expr e2) { + e1 = e2 + or + localExprFlowPlus(e1, e2) +} +bindingset[f] +pragma[inline_late] +private int getFieldSize(Field f) { result = f.getType().getSize() } + +/** + * Gets a field in the union `u` whose size + * is `bytes` number of bytes. + */ +private Field getAFieldWithSize(Union u, int bytes) { + result = u.getAField() and + bytes = getFieldSize(result) +} + +cached private newtype TContent = - TFieldContent(Field f) { - // As reads and writes to union fields can create flow even though the reads and writes - // target different fields, we don't want a read (write) to create a read (write) step. + TFieldContent(Field f, int indirectionIndex) { + indirectionIndex = [1 .. Ssa::getMaxIndirectionsForType(f.getUnspecifiedType())] and + // Reads and writes of union fields are tracked using `UnionContent`. not f.getDeclaringType() instanceof Union } or - TCollectionContent() or // Not used in C/C++ - TArrayContent() // Not used in C/C++. + TUnionContent(Union u, int bytes, int indirectionIndex) { + exists(Field f | + f = u.getAField() and + bytes = getFieldSize(f) and + // We key `UnionContent` by the union instead of its fields since a write to one + // field can be read by any read of the union's fields. + indirectionIndex = + [1 .. max(Ssa::getMaxIndirectionsForType(getAFieldWithSize(u, bytes).getUnspecifiedType()))] + ) + } /** * A description of the way data may be stored inside an object. Examples @@ -1042,25 +1789,52 @@ class Content extends TContent { } } -/** A reference through an instance field. */ +/** A reference through a non-union instance field. */ class FieldContent extends Content, TFieldContent { Field f; + int indirectionIndex; - FieldContent() { this = TFieldContent(f) } + FieldContent() { this = TFieldContent(f, indirectionIndex) } - override string toString() { result = f.toString() } + override string toString() { + indirectionIndex = 1 and result = f.toString() + or + indirectionIndex > 1 and result = f.toString() + " indirection" + } Field getField() { result = f } + + pragma[inline] + int getIndirectionIndex() { + pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex) + } } -/** A reference through an array. */ -class ArrayContent extends Content, TArrayContent { - override string toString() { result = "[]" } -} +/** A reference through an instance field of a union. */ +class UnionContent extends Content, TUnionContent { + Union u; + int indirectionIndex; + int bytes; -/** A reference through the contents of some collection-like container. */ -private class CollectionContent extends Content, TCollectionContent { - override string toString() { result = "" } + UnionContent() { this = TUnionContent(u, bytes, indirectionIndex) } + + override string toString() { + indirectionIndex = 1 and result = u.toString() + or + indirectionIndex > 1 and result = u.toString() + " indirection" + } + + /** Gets a field of the underlying union of this `UnionContent`, if any. */ + Field getAField() { result = u.getAField() and getFieldSize(result) = bytes } + + /** Gets the underlying union of this `UnionContent`. */ + Union getUnion() { result = u } + + /** Gets the indirection index of this `UnionContent`. */ + pragma[inline] + int getIndirectionIndex() { + pragma[only_bind_into](result) = pragma[only_bind_out](indirectionIndex) + } } /** @@ -1109,10 +1883,11 @@ signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch); module BarrierGuard { /** Gets a node that is safely guarded by the given guard check. */ ExprNode getABarrierNode() { - exists(IRGuardCondition g, ValueNumber value, boolean edge | + exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge | + e = value.getAnInstruction().getConvertedResultExpression() and + result.getConvertedExpr() = e and guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and - result.asInstruction() = value.getAnInstruction() and - g.controls(result.asInstruction().getBlock(), edge) + g.controls(getBasicBlock(result), edge) ) } } @@ -1131,10 +1906,11 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in module InstructionBarrierGuard { /** Gets a node that is safely guarded by the given guard check. */ ExprNode getABarrierNode() { - exists(IRGuardCondition g, ValueNumber value, boolean edge | + exists(IRGuardCondition g, ValueNumber value, boolean edge, Operand use | instructionGuardChecks(g, value.getAnInstruction(), edge) and - result.asInstruction() = value.getAnInstruction() and - g.controls(result.asInstruction().getBlock(), edge) + use = value.getAnInstruction().getAUse() and + result.asOperand() = use and + g.controls(use.getDef().getBlock(), edge) ) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll index d6a43ed2975..e8148e29791 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DefaultTaintTrackingImpl.qll @@ -19,6 +19,7 @@ private import semmle.code.cpp.ir.dataflow.TaintTracking private import semmle.code.cpp.ir.dataflow.TaintTracking2 private import semmle.code.cpp.ir.dataflow.TaintTracking3 private import semmle.code.cpp.ir.dataflow.internal.ModelUtil +private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate /** * A predictable instruction is one where an external user can predict @@ -75,6 +76,20 @@ private DataFlow::Node getNodeForExpr(Expr node) { not argv(node.(VariableAccess).getTarget()) } +private predicate conflatePointerAndPointee(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + // Flow from `op` to `*op`. + exists(Operand operand, int indirectionIndex | + nodeHasOperand(nodeFrom, operand, indirectionIndex) and + nodeHasOperand(nodeTo, operand, indirectionIndex - 1) + ) + or + // Flow from `instr` to `*instr`. + exists(Instruction instr, int indirectionIndex | + nodeHasInstruction(nodeFrom, instr, indirectionIndex) and + nodeHasInstruction(nodeTo, instr, indirectionIndex - 1) + ) +} + private class DefaultTaintTrackingCfg extends TaintTracking::Configuration { DefaultTaintTrackingCfg() { this = "DefaultTaintTrackingCfg" } @@ -85,6 +100,10 @@ private class DefaultTaintTrackingCfg extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { nodeIsBarrier(node) } override predicate isSanitizerIn(DataFlow::Node node) { nodeIsBarrierIn(node) } + + override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { + conflatePointerAndPointee(nodeFrom, nodeTo) + } } private class ToGlobalVarTaintTrackingCfg extends TaintTracking::Configuration { @@ -168,16 +187,18 @@ private predicate hasUpperBoundsCheck(Variable var) { private predicate nodeIsBarrierEqualityCandidate( DataFlow::Node node, Operand access, Variable checkedVar ) { - readsVariable(node.asInstruction(), checkedVar) and - any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true) + exists(Instruction instr | instr = node.asOperand().getDef() | + readsVariable(instr, checkedVar) and + any(IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true) + ) } cached private module Cached { cached predicate nodeIsBarrier(DataFlow::Node node) { - exists(Variable checkedVar | - readsVariable(node.asInstruction(), checkedVar) and + exists(Variable checkedVar, Instruction instr | instr = node.asOperand().getDef() | + readsVariable(instr, checkedVar) and hasUpperBoundsCheck(checkedVar) ) or @@ -284,7 +305,7 @@ private module Cached { cached predicate additionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { exists(CallInstruction call, Function func, FunctionInput modelIn, FunctionOutput modelOut | - n1.asOperand() = callInput(call, modelIn) and + n1 = callInput(call, modelIn) and ( func.(TaintFunction).hasTaintFlow(modelIn, modelOut) or @@ -415,6 +436,8 @@ module TaintedWithPath { } override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { + conflatePointerAndPointee(n1, n2) + or // Steps into and out of global variables exists(TaintTrackingConfiguration cfg | cfg.taintThroughGlobals() | writesVariable(n1.asInstruction(), n2.asVariable().(GlobalOrNamespaceVariable)) @@ -622,6 +645,8 @@ module TaintedWithPath { private predicate isGlobalVariablePathNode(WrapPathNode n) { n.inner().getNode().asVariable() instanceof GlobalOrNamespaceVariable + or + n.inner().getNode().asIndirectVariable() instanceof GlobalOrNamespaceVariable } private predicate edgesWithoutGlobals(PathNode a, PathNode b) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll index c7e61ea2e33..20d1e038b41 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ModelUtil.qll @@ -5,41 +5,89 @@ private import semmle.code.cpp.ir.IR private import semmle.code.cpp.ir.dataflow.DataFlow +private import DataFlowUtil +private import SsaInternals as Ssa /** * Gets the instruction that goes into `input` for `call`. */ -Operand callInput(CallInstruction call, FunctionInput input) { +DataFlow::Node callInput(CallInstruction call, FunctionInput input) { // An argument or qualifier exists(int index | - result = call.getArgumentOperand(index) and + result.asOperand() = call.getArgumentOperand(index) and input.isParameterOrQualifierAddress(index) ) or // A value pointed to by an argument or qualifier - exists(ReadSideEffectInstruction read | - result = read.getSideEffectOperand() and - read.getPrimaryInstruction() = call and - input.isParameterDerefOrQualifierObject(read.getIndex()) + exists(int index, int indirectionIndex | + hasOperandAndIndex(result, call.getArgumentOperand(index), indirectionIndex) and + input.isParameterDerefOrQualifierObject(index, indirectionIndex) + ) + or + exists(int ind | + result = getIndirectReturnOutNode(call, ind) and + input.isReturnValueDeref(ind) ) } /** * Gets the instruction that holds the `output` for `call`. */ -Instruction callOutput(CallInstruction call, FunctionOutput output) { +Node callOutput(CallInstruction call, FunctionOutput output) { // The return value - result = call and + result.asInstruction() = call and output.isReturnValue() or // The side effect of a call on the value pointed to by an argument or qualifier - exists(WriteSideEffectInstruction effect | - result = effect and - effect.getPrimaryInstruction() = call and - output.isParameterDerefOrQualifierObject(effect.getIndex()) + exists(int index, int indirectionIndex | + result.(IndirectArgumentOutNode).getArgumentIndex() = index and + result.(IndirectArgumentOutNode).getIndirectionIndex() = indirectionIndex and + result.(IndirectArgumentOutNode).getCallInstruction() = call and + output.isParameterDerefOrQualifierObject(index, indirectionIndex) ) or - // TODO: modify this when we get return value dereferences - result = call and - output.isReturnValueDeref() + exists(int ind | + result = getIndirectReturnOutNode(call, ind) and + output.isReturnValueDeref(ind) + ) +} + +DataFlow::Node callInput(CallInstruction call, FunctionInput input, int d) { + exists(DataFlow::Node n | n = callInput(call, input) and d > 0 | + // An argument or qualifier + hasOperandAndIndex(result, n.asOperand(), d) + or + exists(Operand operand, int indirectionIndex | + // A value pointed to by an argument or qualifier + hasOperandAndIndex(n, operand, indirectionIndex) and + hasOperandAndIndex(result, operand, indirectionIndex + d) + ) + ) +} + +private IndirectReturnOutNode getIndirectReturnOutNode(CallInstruction call, int d) { + result.getCallInstruction() = call and + result.getIndirectionIndex() = d +} + +/** + * Gets the instruction that holds the `output` for `call`. + */ +bindingset[d] +Node callOutput(CallInstruction call, FunctionOutput output, int d) { + exists(DataFlow::Node n | n = callOutput(call, output) and d > 0 | + // The return value + result = getIndirectReturnOutNode(n.asInstruction(), d) + or + // If there isn't an indirect out node for the call with indirection `d` then + // we conflate this with the underlying `CallInstruction`. + not exists(getIndirectReturnOutNode(call, d)) and + n.asInstruction() = result.asInstruction() + or + // The side effect of a call on the value pointed to by an argument or qualifier + exists(Operand operand, int indirectionIndex | + Ssa::outNodeHasAddressAndIndex(n, operand, indirectionIndex) and + Ssa::outNodeHasAddressAndIndex(result, operand, indirectionIndex + d) + ) + ) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll index a14b2b00651..bbe236311fb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/PrintIRLocalFlow.qll @@ -97,23 +97,23 @@ private string getNodeProperty(DataFlow::Node node, string key) { | kind, ", " ) - or - // Is there partial flow from a source to this node? - // This property will only be emitted if partial flow is enabled by overriding - // `DataFlow::Configuration::explorationLimit()`. - key = "pflow" and - result = - strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist, - int order1, int order2 | - any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and - destNode.getNode() = node and - // Only print flow from a source in the same function. - sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable() - | - nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", " - order by - order1, order2, dist desc - ) + // or + // // Is there partial flow from a source to this node? + // // This property will only be emitted if partial flow is enabled by overriding + // // `DataFlow::Configuration::explorationLimit()`. + // key = "pflow" and + // result = + // strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist, + // int order1, int order2 | + // any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and + // destNode.getNode() = node and + // // Only print flow from a source in the same function. + // sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable() + // | + // nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", " + // order by + // order1, order2, dist desc + // ) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll index 128650803d2..ee958431b69 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll @@ -1,638 +1,796 @@ -private import cpp as Cpp +private import codeql.ssa.Ssa as SsaImplCommon private import semmle.code.cpp.ir.IR private import DataFlowUtil private import DataFlowImplCommon as DataFlowImplCommon private import semmle.code.cpp.models.interfaces.Allocation as Alloc private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow -private import codeql.ssa.Ssa as SsaImplCommon +private import semmle.code.cpp.ir.internal.IRCppLanguage +private import DataFlowPrivate +private import ssa0.SsaInternals as SsaInternals0 +import SsaInternalsCommon private module SourceVariables { + int getMaxIndirectionForIRVariable(IRVariable var) { + exists(Type type, boolean isGLValue | + var.getLanguageType().hasType(type, isGLValue) and + if isGLValue = true + then result = 1 + getMaxIndirectionsForType(type) + else result = getMaxIndirectionsForType(type) + ) + } + + cached private newtype TSourceVariable = - TSourceIRVariable(IRVariable var) or - TSourceIRVariableIndirection(InitializeIndirectionInstruction init) + TSourceIRVariable(BaseIRVariable baseVar, int ind) { + ind = [0 .. getMaxIndirectionForIRVariable(baseVar.getIRVariable())] + } or + TCallVariable(AllocationInstruction call, int ind) { + ind = [0 .. countIndirectionsForCppType(getResultLanguageType(call))] + } abstract class SourceVariable extends TSourceVariable { - IRVariable var; + int ind; + bindingset[ind] + SourceVariable() { any() } + + /** Gets a textual representation of this element. */ abstract string toString(); + + /** + * Gets the number of loads performed on the base source variable + * to reach the value of this source variable. + */ + int getIndirection() { result = ind } + + /** + * Gets the base source variable (i.e., the variable without any + * indirections) of this source variable. + */ + abstract BaseSourceVariable getBaseVariable(); + + /** Holds if this variable is a glvalue. */ + predicate isGLValue() { none() } + + /** + * Gets the type of this source variable. If `isGLValue()` holds, then + * the type of this source variable should be thought of as "pointer + * to `getType()`". + */ + abstract DataFlowType getType(); } class SourceIRVariable extends SourceVariable, TSourceIRVariable { - SourceIRVariable() { this = TSourceIRVariable(var) } + BaseIRVariable var; - IRVariable getIRVariable() { result = var } + SourceIRVariable() { this = TSourceIRVariable(var, ind) } - override string toString() { result = this.getIRVariable().toString() } - } + IRVariable getIRVariable() { result = var.getIRVariable() } - class SourceIRVariableIndirection extends SourceVariable, TSourceIRVariableIndirection { - InitializeIndirectionInstruction init; + override BaseIRVariable getBaseVariable() { result.getIRVariable() = this.getIRVariable() } - SourceIRVariableIndirection() { - this = TSourceIRVariableIndirection(init) and var = init.getIRVariable() + override string toString() { + ind = 0 and + result = this.getIRVariable().toString() + or + ind > 0 and + result = this.getIRVariable().toString() + " indirection" } - IRVariable getUnderlyingIRVariable() { result = var } + override predicate isGLValue() { ind = 0 } - override string toString() { result = "*" + this.getUnderlyingIRVariable().toString() } + override DataFlowType getType() { + if ind = 0 then result = var.getType() else result = getTypeImpl(var.getType(), ind - 1) + } + } + + class CallVariable extends SourceVariable, TCallVariable { + AllocationInstruction call; + + CallVariable() { this = TCallVariable(call, ind) } + + AllocationInstruction getCall() { result = call } + + override BaseCallVariable getBaseVariable() { result.getCallInstruction() = call } + + override string toString() { + ind = 0 and + result = "Call" + or + ind > 0 and + result = "Call indirection" + } + + override DataFlowType getType() { result = getTypeImpl(call.getResultType(), ind) } } } +import SourceVariables + +/** + * Holds if the `(operand, indirectionIndex)` columns should be + * assigned a `RawIndirectOperand` value. + */ +predicate hasRawIndirectOperand(Operand op, int indirectionIndex) { + exists(CppType type, int m | + not ignoreOperand(op) and + type = getLanguageType(op) and + m = countIndirectionsForCppType(type) and + indirectionIndex = [1 .. m] and + not exists(getIRRepresentationOfIndirectOperand(op, indirectionIndex)) + ) +} + +/** + * Holds if the `(instr, indirectionIndex)` columns should be + * assigned a `RawIndirectInstruction` value. + */ +predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) { + exists(CppType type, int m | + not ignoreInstruction(instr) and + type = getResultLanguageType(instr) and + m = countIndirectionsForCppType(type) and + indirectionIndex = [1 .. m] and + not exists(getIRRepresentationOfIndirectInstruction(instr, indirectionIndex)) + ) +} + cached -private newtype TDefOrUse = - TExplicitDef(Instruction store) { explicitWrite(_, store, _) } or - TInitializeParam(Instruction instr) { - instr instanceof InitializeParameterInstruction - or - instr instanceof InitializeIndirectionInstruction +private newtype TDefOrUseImpl = + TDefImpl(Operand address, int indirectionIndex) { + exists(Instruction base | isDef(_, _, address, base, _, indirectionIndex) | + // We only include the definition if the SSA pruning stage + // concluded that the definition is live after the write. + any(SsaInternals0::Def def).getAddressOperand() = address + or + // Since the pruning stage doesn't know about global variables we can't use the above check to + // rule out dead assignments to globals. + base.(VariableAddressInstruction).getAstVariable() instanceof Cpp::GlobalOrNamespaceVariable + ) } or - TExplicitUse(Operand op) { isExplicitUse(op) } or - TReturnParamIndirection(Operand op) { returnParameterIndirection(op, _) } + TUseImpl(Operand operand, int indirectionIndex) { + isUse(_, operand, _, _, indirectionIndex) and + not isDef(_, _, operand, _, _, _) + } or + TGlobalUse(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) { + // Represents a final "use" of a global variable to ensure that + // the assignment to a global variable isn't ruled out as dead. + exists(VariableAddressInstruction vai, int defIndex | + vai.getEnclosingIRFunction() = f and + vai.getAstVariable() = v and + isDef(_, _, _, vai, _, defIndex) and + indirectionIndex = [0 .. defIndex] + 1 + ) + } or + TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) { + // Represents the initial "definition" of a global variable when entering + // a function body. + exists(VariableAddressInstruction vai | + vai.getEnclosingIRFunction() = f and + vai.getAstVariable() = v and + isUse(_, _, vai, _, indirectionIndex) and + not isDef(_, _, vai.getAUse(), _, _, _) + ) + } or + TIteratorDef( + Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex + ) { + isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex) and + any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorDerefAddress + } or + TIteratorUse( + Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex + ) { + isIteratorUse(container, iteratorAddress, _, indirectionIndex) + } or + TFinalParameterUse(Parameter p, int indirectionIndex) { + // Avoid creating parameter nodes if there is no definitions of the variable other than the initializaion. + exists(SsaInternals0::Def def | + def.getSourceVariable().getBaseVariable().(BaseIRVariable).getIRVariable().getAst() = p and + not def.getValue().asInstruction() instanceof InitializeParameterInstruction and + unspecifiedTypeIsModifiableAt(p.getUnspecifiedType(), indirectionIndex) + ) + } -private class DefOrUse extends TDefOrUse { - /** Gets the instruction associated with this definition, if any. */ - Instruction asDef() { none() } +private predicate unspecifiedTypeIsModifiableAt(Type unspecified, int indirectionIndex) { + indirectionIndex = [1 .. getIndirectionForUnspecifiedType(unspecified).getNumberOfIndirections()] and + exists(CppType cppType | + cppType.hasUnspecifiedType(unspecified, _) and + isModifiableAt(cppType, indirectionIndex + 1) + ) +} - /** Gets the operand associated with this use, if any. */ - Operand asUse() { none() } +private Indirection getIndirectionForUnspecifiedType(Type t) { result.getType() = t } +abstract private class DefOrUseImpl extends TDefOrUseImpl { /** Gets a textual representation of this element. */ abstract string toString(); /** Gets the block of this definition or use. */ - abstract IRBlock getBlock(); + final IRBlock getBlock() { this.hasIndexInBlock(result, _) } /** Holds if this definition or use has index `index` in block `block`. */ - final predicate hasIndexInBlock(IRBlock block, int index) { - block.getInstruction(index) = toInstruction(this) + abstract predicate hasIndexInBlock(IRBlock block, int index); + + /** + * Holds if this definition (or use) has index `index` in block `block`, + * and is a definition (or use) of the variable `sv` + */ + final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { + this.hasIndexInBlock(block, index) and + sv = this.getSourceVariable() } /** Gets the location of this element. */ abstract Cpp::Location getLocation(); + + /** + * Gets the index (i.e., the number of loads required) of this + * definition or use. + * + * Note that this is _not_ the definition's (or use's) index in + * the enclosing basic block. To obtain this index, use + * `DefOrUseImpl::hasIndexInBlock/2` or `DefOrUseImpl::hasIndexInBlock/3`. + */ + abstract int getIndirectionIndex(); + + /** + * Gets the instruction that computes the base of this definition or use. + * This is always a `VariableAddressInstruction` or an `AllocationInstruction`. + */ + abstract BaseSourceVariableInstruction getBase(); + + /** + * Gets the base source variable (i.e., the variable without + * any indirection) of this definition or use. + */ + final BaseSourceVariable getBaseSourceVariable() { + this.getBase().getBaseSourceVariable() = result + } + + /** Gets the variable that is defined or used. */ + SourceVariable getSourceVariable() { + exists(BaseSourceVariable v, int ind | + sourceVariableHasBaseAndIndex(result, v, ind) and + defOrUseHasSourceVariable(this, v, ind) + ) + } } -private Instruction toInstruction(DefOrUse defOrUse) { - result = defOrUse.asDef() +private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv, int ind) { + defHasSourceVariable(defOrUse, bv, ind) or - result = defOrUse.asUse().getUse() + useHasSourceVariable(defOrUse, bv, ind) } -abstract class Def extends DefOrUse { - Instruction store; +pragma[noinline] +private predicate defHasSourceVariable(DefImpl def, BaseSourceVariable bv, int ind) { + bv = def.getBaseSourceVariable() and + ind = def.getIndirection() +} - /** Gets the instruction of this definition. */ - Instruction getInstruction() { result = store } +pragma[noinline] +private predicate useHasSourceVariable(UseImpl use, BaseSourceVariable bv, int ind) { + bv = use.getBaseSourceVariable() and + ind = use.getIndirection() +} - /** Gets the variable that is defined by this definition. */ - abstract SourceVariables::SourceVariable getSourceVariable(); +pragma[noinline] +private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVariable bv, int ind) { + v.getBaseVariable() = bv and + v.getIndirection() = ind +} + +abstract class DefImpl extends DefOrUseImpl { + Operand address; + int ind; + + bindingset[ind] + DefImpl() { any() } + + abstract int getIndirection(); + + abstract Node0Impl getValue(); - /** Holds if this definition is guaranteed to happen. */ abstract predicate isCertain(); - override Instruction asDef() { result = this.getInstruction() } + Operand getAddressOperand() { result = address } - override string toString() { result = "Def" } + override int getIndirectionIndex() { result = ind } - override IRBlock getBlock() { result = this.getInstruction().getBlock() } + override string toString() { result = "Def of " + this.getSourceVariable() } - override Cpp::Location getLocation() { result = store.getLocation() } + override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + this.getAddressOperand().getUse() = block.getInstruction(index) + } } -private class ExplicitDef extends Def, TExplicitDef { - ExplicitDef() { this = TExplicitDef(store) } +private class DirectDef extends DefImpl, TDefImpl { + DirectDef() { this = TDefImpl(address, ind) } - override SourceVariables::SourceVariable getSourceVariable() { - exists(VariableInstruction var | - explicitWrite(_, this.getInstruction(), var) and - result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable() - ) - } + override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) } - override predicate isCertain() { explicitWrite(true, this.getInstruction(), _) } + override int getIndirection() { isDef(_, _, address, _, result, ind) } + + override Node0Impl getValue() { isDef(_, result, address, _, _, _) } + + override predicate isCertain() { isDef(true, _, address, _, _, ind) } } -private class ParameterDef extends Def, TInitializeParam { - ParameterDef() { this = TInitializeParam(store) } +private class IteratorDef extends DefImpl, TIteratorDef { + BaseSourceVariableInstruction container; - override SourceVariables::SourceVariable getSourceVariable() { - result.(SourceVariables::SourceIRVariable).getIRVariable() = - store.(InitializeParameterInstruction).getIRVariable() - or - result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() = - store.(InitializeIndirectionInstruction).getIRVariable() + IteratorDef() { this = TIteratorDef(address, container, ind) } + + override BaseSourceVariableInstruction getBase() { result = container } + + override int getIndirection() { isIteratorDef(container, address, _, result, ind) } + + override Node0Impl getValue() { isIteratorDef(container, address, result, _, _) } + + override predicate isCertain() { none() } +} + +abstract class UseImpl extends DefOrUseImpl { + int ind; + + bindingset[ind] + UseImpl() { any() } + + /** Gets the node associated with this use. */ + abstract Node getNode(); + + override string toString() { result = "Use of " + this.getSourceVariable() } + + /** Gets the indirection index of this use. */ + final override int getIndirectionIndex() { result = ind } + + /** Gets the number of loads that precedence this use. */ + abstract int getIndirection(); + + /** + * Holds if this use is guaranteed to read the + * associated variable. + */ + abstract predicate isCertain(); +} + +abstract private class OperandBasedUse extends UseImpl { + Operand operand; + + bindingset[ind] + OperandBasedUse() { any() } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + operand.getUse() = block.getInstruction(index) } + final Operand getOperand() { result = operand } + + final override Cpp::Location getLocation() { result = operand.getLocation() } +} + +private class DirectUse extends OperandBasedUse, TUseImpl { + DirectUse() { this = TUseImpl(operand, ind) } + + override int getIndirection() { isUse(_, operand, _, result, ind) } + + override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) } + + override predicate isCertain() { isUse(true, operand, _, _, ind) } + + override Node getNode() { nodeHasOperand(result, operand, ind) } +} + +private class IteratorUse extends OperandBasedUse, TIteratorUse { + BaseSourceVariableInstruction container; + + IteratorUse() { this = TIteratorUse(operand, container, ind) } + + override int getIndirection() { isIteratorUse(container, operand, result, ind) } + + override BaseSourceVariableInstruction getBase() { result = container } + + override predicate isCertain() { none() } + + override Node getNode() { nodeHasOperand(result, operand, ind) } +} + +pragma[nomagic] +private predicate finalParameterNodeHasParameterAndIndex( + FinalParameterNode n, Parameter p, int indirectionIndex +) { + n.getParameter() = p and + n.getIndirectionIndex() = indirectionIndex +} + +class FinalParameterUse extends UseImpl, TFinalParameterUse { + Parameter p; + + FinalParameterUse() { this = TFinalParameterUse(p, ind) } + + Parameter getParameter() { result = p } + + override Node getNode() { finalParameterNodeHasParameterAndIndex(result, p, ind) } + + override int getIndirection() { result = ind + 1 } + override predicate isCertain() { any() } -} -abstract class Use extends DefOrUse { - Operand use; + override predicate hasIndexInBlock(IRBlock block, int index) { + // Ideally, this should always be a `ReturnInstruction`, but if + // someone forgets to write a `return` statement in a function + // with a non-void return type we generate an `UnreachedInstruction`. + // In this case we still want to generate flow out of such functions + // if they write to a parameter. So we pick the index of the + // `UnreachedInstruction` as the index of this use. + // Note that a function may have both a `ReturnInstruction` and an + // `UnreachedInstruction`. If that's the case this predicate will + // return multiple results. I don't think this is detrimental to + // performance, however. + exists(Instruction return | + return instanceof ReturnInstruction or + return instanceof UnreachedInstruction + | + block.getInstruction(index) = return and + return.getEnclosingFunction() = p.getFunction() + ) + } - override Operand asUse() { result = use } + override Cpp::Location getLocation() { + // Parameters can have multiple locations. When there's a unique location we use + // that one, but if multiple locations exist we default to an unknown location. + result = unique( | | p.getLocation()) + or + not exists(unique( | | p.getLocation())) and + result instanceof UnknownDefaultLocation + } - /** Gets the underlying operand of this use. */ - Operand getOperand() { result = use } - - override string toString() { result = "Use" } - - /** Gets the variable that is used by this use. */ - abstract SourceVariables::SourceVariable getSourceVariable(); - - override IRBlock getBlock() { result = use.getUse().getBlock() } - - override Cpp::Location getLocation() { result = use.getLocation() } -} - -private class ExplicitUse extends Use, TExplicitUse { - ExplicitUse() { this = TExplicitUse(use) } - - override SourceVariables::SourceVariable getSourceVariable() { - exists(VariableInstruction var | - use.getDef() = var and - if use.getUse() instanceof ReadSideEffectInstruction - then - result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() = - var.getIRVariable() - else result.(SourceVariables::SourceIRVariable).getIRVariable() = var.getIRVariable() + override BaseSourceVariableInstruction getBase() { + exists(InitializeParameterInstruction init | + init.getParameter() = p and + // This is always a `VariableAddressInstruction` + result = init.getAnOperand().getDef() ) } } -private class ReturnParameterIndirection extends Use, TReturnParamIndirection { - ReturnParameterIndirection() { this = TReturnParamIndirection(use) } +class GlobalUse extends UseImpl, TGlobalUse { + Cpp::GlobalOrNamespaceVariable global; + IRFunction f; - override SourceVariables::SourceVariable getSourceVariable() { - exists(ReturnIndirectionInstruction ret | - returnParameterIndirection(use, ret) and - result.(SourceVariables::SourceIRVariableIndirection).getUnderlyingIRVariable() = - ret.getIRVariable() + GlobalUse() { this = TGlobalUse(global, f, ind) } + + override FinalGlobalValue getNode() { result.getGlobalUse() = this } + + override int getIndirection() { result = ind + 1 } + + /** Gets the global variable associated with this use. */ + Cpp::GlobalOrNamespaceVariable getVariable() { result = global } + + /** Gets the `IRFunction` whose body is exited from after this use. */ + IRFunction getIRFunction() { result = f } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + exists(ExitFunctionInstruction exit | + exit = f.getExitFunctionInstruction() and + block.getInstruction(index) = exit ) } + + override SourceVariable getSourceVariable() { sourceVariableIsGlobal(result, global, f, ind) } + + final override Cpp::Location getLocation() { result = f.getLocation() } + + /** + * Gets the type of this use after specifiers have been deeply stripped + * and typedefs have been resolved. + */ + Type getUnspecifiedType() { result = global.getUnspecifiedType() } + + override predicate isCertain() { any() } + + override BaseSourceVariableInstruction getBase() { none() } } -private predicate isExplicitUse(Operand op) { - exists(VariableAddressInstruction vai | vai = op.getDef() | - // Don't include this operand as a use if it only exists to initialize the - // indirection of a parameter. - not exists(LoadInstruction load | - load.getSourceAddressOperand() = op and - load.getAUse().getUse() instanceof InitializeIndirectionInstruction - ) and - // Don't include this operand as a use if the only use of the address is for a write - // that definitely overrides a variable. - not (explicitWrite(true, _, vai) and exists(unique( | | vai.getAUse()))) - ) -} +class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl { + Cpp::GlobalOrNamespaceVariable global; + IRFunction f; + int indirectionIndex; -private predicate returnParameterIndirection(Operand op, ReturnIndirectionInstruction ret) { - ret.getSourceAddressOperand() = op + GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) } + + /** Gets the global variable associated with this definition. */ + Cpp::GlobalOrNamespaceVariable getVariable() { result = global } + + /** Gets the `IRFunction` whose body is evaluated after this definition. */ + IRFunction getIRFunction() { result = f } + + /** Gets the global variable associated with this definition. */ + override int getIndirectionIndex() { result = indirectionIndex } + + /** Holds if this definition or use has index `index` in block `block`. */ + final override predicate hasIndexInBlock(IRBlock block, int index) { + exists(EnterFunctionInstruction enter | + enter = f.getEnterFunctionInstruction() and + block.getInstruction(index) = enter + ) + } + + /** Gets the global variable associated with this definition. */ + override SourceVariable getSourceVariable() { + sourceVariableIsGlobal(result, global, f, indirectionIndex) + } + + /** + * Gets the type of this use after specifiers have been deeply stripped + * and typedefs have been resolved. + */ + Type getUnspecifiedType() { result = global.getUnspecifiedType() } + + override string toString() { result = "GlobalDef" } + + override Location getLocation() { result = f.getLocation() } + + override BaseSourceVariableInstruction getBase() { none() } } /** - * Holds if `iFrom` computes an address that is used by `iTo`. + * Holds if `defOrUse1` is a definition which is first read by `use`, + * or if `defOrUse1` is a use and `use` is a next subsequent use. + * + * In both cases, `use` can either be an explicit use written in the + * source file, or it can be a phi node as computed by the SSA library. */ -predicate addressFlow(Instruction iFrom, Instruction iTo) { - iTo.(CopyValueInstruction).getSourceValue() = iFrom - or - iTo.(ConvertInstruction).getUnary() = iFrom - or - iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom - or - iTo.(InheritanceConversionInstruction).getUnary() = iFrom - or - iTo.(PointerArithmeticInstruction).getLeft() = iFrom - or - iTo.(FieldAddressInstruction).getObjectAddress() = iFrom - or - // We traverse `LoadInstruction`s since we want to conclude that the - // destination of the store operation `*x = source()` is derived from `x`. - iTo.(LoadInstruction).getSourceAddress() = iFrom - or - // We want to include `ReadSideEffectInstruction`s for the same reason that we include - // `LoadInstruction`s, but only when a `WriteSideEffectInstruction` for the same index exists as well - // (as otherwise we know that the callee won't override the data). However, given an index `i`, the - // destination of the `WriteSideEffectInstruction` for `i` is identical to the source address of the - // `ReadSideEffectInstruction` for `i`. So we don't have to talk about the `ReadSideEffectInstruction` - // at all. - exists(WriteSideEffectInstruction write | - write.getPrimaryInstruction() = iTo and - write.getDestinationAddress() = iFrom - ) -} - -/** - * The reflexive, transitive closure of `addressFlow` that ends as the address of a - * store or read operation. - */ -cached -predicate addressFlowTC(Instruction iFrom, Instruction iTo) { - iTo = [getDestinationAddress(_), getSourceAddress(_)] and - addressFlow*(iFrom, iTo) -} - -/** - * Gets the destination address of `instr` if it is a `StoreInstruction` or - * a `WriteSideEffectInstruction`. - */ -Instruction getDestinationAddress(Instruction instr) { - result = - [ - instr.(StoreInstruction).getDestinationAddress(), - instr.(WriteSideEffectInstruction).getDestinationAddress() - ] -} - -/** Gets the source address of `instr` if it is an instruction that behaves like a `LoadInstruction`. */ -Instruction getSourceAddress(Instruction instr) { result = getSourceAddressOperand(instr).getDef() } - -/** - * Gets the operand that represents the source address of `instr` if it is an - * instruction that behaves like a `LoadInstruction`. - */ -Operand getSourceAddressOperand(Instruction instr) { - result = - [ - instr.(LoadInstruction).getSourceAddressOperand(), - instr.(ReadSideEffectInstruction).getArgumentOperand() - ] -} - -/** - * Gets the source address of `node` if it's an instruction or operand that - * behaves like a `LoadInstruction`. - */ -Instruction getSourceAddressFromNode(Node node) { - result = getSourceAddress(node.asInstruction()) - or - result = getSourceAddress(node.asOperand().(SideEffectOperand).getUse()) -} - -/** - * Gets the operand that represents the source value of `instr` if it's an instruction - * that behaves like a `LoadInstruction`. - */ -Operand getSourceValueOperand(Instruction instr) { - result = instr.(LoadInstruction).getSourceValueOperand() - or - result = instr.(ReadSideEffectInstruction).getSideEffectOperand() -} - -/** - * Holds if `instr` is a `StoreInstruction` or a `WriteSideEffectInstruction` that writes to an address. - * The addresses is computed using `address`, and `certain` is `true` if the write is guaranteed to overwrite - * the entire variable. - */ -cached -predicate explicitWrite(boolean certain, Instruction instr, Instruction address) { - exists(StoreInstruction store | - store = instr and addressFlowTC(address, store.getDestinationAddress()) +predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) { + exists(IRBlock bb1, int i1, SourceVariable v | + defOrUse1.asDefOrUse().hasIndexInBlock(bb1, i1, v) | - // Set `certain = false` if the address is derived from any instructions that prevents us from - // concluding that the entire variable is overridden. - if - addressFlowTC(any(Instruction i | - i instanceof FieldAddressInstruction or - i instanceof PointerArithmeticInstruction or - i instanceof LoadInstruction or - i instanceof InheritanceConversionInstruction - ), store.getDestinationAddress()) - then certain = false - else certain = true + exists(IRBlock bb2, int i2, DefinitionExt def | + adjacentDefReadExt(pragma[only_bind_into](def), pragma[only_bind_into](bb1), + pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and + def.getSourceVariable() = v and + use.asDefOrUse().(UseImpl).hasIndexInBlock(bb2, i2, v) + ) + or + exists(PhiNode phi | + lastRefRedefExt(_, bb1, i1, phi) and + use.asPhi() = phi and + phi.getSourceVariable() = pragma[only_bind_into](v) + ) ) +} + +/** + * Holds if `globalDef` represents the initial definition of a global variable that + * flows to `useOrPhi`. + */ +private predicate globalDefToUse(GlobalDef globalDef, UseOrPhi useOrPhi) { + exists(IRBlock bb1, int i1, SourceVariable v | globalDef.hasIndexInBlock(bb1, i1, v) | + exists(IRBlock bb2, int i2 | + adjacentDefReadExt(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1), + pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and + useOrPhi.asDefOrUse().hasIndexInBlock(bb2, i2, v) + ) + or + exists(PhiNode phi | + lastRefRedefExt(_, bb1, i1, phi) and + useOrPhi.asPhi() = phi and + phi.getSourceVariable() = pragma[only_bind_into](v) + ) + ) +} + +private predicate useToNode(UseOrPhi use, Node nodeTo) { use.getNode() = nodeTo } + +pragma[noinline] +predicate outNodeHasAddressAndIndex( + IndirectArgumentOutNode out, Operand address, int indirectionIndex +) { + out.getAddressOperand() = address and + out.getIndirectionIndex() = indirectionIndex +} + +private predicate defToNode(Node nodeFrom, Def def, boolean uncertain) { + ( + nodeHasOperand(nodeFrom, def.getValue().asOperand(), def.getIndirectionIndex()) + or + nodeHasInstruction(nodeFrom, def.getValue().asInstruction(), def.getIndirectionIndex()) + ) and + if def.isCertain() then uncertain = false else uncertain = true +} + +/** + * INTERNAL: Do not use. + * + * Holds if `nodeFrom` is the node that correspond to the definition or use `defOrUse`. + */ +predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse, boolean uncertain) { + // Node -> Def + defToNode(nodeFrom, defOrUse, uncertain) or - addressFlowTC(address, instr.(WriteSideEffectInstruction).getDestinationAddress()) and - certain = false + // Node -> Use + useToNode(defOrUse, nodeFrom) and + uncertain = false } -cached -private module Cached { - private predicate defUseFlow(Node nodeFrom, Node nodeTo) { - exists(IRBlock bb1, int i1, IRBlock bb2, int i2, DefOrUse defOrUse, Use use | - defOrUse.hasIndexInBlock(bb1, i1) and - use.hasIndexInBlock(bb2, i2) and - adjacentDefRead(_, bb1, i1, bb2, i2) and - nodeFrom.asInstruction() = toInstruction(defOrUse) and - flowOutOfAddressStep(use.getOperand(), nodeTo) - ) - } - - private predicate fromStoreNode(StoreNodeInstr nodeFrom, Node nodeTo) { - // Def-use flow from a `StoreNode`. - exists(IRBlock bb1, int i1, IRBlock bb2, int i2, Def def, Use use | - nodeFrom.isTerminal() and - def.getInstruction() = nodeFrom.getStoreInstruction() and - def.hasIndexInBlock(bb1, i1) and - adjacentDefRead(_, bb1, i1, bb2, i2) and - use.hasIndexInBlock(bb2, i2) and - flowOutOfAddressStep(use.getOperand(), nodeTo) +/** + * Perform a single conversion-like step from `nFrom` to `nTo`. This relation + * only holds when there is no use-use relation out of `nTo`. + */ +private predicate indirectConversionFlowStep(Node nFrom, Node nTo) { + not exists(UseOrPhi defOrUse | + nodeToDefOrUse(nTo, defOrUse, _) and + adjacentDefRead(defOrUse, _) + ) and + ( + exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr | + hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and + hasOperandAndIndex(nTo, op2, pragma[only_bind_into](indirectionIndex)) and + instr = op2.getDef() and + conversionFlow(op1, instr, _, _) ) or - // This final case is a bit annoying. The write side effect on an expression like `a = new A;` writes - // to a fresh address returned by `operator new`, and there's no easy way to use the shared SSA - // library to hook that up to the assignment to `a`. So instead we flow to the _first_ use of the - // value computed by `operator new` that occurs after `nodeFrom` (to avoid a loop in the - // dataflow graph). - exists(WriteSideEffectInstruction write, IRBlock bb, int i1, int i2, Operand op | - nodeFrom.getInstruction().(CallInstruction).getStaticCallTarget() instanceof - Alloc::OperatorNewAllocationFunction and - write = nodeFrom.getStoreInstruction() and - bb.getInstruction(i1) = write and - bb.getInstruction(i2) = op.getUse() and - // Flow to an instruction that occurs later in the block. - conversionFlow*(nodeFrom.getInstruction(), op.getDef()) and - nodeTo.asOperand() = op and - i2 > i1 and - // There is no previous instruction that also occurs after `nodeFrom`. - not exists(Instruction instr, int i | - bb.getInstruction(i) = instr and - conversionFlow(instr, op.getDef()) and - i1 < i and - i < i2 - ) + exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr | + hasOperandAndIndex(nFrom, op1, pragma[only_bind_into](indirectionIndex)) and + hasOperandAndIndex(nTo, op2, indirectionIndex - 1) and + instr = op2.getDef() and + isDereference(instr, op1) ) - } - - private predicate fromReadNode(ReadNode nodeFrom, Node nodeTo) { - exists(IRBlock bb1, int i1, IRBlock bb2, int i2, Use use1, Use use2 | - use1.hasIndexInBlock(bb1, i1) and - use2.hasIndexInBlock(bb2, i2) and - use1.getOperand().getDef() = nodeFrom.getInstruction() and - adjacentDefRead(_, bb1, i1, bb2, i2) and - flowOutOfAddressStep(use2.getOperand(), nodeTo) - ) - } - - private predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) { - exists(PhiNode phi, Use use, IRBlock block, int rnk | - phi = nodeFrom.getPhiNode() and - adjacentDefRead(phi, _, _, block, rnk) and - use.hasIndexInBlock(block, rnk) and - flowOutOfAddressStep(use.getOperand(), nodeTo) - ) - } - - private predicate toPhiNode(Node nodeFrom, SsaPhiNode nodeTo) { - // Flow to phi nodes - exists(Def def, IRBlock block, int rnk | - def.hasIndexInBlock(block, rnk) and - nodeTo.hasInputAtRankInBlock(block, rnk) - | - exists(StoreNodeInstr storeNode | - storeNode = nodeFrom and - storeNode.isTerminal() and - def.getInstruction() = storeNode.getStoreInstruction() - ) - or - def.getInstruction() = nodeFrom.asInstruction() - ) - or - // Phi -> phi flow - nodeTo.hasInputAtRankInBlock(_, _, nodeFrom.(SsaPhiNode).getPhiNode()) - } - - /** - * Holds if `nodeFrom` is a read or write, and `nTo` is the next subsequent read of the variable - * written (or read) by `storeOrRead`. - */ - cached - predicate ssaFlow(Node nodeFrom, Node nodeTo) { - // Def-use/use-use flow from an `InstructionNode`. - defUseFlow(nodeFrom, nodeTo) - or - // Def-use flow from a `StoreNode`. - fromStoreNode(nodeFrom, nodeTo) - or - // Use-use flow from a `ReadNode`. - fromReadNode(nodeFrom, nodeTo) - or - fromPhiNode(nodeFrom, nodeTo) - or - toPhiNode(nodeFrom, nodeTo) - or - // When we want to transfer flow out of a `StoreNode` we perform two steps: - // 1. Find the next use of the address being stored to - // 2. Find the `LoadInstruction` that loads the address - // When the address being stored into doesn't have a `LoadInstruction` associated with it because it's - // passed into a `CallInstruction` we transfer flow to the `ReadSideEffect`, which will then flow into - // the callee. We then pickup the flow from the `InitializeIndirectionInstruction` and use the shared - // SSA library to determine where the next use of the address that received the flow is. - exists(Node init, Node mid | - nodeFrom.asInstruction().(InitializeIndirectionInstruction).getIRVariable() = - init.asInstruction().(InitializeParameterInstruction).getIRVariable() and - // No need for the flow if the next use is the instruction that returns the flow out of the callee. - not mid.asInstruction() instanceof ReturnIndirectionInstruction and - // Find the next use of the address - ssaFlow(init, mid) and - // And flow to the next load of that address - flowOutOfAddressStep([mid.asInstruction().getAUse(), mid.asOperand()], nodeTo) - ) - } - - /** - * Holds if `iTo` is a conversion-like instruction that copies - * the value computed by `iFrom`. - * - * This predicate is used by `fromStoreNode` to find the next use of a pointer that - * points to freshly allocated memory. - */ - private predicate conversionFlow(Instruction iFrom, Instruction iTo) { - iTo.(CopyValueInstruction).getSourceValue() = iFrom - or - iTo.(ConvertInstruction).getUnary() = iFrom - or - iTo.(CheckedConvertOrNullInstruction).getUnary() = iFrom - or - iTo.(InheritanceConversionInstruction).getUnary() = iFrom - } - - pragma[noinline] - private predicate callTargetHasInputOutput( - CallInstruction call, DataFlow::FunctionInput input, DataFlow::FunctionOutput output - ) { - exists(DataFlow::DataFlowFunction func | - call.getStaticCallTarget() = func and - func.hasDataFlow(input, output) - ) - } - - /** - * The role of `flowOutOfAddressStep` is to select the node for which we want dataflow to end up in - * after the shared SSA library's `adjacentDefRead` predicate has determined that `operand` is the - * next use of some variable. - * - * More precisely, this predicate holds if `operand` is an operand that represents an address, and: - * - `nodeTo` is the next load of that address, or - * - `nodeTo` is a `ReadNode` that uses the definition of `operand` to start a sequence of reads, or - * - `nodeTo` is the outer-most `StoreNode` that uses the address represented by `operand`. We obtain - * use-use flow in this case since `StoreNodeFlow::flowOutOf` will then provide flow to the next of - * of `operand`. - * - * There is one final (slightly annoying) case: When `operand` is a an argument to a modeled function - * without any `ReadSideEffect` (such as `std::move`). Here, the address flows from the argument to - * the return value, which might then be read later. - */ - private predicate flowOutOfAddressStep(Operand operand, Node nodeTo) { - // Flow into a read node - exists(ReadNode readNode | readNode = nodeTo | - readNode.isInitial() and - operand.getDef() = readNode.getInstruction() - ) - or - exists(StoreNodeInstr storeNode, Instruction def | - storeNode = nodeTo and - def = operand.getDef() - | - storeNode.isTerminal() and - not addressFlow(def, _) and - // Only transfer flow to a store node if it doesn't immediately overwrite the address - // we've just written to. - explicitWrite(false, storeNode.getStoreInstruction(), def) - ) - or - // The destination of a store operation has undergone lvalue-to-rvalue conversion and is now a - // right-hand-side of a store operation. - // Find the next use of the variable in that store operation, and recursively find the load of that - // pointer. For example, consider this case: - // - // ```cpp - // int x = source(); - // int* p = &x; - // sink(*p); - // ``` - // - // if we want to find the load of the address of `x`, we see that the pointer is stored into `p`, - // and we then need to recursively look for the load of `p`. - exists( - Def def, StoreInstruction store, IRBlock block1, int rnk1, Use use, IRBlock block2, int rnk2 - | - store = def.getInstruction() and - store.getSourceValueOperand() = operand and - def.hasIndexInBlock(block1, rnk1) and - use.hasIndexInBlock(block2, rnk2) and - adjacentDefRead(_, block1, rnk1, block2, rnk2) - | - // The shared SSA library has determined that `use` is the next use of the operand - // so we find the next load of that use (but only if there is no `PostUpdateNode`) we - // need to flow into first. - not StoreNodeFlow::flowInto(store, _) and - flowOutOfAddressStep(use.getOperand(), nodeTo) - or - // It may also be the case that `store` gives rise to another store step. So let's make sure that - // we also take those into account. - StoreNodeFlow::flowInto(store, nodeTo) - ) - or - // As we find the next load of an address, we might come across another use of the same variable. - // In that case, we recursively find the next use of _that_ operand, and continue searching for - // the next load of that operand. For example, consider this case: - // - // ```cpp - // int x = source(); - // use(&x); - // int* p = &x; - // sink(*p); - // ``` - // - // The next use of `x` after its definition is `use(&x)`, but there is a later load of the address - // of `x` that we want to flow to. So we use the shared SSA library to find the next load. - not operand = getSourceAddressOperand(_) and - exists(Use use1, Use use2, IRBlock block1, int rnk1, IRBlock block2, int rnk2 | - use1.getOperand() = operand and - use1.hasIndexInBlock(block1, rnk1) and - // Don't flow to the next use if this use is part of a store operation that totally - // overrides a variable. - not explicitWrite(true, _, use1.getOperand().getDef()) and - adjacentDefRead(_, block1, rnk1, block2, rnk2) and - use2.hasIndexInBlock(block2, rnk2) and - flowOutOfAddressStep(use2.getOperand(), nodeTo) - ) - or - operand = getSourceAddressOperand(nodeTo.asInstruction()) - or - exists(ReturnIndirectionInstruction ret | - ret.getSourceAddressOperand() = operand and - ret = nodeTo.asInstruction() - ) - or - exists(ReturnValueInstruction ret | - ret.getReturnAddressOperand() = operand and - nodeTo.asInstruction() = ret - ) - or - exists(CallInstruction call, int index, ReadSideEffectInstruction read | - call.getArgumentOperand(index) = operand and - read = getSideEffectFor(call, index) and - nodeTo.asOperand() = read.getSideEffectOperand() - ) - or - exists(CopyInstruction copy | - not exists(getSourceAddressOperand(copy)) and - copy.getSourceValueOperand() = operand and - flowOutOfAddressStep(copy.getAUse(), nodeTo) - ) - or - exists(ConvertInstruction convert | - convert.getUnaryOperand() = operand and - flowOutOfAddressStep(convert.getAUse(), nodeTo) - ) - or - exists(CheckedConvertOrNullInstruction convert | - convert.getUnaryOperand() = operand and - flowOutOfAddressStep(convert.getAUse(), nodeTo) - ) - or - exists(InheritanceConversionInstruction convert | - convert.getUnaryOperand() = operand and - flowOutOfAddressStep(convert.getAUse(), nodeTo) - ) - or - exists(PointerArithmeticInstruction arith | - arith.getLeftOperand() = operand and - flowOutOfAddressStep(arith.getAUse(), nodeTo) - ) - or - // Flow through a modeled function that has parameter -> return value flow. - exists( - CallInstruction call, int index, DataFlow::FunctionInput input, - DataFlow::FunctionOutput output - | - callTargetHasInputOutput(call, input, output) and - call.getArgumentOperand(index) = operand and - not getSideEffectFor(call, index) instanceof ReadSideEffectInstruction and - input.isParameter(index) and - output.isReturnValue() and - flowOutOfAddressStep(call.getAUse(), nodeTo) - ) - } + ) } -import Cached +/** + * The reason for this predicate is a bit annoying: + * We cannot mark a `PointerArithmeticInstruction` that computes an offset based on some SSA + * variable `x` as a use of `x` since this creates taint-flow in the following example: + * ```c + * int x = array[source] + * sink(*array) + * ``` + * This is because `source` would flow from the operand of `PointerArithmeticInstruction` to the + * result of the instruction, and into the `IndirectOperand` that represents the value of `*array`. + * Then, via use-use flow, flow will arrive at `*array` in `sink(*array)`. + * + * So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the + * first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`. + */ +private predicate adjustForPointerArith( + DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain +) { + nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and + exists(Node adjusted | + indirectConversionFlowStep*(adjusted, nodeFrom) and + nodeToDefOrUse(adjusted, defOrUse, uncertain) and + adjacentDefRead(defOrUse, use) + ) +} + +private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) { + // `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith. + exists(UseOrPhi use | + adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and + useToNode(use, nodeTo) + or + not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and + nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and + adjacentDefRead(defOrUse, use) and + useToNode(use, nodeTo) + or + // Initial global variable value to a first use + nodeFrom.(InitialGlobalValue).getGlobalDef() = defOrUse and + globalDefToUse(defOrUse, use) and + useToNode(use, nodeTo) and + uncertain = false + ) +} + +/** + * Holds if `def` is the corresponding definition of + * the SSA library's `definition`. + */ +private DefinitionExt ssaDefinition(Def def) { + exists(IRBlock block, int i, SourceVariable sv | + def.hasIndexInBlock(block, i, sv) and + result.definesAt(sv, block, i, _) + ) +} + +/** Gets a node that represents the prior definition of `node`. */ +private Node getAPriorDefinition(SsaDefOrUse defOrUse) { + exists(IRBlock bb, int i, SourceVariable sv, DefinitionExt def, DefOrUse defOrUse0 | + lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](bb), + pragma[only_bind_into](i), ssaDefinition(defOrUse)) and + def.getSourceVariable() = sv and + defOrUse0.hasIndexInBlock(bb, i, sv) and + nodeToDefOrUse(result, defOrUse0, _) + ) +} + +/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */ +predicate ssaFlow(Node nodeFrom, Node nodeTo) { + exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse | + ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and + if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom + ) +} + +/** + * Holds if `use` is a use of `sv` and is a next adjacent use of `phi` in + * index `i1` in basic block `bb1`. + * + * This predicate exists to prevent an early join of `adjacentDefRead` with `definesAt`. + */ +pragma[nomagic] +private predicate fromPhiNodeToUse(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use) { + exists(IRBlock bb2, int i2 | + use.asDefOrUse().hasIndexInBlock(bb2, i2, sv) and + adjacentDefReadExt(pragma[only_bind_into](phi), pragma[only_bind_into](bb1), + pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) + ) +} + +/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */ +predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) { + exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use | + phi = nodeFrom.getPhiNode() and + phi.definesAt(sv, bb1, i1, _) and + useToNode(use, nodeTo) + | + fromPhiNodeToUse(phi, sv, bb1, i1, use) + or + exists(PhiNode phiTo | + lastRefRedefExt(phi, _, _, phiTo) and + nodeTo.(SsaPhiNode).getPhiNode() = phiTo + ) + ) +} + +/** + * Holds if there is a write at index `i` in basic block `bb` to variable `v` that's + * subsequently read (as determined by the SSA pruning stage). + */ +private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) { + exists(SsaInternals0::Def def, SsaInternals0::SourceVariable v0 | + def.asDefOrUse().hasIndexInBlock(bb, i, v0) and + v0 = v.getBaseVariable() + ) +} + +private predicate sourceVariableIsGlobal( + SourceVariable sv, Cpp::GlobalOrNamespaceVariable global, IRFunction func, int indirectionIndex +) { + exists(IRVariable irVar, BaseIRVariable base | + sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and + irVar = base.getIRVariable() and + irVar.getEnclosingIRFunction() = func and + global = irVar.getAst() + ) +} private module SsaInput implements SsaImplCommon::InputSig { - private import semmle.code.cpp.ir.IR - - class BasicBlock = IRBlock; - - class SourceVariable = SourceVariables::SourceVariable; - - BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) } - - BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } - - class ExitBasicBlock extends IRBlock { - ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction } - } + import InputSigCommon + import SourceVariables /** * Holds if the `i`'th write in block `bb` writes to the variable `v`. * `certain` is `true` if the write is guaranteed to overwrite the entire variable. */ - predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) { + predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) { DataFlowImplCommon::forceCachingInSameStage() and - exists(Def def | - def.hasIndexInBlock(bb, i) and - v = def.getSourceVariable() and - (if def.isCertain() then certain = true else certain = false) + ( + variableWriteCand(bb, i, v) or + sourceVariableIsGlobal(v, _, _, _) + ) and + exists(DefImpl def | def.hasIndexInBlock(bb, i, v) | + if def.isCertain() then certain = true else certain = false + ) + or + exists(GlobalDefImpl global | + global.hasIndexInBlock(bb, i, v) and + certain = true ) } @@ -640,13 +798,209 @@ private module SsaInput implements SsaImplCommon::InputSig { * Holds if the `i`'th read in block `bb` reads to the variable `v`. * `certain` is `true` if the read is guaranteed. For C++, this is always the case. */ - predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) { - exists(Use use | - use.hasIndexInBlock(bb, i) and - v = use.getSourceVariable() and + predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) { + exists(UseImpl use | use.hasIndexInBlock(bb, i, v) | + if use.isCertain() then certain = true else certain = false + ) + or + exists(GlobalUse global | + global.hasIndexInBlock(bb, i, v) and certain = true ) } } -import SsaImplCommon::Make +/** + * The final SSA predicates used for dataflow purposes. + */ +cached +module SsaCached { + /** + * 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`. + */ + cached + predicate adjacentDefReadExt(DefinitionExt def, IRBlock bb1, int i1, IRBlock bb2, int i2) { + SsaImpl::adjacentDefReadExt(def, _, bb1, i1, bb2, i2) + } + + /** + * 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. + */ + cached + predicate lastRefRedefExt(DefinitionExt def, IRBlock bb, int i, DefinitionExt next) { + SsaImpl::lastRefRedefExt(def, _, bb, i, next) + } +} + +cached +private newtype TSsaDefOrUse = + TDefOrUse(DefOrUseImpl defOrUse) { + defOrUse instanceof UseImpl + or + // Like in the pruning stage, we only include definition that's live after the + // write as the final definitions computed by SSA. + exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i | + def.definesAt(sv, bb, i, _) and + defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv) + ) + } or + TPhi(PhiNode phi) or + TGlobalDef(GlobalDefImpl global) + +abstract private class SsaDefOrUse extends TSsaDefOrUse { + /** Gets a textual representation of this element. */ + string toString() { none() } + + /** Gets the underlying non-phi definition or use. */ + DefOrUseImpl asDefOrUse() { none() } + + /** Gets the underlying phi node. */ + PhiNode asPhi() { none() } + + /** Gets the location of this element. */ + abstract Location getLocation(); +} + +class DefOrUse extends TDefOrUse, SsaDefOrUse { + DefOrUseImpl defOrUse; + + DefOrUse() { this = TDefOrUse(defOrUse) } + + final override DefOrUseImpl asDefOrUse() { result = defOrUse } + + final override Location getLocation() { result = defOrUse.getLocation() } + + final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() } + + override string toString() { result = defOrUse.toString() } + + /** + * Holds if this definition (or use) has index `index` in block `block`, + * and is a definition (or use) of the variable `sv`. + */ + predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { + defOrUse.hasIndexInBlock(block, index, sv) + } +} + +class GlobalDef extends TGlobalDef, SsaDefOrUse { + GlobalDefImpl global; + + GlobalDef() { this = TGlobalDef(global) } + + /** Gets the location of this definition. */ + final override Location getLocation() { result = global.getLocation() } + + /** Gets a textual representation of this definition. */ + override string toString() { result = "GlobalDef" } + + /** + * Holds if this definition has index `index` in block `block`, and + * is a definition of the variable `sv`. + */ + predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { + global.hasIndexInBlock(block, index, sv) + } + + /** Gets the indirection index of this definition. */ + int getIndirectionIndex() { result = global.getIndirectionIndex() } + + /** + * Gets the type of this definition after specifiers have been deeply stripped + * and typedefs have been resolved. + */ + DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() } + + /** Gets the `IRFunction` whose body is evaluated after this definition. */ + IRFunction getIRFunction() { result = global.getIRFunction() } + + /** Gets the global variable associated with this definition. */ + Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() } +} + +class Phi extends TPhi, SsaDefOrUse { + PhiNode phi; + + Phi() { this = TPhi(phi) } + + final override PhiNode asPhi() { result = phi } + + final override Location getLocation() { result = phi.getBasicBlock().getLocation() } + + override string toString() { result = "Phi" } + + SsaPhiNode getNode() { result.getPhiNode() = phi } +} + +class UseOrPhi extends SsaDefOrUse { + UseOrPhi() { + this.asDefOrUse() instanceof UseImpl + or + this instanceof Phi + } + + final override Location getLocation() { + result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation() + } + + final Node getNode() { + result = this.(Phi).getNode() + or + result = this.asDefOrUse().(UseImpl).getNode() + } +} + +class Def extends DefOrUse { + override DefImpl defOrUse; + + Operand getAddressOperand() { result = defOrUse.getAddressOperand() } + + Instruction getAddress() { result = this.getAddressOperand().getDef() } + + /** + * Gets the indirection index of this definition. + * + * This predicate ensures that joins go from `defOrUse` to the result + * instead of the other way around. + */ + pragma[inline] + int getIndirectionIndex() { + pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirectionIndex() + } + + /** + * Gets the indirection level that this definition is writing to. + * For instance, `x = y` is a definition of `x` at indirection level 1 and + * `*x = y` is a definition of `x` at indirection level 2. + * + * This predicate ensures that joins go from `defOrUse` to the result + * instead of the other way around. + */ + pragma[inline] + int getIndirection() { + pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirection() + } + + Node0Impl getValue() { result = defOrUse.getValue() } + + predicate isCertain() { defOrUse.isCertain() } +} + +private module SsaImpl = SsaImplCommon::Make; + +class PhiNode extends SsaImpl::DefinitionExt { + PhiNode() { + this instanceof SsaImpl::PhiNode or + this instanceof SsaImpl::PhiReadNode + } +} + +class DefinitionExt = SsaImpl::DefinitionExt; + +class UncertainWriteDefinition = SsaImpl::UncertainWriteDefinition; + +import SsaCached diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll new file mode 100644 index 00000000000..84cdefe7823 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll @@ -0,0 +1,907 @@ +import cpp as Cpp +import semmle.code.cpp.ir.IR +import semmle.code.cpp.ir.internal.IRCppLanguage +private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects +private import DataFlowImplCommon as DataFlowImplCommon +private import DataFlowUtil +private import semmle.code.cpp.models.interfaces.PointerWrapper +private import DataFlowPrivate + +/** + * Holds if `operand` is an operand that is not used by the dataflow library. + * Ignored operands are not recognized as uses by SSA, and they don't have a + * corresponding `(Indirect)OperandNode`. + */ +predicate ignoreOperand(Operand operand) { + operand = any(Instruction instr | ignoreInstruction(instr)).getAnOperand() or + operand = any(Instruction instr | ignoreInstruction(instr)).getAUse() or + operand instanceof MemoryOperand +} + +/** + * Holds if `instr` is an instruction that is not used by the dataflow library. + * Ignored instructions are not recognized as reads/writes by SSA, and they + * don't have a corresponding `(Indirect)InstructionNode`. + */ +predicate ignoreInstruction(Instruction instr) { + DataFlowImplCommon::forceCachingInSameStage() and + ( + instr instanceof WriteSideEffectInstruction or + instr instanceof PhiInstruction or + instr instanceof ReadSideEffectInstruction or + instr instanceof ChiInstruction or + instr instanceof InitializeIndirectionInstruction or + instr instanceof AliasedDefinitionInstruction or + instr instanceof InitializeNonLocalInstruction or + instr instanceof ReturnIndirectionInstruction + ) +} + +/** + * Gets the C++ type of `this` in the member function `f`. + * The result is a glvalue if `isGLValue` is true, and + * a prvalue if `isGLValue` is false. + */ +bindingset[isGLValue] +private CppType getThisType(Cpp::MemberFunction f, boolean isGLValue) { + result.hasType(f.getTypeOfThis(), isGLValue) +} + +/** + * Gets the C++ type of the instruction `i`. + * + * This is equivalent to `i.getResultLanguageType()` with the exception + * of instructions that directly references a `this` IRVariable. In this + * case, `i.getResultLanguageType()` gives an unknown type, whereas the + * predicate gives the expected type (i.e., a potentially cv-qualified + * type `A*` where `A` is the declaring type of the member function that + * contains `i`). + */ +cached +CppType getResultLanguageType(Instruction i) { + if i.(VariableAddressInstruction).getIRVariable() instanceof IRThisVariable + then + if i.isGLValue() + then result = getThisType(i.getEnclosingFunction(), true) + else result = getThisType(i.getEnclosingFunction(), false) + else result = i.getResultLanguageType() +} + +/** + * Gets the C++ type of the operand `operand`. + * This is equivalent to the type of the operand's defining instruction. + * + * See `getResultLanguageType` for a description of this behavior. + */ +CppType getLanguageType(Operand operand) { result = getResultLanguageType(operand.getDef()) } + +/** + * Gets the maximum number of indirections a glvalue of type `type` can have. + * For example: + * - If `type = int`, the result is 1 + * - If `type = MyStruct`, the result is 1 + * - If `type = char*`, the result is 2 + */ +int getMaxIndirectionsForType(Type type) { + result = countIndirectionsForCppType(getTypeForGLValue(type)) +} + +private class PointerOrArrayOrReferenceType extends Cpp::DerivedType { + PointerOrArrayOrReferenceType() { + this instanceof Cpp::PointerType + or + this instanceof Cpp::ArrayType + or + this instanceof Cpp::ReferenceType + } +} + +/** + * Gets the maximum number of indirections a value of type `type` can have. + * + * Note that this predicate is intended to be called on unspecified types + * (i.e., `countIndirections(e.getUnspecifiedType())`). + */ +private int countIndirections(Type t) { + // We special case void pointers because we don't know how many indirections + // they really have. In a Glorious Future we could do a pre-analysis to figure out + // which kinds of values flows into the type and use the maximum number of + // indirections flowinginto the type. + if t instanceof Cpp::VoidPointerType + then result = 2 + else ( + result = any(Indirection ind | ind.getType() = t).getNumberOfIndirections() + or + not exists(Indirection ind | ind.getType() = t) and + result = 0 + ) +} + +/** + * Gets the maximum number of indirections a value of C++ + * type `langType` can have. + */ +int countIndirectionsForCppType(LanguageType langType) { + exists(Type type | langType.hasType(type, true) | + result = 1 + countIndirections(type.getUnspecifiedType()) + ) + or + exists(Type type | langType.hasType(type, false) | + result = countIndirections(type.getUnspecifiedType()) + ) +} + +/** + * A `CallInstruction` that calls an allocation function such + * as `malloc` or `operator new`. + */ +class AllocationInstruction extends CallInstruction { + AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction } +} + +/** + * An abstract class for handling indirections. + * + * Extend this class to make a type behave as a pointer for the + * purposes of dataflow. + */ +abstract class Indirection extends Type { + Type baseType; + + /** Gets the type of this indirection. */ + final Type getType() { result = this } + + /** + * Gets the number of indirections supported by this type. + * + * For example, the number of indirections of a variable `p` of type + * `int**` is `3` (i.e., `p`, `*p` and `**p`). + */ + abstract int getNumberOfIndirections(); + + /** + * Holds if `deref` is an instruction that behaves as a `LoadInstruction` + * that loads the value computed by `address`. + */ + predicate isAdditionalDereference(Instruction deref, Operand address) { none() } + + /** + * Holds if `value` is written to the address computed by `address`. + * + * `certain` is `true` if this write is guaranteed to write to the address. + */ + predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) { none() } + + /** + * Gets the base type of this indirection, after specifiers have been deeply + * stripped and typedefs have been resolved. + * + * For example, the base type of `int*&` is `int*`, and the base type of `int*` is `int`. + */ + final Type getBaseType() { result = baseType } + + /** Holds if there should be an additional taint step from `node1` to `node2`. */ + predicate isAdditionalTaintStep(Node node1, Node node2) { none() } + + /** + * Holds if the step from `opFrom` to `instrTo` should be considered a conversion + * from `opFrom` to `instrTo`. + */ + predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) { none() } +} + +private class PointerOrArrayOrReferenceTypeIndirection extends Indirection instanceof PointerOrArrayOrReferenceType +{ + PointerOrArrayOrReferenceTypeIndirection() { + baseType = PointerOrArrayOrReferenceType.super.getBaseType() + } + + override int getNumberOfIndirections() { + result = 1 + countIndirections(this.getBaseType().getUnspecifiedType()) + } +} + +private class PointerWrapperTypeIndirection extends Indirection instanceof PointerWrapper { + PointerWrapperTypeIndirection() { baseType = PointerWrapper.super.getBaseType() } + + override int getNumberOfIndirections() { + result = 1 + countIndirections(this.getBaseType().getUnspecifiedType()) + } + + override predicate isAdditionalDereference(Instruction deref, Operand address) { + exists(CallInstruction call | + operandForFullyConvertedCall(getAUse(deref), call) and + this = call.getStaticCallTarget().getClassAndName("operator*") and + address = call.getThisArgumentOperand() + ) + } +} + +private module IteratorIndirections { + import semmle.code.cpp.models.interfaces.Iterator as Interfaces + import semmle.code.cpp.models.implementations.Iterator as Iterator + import semmle.code.cpp.models.implementations.StdContainer as StdContainer + + class IteratorIndirection extends Indirection instanceof Interfaces::Iterator { + IteratorIndirection() { + not this instanceof PointerOrArrayOrReferenceTypeIndirection and + baseType = super.getValueType() + } + + override int getNumberOfIndirections() { + result = 1 + countIndirections(this.getBaseType().getUnspecifiedType()) + } + + override predicate isAdditionalDereference(Instruction deref, Operand address) { + exists(CallInstruction call | + operandForFullyConvertedCall(getAUse(deref), call) and + this = call.getStaticCallTarget().getClassAndName("operator*") and + address = call.getThisArgumentOperand() + ) + } + + override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) { + exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() | + this = call.getStaticCallTarget().getClassAndName("operator=") and + address = call.getThisArgumentOperand() and + certain = false + ) + } + + override predicate isAdditionalTaintStep(Node node1, Node node2) { + exists(CallInstruction call | + // Taint through `operator+=` and `operator-=` on iterators. + call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and + node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and + node1.(IndirectOperand).getOperand() = call.getArgumentOperand(0) and + node1.getType().getUnspecifiedType() = this + ) + } + + override predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) { + // This is a bit annoying: Consider the following snippet: + // ``` + // struct MyIterator { + // ... + // insert_iterator_by_trait operator*(); + // insert_iterator_by_trait operator=(int x); + // }; + // ... + // MyIterator it; + // ... + // *it = source(); + // ``` + // The qualifier to `operator*` will undergo prvalue-to-xvalue conversion and a + // temporary object will be created. Thus, the IR for the call to `operator=` will + // look like (simplified): + // ``` + // r1(glval) = VariableAddress[it] : + // r2(glval) = FunctionAddress[operator*] : + // r3(MyIterator) = Call[operator*] : func:r2, this:r1 + // r4(glval) = VariableAddress[#temp] : + // m1(MyIterator) = Store[#temp] : &:r4, r3 + // r5(glval) = FunctionAddress[operator=] : + // r6(glval) = FunctionAddress[source] : + // r7(int) = Call[source] : func:r6 + // r8(MyIterator) = Call[operator=] : func:r5, this:r4, 0:r7 + // ``` + // in order to properly recognize that the qualifier to the call to `operator=` accesses + // `it` we look for the store that writes to the temporary object, and use the source value + // of that store as the "address" to continue searching for the base variable `it`. + exists(StoreInstruction store, VariableInstruction var | + var = instrTo and + var.getIRVariable() instanceof IRTempVariable and + opFrom.getType() = this and + store.getSourceValueOperand() = opFrom and + store.getDestinationAddress() = var + ) + or + // A call to `operator++` or `operator--` is the iterator equivalent version of a + // pointer arithmetic instruction. + exists(CallInstruction call | + instrTo = call and + call.getStaticCallTarget() instanceof Iterator::IteratorCrementMemberOperator and + opFrom = call.getThisArgumentOperand() + ) + } + } +} + +predicate isDereference(Instruction deref, Operand address) { + any(Indirection ind).isAdditionalDereference(deref, address) + or + deref.(LoadInstruction).getSourceAddressOperand() = address +} + +predicate isWrite(Node0Impl value, Operand address, boolean certain) { + any(Indirection ind).isAdditionalWrite(value, address, certain) + or + certain = true and + ( + exists(StoreInstruction store | + value.asInstruction() = store and + address = store.getDestinationAddressOperand() + ) + or + exists(InitializeParameterInstruction init | + value.asInstruction() = init and + address = init.getAnOperand() + ) + or + exists(InitializeDynamicAllocationInstruction init | + value.asInstruction() = init and + address = init.getAllocationAddressOperand() + ) + or + exists(UninitializedInstruction uninitialized | + value.asInstruction() = uninitialized and + address = uninitialized.getAnOperand() + ) + ) +} + +predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) { + any(Indirection ind).isAdditionalConversionFlow(opFrom, instrTo) +} + +newtype TBaseSourceVariable = + // Each IR variable gets its own source variable + TBaseIRVariable(IRVariable var) or + // Each allocation gets its own source variable + TBaseCallVariable(AllocationInstruction call) + +abstract class BaseSourceVariable extends TBaseSourceVariable { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets the type of this base source variable. */ + abstract DataFlowType getType(); +} + +class BaseIRVariable extends BaseSourceVariable, TBaseIRVariable { + IRVariable var; + + IRVariable getIRVariable() { result = var } + + BaseIRVariable() { this = TBaseIRVariable(var) } + + override string toString() { result = var.toString() } + + override DataFlowType getType() { result = var.getType() } +} + +class BaseCallVariable extends BaseSourceVariable, TBaseCallVariable { + AllocationInstruction call; + + BaseCallVariable() { this = TBaseCallVariable(call) } + + AllocationInstruction getCallInstruction() { result = call } + + override string toString() { result = call.toString() } + + override DataFlowType getType() { result = call.getResultType() } +} + +/** + * Holds if the value pointed to by `operand` can potentially be + * modified be the caller. + */ +predicate isModifiableByCall(ArgumentOperand operand, int indirectionIndex) { + exists(CallInstruction call, int index, CppType type | + indirectionIndex = [1 .. countIndirectionsForCppType(type)] and + type = getLanguageType(operand) and + call.getArgumentOperand(index) = operand and + if index = -1 + then + // A qualifier is "modifiable" if: + // 1. the member function is not const specified, or + // 2. the member function is `const` specified, but returns a pointer or reference + // type that is non-const. + // + // To see why this is necessary, consider the following function: + // ``` + // struct C { + // void* data_; + // void* data() const { return data; } + // }; + // ... + // C c; + // memcpy(c.data(), source, 16) + // ``` + // the data pointed to by `c.data_` is potentially modified by the call to `memcpy` even though + // `C::data` has a const specifier. So we further place the restriction that the type returned + // by `call` should not be of the form `const T*` (for some deeply const type `T`). + if call.getStaticCallTarget() instanceof Cpp::ConstMemberFunction + then + exists(PointerOrArrayOrReferenceType resultType | + resultType = call.getResultType() and + not resultType.isDeeplyConstBelow() + ) + else any() + else + // An argument is modifiable if it's a non-const pointer or reference type. + isModifiableAt(type, indirectionIndex) + ) +} + +/** + * Holds if `t` is a pointer or reference type that supports at least `indirectionIndex` number + * of indirections, and the `indirectionIndex` indirection cannot be modfiied by passing a + * value of `t` to a function. + */ +private predicate isModifiableAtImpl(CppType cppType, int indirectionIndex) { + indirectionIndex = [1 .. countIndirectionsForCppType(cppType)] and + ( + exists(Type pointerType, Type base, Type t | + pointerType = t.getUnderlyingType() and + pointerType = any(Indirection ind).getUnderlyingType() and + cppType.hasType(t, _) and + base = getTypeImpl(pointerType, indirectionIndex) + | + // The value cannot be modified if it has a const specifier, + not base.isConst() + or + // but in the case of a class type, it may be the case that + // one of the members was modified. + exists(base.stripType().(Cpp::Class).getAField()) + ) + or + // If the `indirectionIndex`'th dereference of a type can be modified + // then so can the `indirectionIndex + 1`'th dereference. + isModifiableAtImpl(cppType, indirectionIndex - 1) + ) +} + +/** + * Holds if `t` is a type with at least `indirectionIndex` number of indirections, + * and the `indirectionIndex` indirection can be modified by passing a value of + * type `t` to a function function. + */ +bindingset[indirectionIndex] +predicate isModifiableAt(CppType cppType, int indirectionIndex) { + isModifiableAtImpl(cppType, indirectionIndex) + or + exists(PointerWrapper pw, Type t | + cppType.hasType(t, _) and + t.stripType() = pw and + not pw.pointsToConst() + ) +} + +abstract class BaseSourceVariableInstruction extends Instruction { + /** Gets the base source variable accessed by this instruction. */ + abstract BaseSourceVariable getBaseSourceVariable(); +} + +private class BaseIRVariableInstruction extends BaseSourceVariableInstruction, + VariableAddressInstruction +{ + override BaseIRVariable getBaseSourceVariable() { result.getIRVariable() = this.getIRVariable() } +} + +private class BaseAllocationInstruction extends BaseSourceVariableInstruction, AllocationInstruction +{ + override BaseCallVariable getBaseSourceVariable() { result.getCallInstruction() = this } +} + +cached +private module Cached { + private import semmle.code.cpp.models.interfaces.Iterator as Interfaces + private import semmle.code.cpp.models.implementations.Iterator as Iterator + private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO + + /** + * Holds if `next` is a instruction with a memory result that potentially + * updates the memory produced by `prev`. + */ + private predicate memorySucc(Instruction prev, Instruction next) { + prev = next.(ChiInstruction).getTotal() + or + // Phi inputs can be inexact. + prev = next.(PhiInstruction).getAnInputOperand().getAnyDef() + or + prev = next.(CopyInstruction).getSourceValue() + or + exists(ReadSideEffectInstruction read | + next = read.getPrimaryInstruction() and + isAdditionalConversionFlow(_, next) and + prev = read.getSideEffectOperand().getAnyDef() + ) + } + + /** + * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`) + * that is used for a write operation that writes the value `value`. The `memory` instruction + * represents the memory that the IR's SSA analysis determined was read by the call to `operator*`. + * + * The `numberOfLoads` integer represents the number of dereferences this write corresponds to + * on the underlying container that produced the iterator. + */ + private predicate isChiAfterIteratorDef( + Instruction memory, Operand iteratorDerefAddress, Node0Impl value, int numberOfLoads + ) { + exists( + BaseSourceVariableInstruction iteratorBase, ReadSideEffectInstruction read, + Operand iteratorAddress + | + numberOfLoads >= 0 and + isDef(_, value, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and + isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and + iteratorBase.getResultType() instanceof Interfaces::Iterator and + isDereference(iteratorAddress.getDef(), read.getArgumentDef().getAUse()) and + memory = read.getSideEffectOperand().getAnyDef() + ) + } + + private predicate isSource(Instruction instr, Operand iteratorAddress, int numberOfLoads) { + getAUse(instr) = iteratorAddress and + exists(BaseSourceVariableInstruction iteratorBase | + iteratorBase.getResultType() instanceof Interfaces::Iterator and + not iteratorBase.getResultType() instanceof Cpp::PointerType and + isUse(_, iteratorAddress, iteratorBase, numberOfLoads - 1, 0) + ) + } + + private predicate isSink(Instruction instr, CallInstruction call) { + getAUse(instr).(ArgumentOperand).getCall() = call and + // Only include operations that may modify the object that the iterator points to. + // The following is a non-exhaustive list of things that may modify the value of the + // iterator, but never the value of what the iterator points to. + // The more things we can exclude here, the faster the small dataflow-like analysis + // done by `convertsIntoArgument` will converge. + not exists(Function f | f = call.getStaticCallTarget() | + f instanceof Iterator::IteratorCrementOperator or + f instanceof Iterator::IteratorBinaryArithmeticOperator or + f instanceof Iterator::IteratorAssignArithmeticOperator or + f instanceof Iterator::IteratorCrementMemberOperator or + f instanceof Iterator::IteratorBinaryArithmeticMemberOperator or + f instanceof Iterator::IteratorAssignArithmeticMemberOperator or + f instanceof Iterator::IteratorAssignmentMemberOperator + ) + } + + private predicate convertsIntoArgumentFwd(Instruction instr) { + isSource(instr, _, _) + or + exists(Instruction prev | convertsIntoArgumentFwd(prev) | + conversionFlow(unique( | | getAUse(prev)), instr, false, _) + ) + } + + pragma[assume_small_delta] + private predicate convertsIntoArgumentRev(Instruction instr) { + convertsIntoArgumentFwd(instr) and + ( + isSink(instr, _) + or + exists(Instruction next | convertsIntoArgumentRev(next) | + conversionFlow(unique( | | getAUse(instr)), next, false, _) + ) + ) + } + + private predicate convertsIntoArgument( + Operand iteratorAddress, CallInstruction call, int numberOfLoads + ) { + exists(Instruction iteratorAddressDef | + isSource(iteratorAddressDef, iteratorAddress, numberOfLoads) and + isSink(iteratorAddressDef, call) and + convertsIntoArgumentRev(pragma[only_bind_into](iteratorAddressDef)) + ) + } + + private predicate isChiAfterIteratorArgument( + Instruction memory, Operand iteratorAddress, int numberOfLoads + ) { + // Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be + // various conversions applied to it before it becomes an argument. + // So we do a small amount of flow to find the call that the iterator is passed to. + exists(CallInstruction call | convertsIntoArgument(iteratorAddress, call, numberOfLoads) | + exists(ReadSideEffectInstruction read | + read.getPrimaryInstruction() = call and + read.getSideEffectOperand().getAnyDef() = memory + ) + or + exists(LoadInstruction load | + iteratorAddress.getDef() = load and + memory = load.getSourceValueOperand().getAnyDef() + ) + ) + } + + /** + * Holds if `iterator` is a `StoreInstruction` that stores the result of some function + * returning an iterator into an address computed started at `containerBase`. + * + * For example, given a declaration like `std::vector::iterator it = v.begin()`, + * the `iterator` will be the `StoreInstruction` generated by the write to `it`, and + * `containerBase` will be the address of `v`. + */ + private predicate isChiAfterBegin( + BaseSourceVariableInstruction containerBase, StoreInstruction iterator + ) { + exists( + CallInstruction getIterator, Iterator::GetIteratorFunction getIteratorFunction, + IO::FunctionInput input, int i + | + getIterator = iterator.getSourceValue() and + getIteratorFunction = getIterator.getStaticCallTarget() and + getIteratorFunction.getsIterator(input, _) and + isDef(_, any(Node0Impl n | n.asInstruction() = iterator), _, _, 1, 0) and + input.isParameterDerefOrQualifierObject(i) and + isUse(_, getIterator.getArgumentOperand(i), containerBase, 0, 0) + ) + } + + /** + * Holds if `iteratorAddress` is an address of an iterator that is used for + * a read operation. The `memory` instruction represents the memory that + * the IR's SSA analysis determined was read by the call to `operator*`. + * + * Finally, the `numberOfLoads` integer represents the number of dereferences + * this read corresponds to on the underlying container that produced the iterator. + */ + private predicate isChiBeforeIteratorUse( + Operand iteratorAddress, Instruction memory, int numberOfLoads + ) { + exists( + BaseSourceVariableInstruction iteratorBase, LoadInstruction load, + ReadSideEffectInstruction read, Operand iteratorDerefAddress + | + numberOfLoads >= 0 and + isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and + isUse(_, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and + iteratorBase.getResultType() instanceof Interfaces::Iterator and + load.getSourceAddressOperand() = iteratorDerefAddress and + read.getPrimaryInstruction() = load.getSourceAddress() and + memory = read.getSideEffectOperand().getAnyDef() + ) + } + + /** + * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`) + * that is used for a write operation that writes the value `value` to a container that + * created the iterator. `container` represents the base of the address of the container + * that was used to create the iterator. + */ + cached + predicate isIteratorDef( + BaseSourceVariableInstruction container, Operand iteratorDerefAddress, Node0Impl value, + int numberOfLoads, int indirectionIndex + ) { + exists(Instruction memory, Instruction begin, int upper, int ind | + isChiAfterIteratorDef(memory, iteratorDerefAddress, value, numberOfLoads) and + memorySucc*(begin, memory) and + isChiAfterBegin(container, begin) and + upper = countIndirectionsForCppType(getResultLanguageType(container)) and + ind = numberOfLoads + [1 .. upper] and + indirectionIndex = ind - (numberOfLoads + 1) + ) + } + + /** + * Holds if `iteratorAddress` is an address of an iterator that is used for a + * read operation to read a value from a container that created the iterator. + * `container` represents the base of the address of the container that was used + * to create the iterator. + */ + cached + predicate isIteratorUse( + BaseSourceVariableInstruction container, Operand iteratorAddress, int numberOfLoads, + int indirectionIndex + ) { + // Direct use + exists(Instruction begin, Instruction memory, int upper, int ind | + isChiBeforeIteratorUse(iteratorAddress, memory, numberOfLoads) and + memorySucc*(begin, memory) and + isChiAfterBegin(container, begin) and + upper = countIndirectionsForCppType(getResultLanguageType(container)) and + ind = numberOfLoads + [1 .. upper] and + indirectionIndex = ind - (numberOfLoads + 1) + ) + or + // Use through function output + exists(Instruction memory, Instruction begin, int upper, int ind | + isChiAfterIteratorArgument(memory, iteratorAddress, numberOfLoads) and + memorySucc*(begin, memory) and + isChiAfterBegin(container, begin) and + upper = countIndirectionsForCppType(getResultLanguageType(container)) and + ind = numberOfLoads + [1 .. upper] and + indirectionIndex = ind - (numberOfLoads - 1) + ) + } + + /** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */ + private predicate isConversion(Operand op) { + exists(Instruction def, Operand use | + def = op.getDef() and + use = unique( | | getAUse(def)) and + conversionFlow(use, _, false, false) + ) + } + + /** + * Holds if `op` is a use of an SSA variable rooted at `base` with `ind` number + * of indirections. + * + * `certain` is `true` if the operand is guaranteed to read the variable, and + * `indirectionIndex` specifies the number of loads required to read the variable. + */ + cached + predicate isUse( + boolean certain, Operand op, BaseSourceVariableInstruction base, int ind, int indirectionIndex + ) { + not ignoreOperand(op) and + certain = true and + exists(LanguageType type, int upper, int ind0 | + type = getLanguageType(op) and + upper = countIndirectionsForCppType(type) and + isUseImpl(op, base, ind0) and + // Don't count every conversion as their own use. Instead, only the first + // use (i.e., before any conversions are applied) will count as a use. + not isConversion(op) and + ind = ind0 + [0 .. upper] and + indirectionIndex = ind - ind0 + ) + } + + /** + * Holds if the underlying IR has a suitable instruction to represent a value + * that would otherwise need to be represented by a dedicated `OperandNode` value. + * + * Such operands do not create new `OperandNode` values, but are + * instead associated with the instruction returned by this predicate. + */ + cached + Instruction getIRRepresentationOfOperand(Operand operand) { + operand = unique( | | getAUse(result)) + } + + /** + * Holds if the underlying IR has a suitable operand to represent a value + * that would otherwise need to be represented by a dedicated `RawIndirectOperand` value. + * + * Such operands do not create new `RawIndirectOperand` values, but are + * instead associated with the operand returned by this predicate. + */ + cached + Operand getIRRepresentationOfIndirectOperand(Operand operand, int indirectionIndex) { + exists(Instruction load | + isDereference(load, operand) and + result = unique( | | getAUse(load)) and + isUseImpl(operand, _, indirectionIndex - 1) + ) + } + + /** + * Holds if the underlying IR has a suitable instruction to represent a value + * that would otherwise need to be represented by a dedicated `RawIndirectInstruction` value. + * + * Such instructions do not create new `RawIndirectOperand` values, but are + * instead associated with the instruction returned by this predicate. + */ + cached + Instruction getIRRepresentationOfIndirectInstruction(Instruction instr, int indirectionIndex) { + exists(Instruction load, Operand address | + address.getDef() = instr and + isDereference(load, address) and + isUseImpl(address, _, indirectionIndex - 1) and + result = instr + ) + } + + /** + * Holds if `operand` is a use of an SSA variable rooted at `base`, and the + * path from `base` to `operand` passes through `ind` load-like instructions. + */ + private predicate isUseImpl(Operand operand, BaseSourceVariableInstruction base, int ind) { + DataFlowImplCommon::forceCachingInSameStage() and + ind = 0 and + operand = base.getAUse() + or + exists(Operand mid, Instruction instr | + isUseImpl(mid, base, ind) and + instr = operand.getDef() and + conversionFlow(mid, instr, false, _) + ) + or + exists(int ind0 | + exists(Operand address | + isDereference(operand.getDef(), address) and + isUseImpl(address, base, ind0) + ) + or + isUseImpl(operand.getDef().(InitializeParameterInstruction).getAnOperand(), base, ind0) + | + ind0 = ind - 1 + ) + } + + /** + * Holds if `address` is an address of an SSA variable rooted at `base`, + * and `instr` is a definition of the SSA variable with `ind` number of indirections. + * + * `certain` is `true` if `instr` is guaranteed to write to the variable, and + * `indirectionIndex` specifies the number of loads required to read the variable + * after the write operation. + */ + cached + predicate isDef( + boolean certain, Node0Impl value, Operand address, BaseSourceVariableInstruction base, int ind, + int indirectionIndex + ) { + exists( + boolean writeIsCertain, boolean addressIsCertain, int ind0, CppType type, int lower, int upper + | + isWrite(value, address, writeIsCertain) and + isDefImpl(address, base, ind0, addressIsCertain) and + certain = writeIsCertain.booleanAnd(addressIsCertain) and + type = getLanguageType(address) and + upper = countIndirectionsForCppType(type) and + ind = ind0 + [lower .. upper] and + indirectionIndex = ind - (ind0 + lower) and + (if type.hasType(any(Cpp::ArrayType arrayType), true) then lower = 0 else lower = 1) + ) + } + + /** + * Holds if the address computed by `operand` is guaranteed to write + * to a specific address. + */ + private predicate isCertainAddress(Operand operand) { + operand.getDef() instanceof VariableAddressInstruction + or + operand.getType() instanceof Cpp::ReferenceType + } + + /** + * Holds if `address` is a use of an SSA variable rooted at `base`, and the + * path from `base` to `address` passes through `ind` load-like instructions. + * + * Note: Unlike `isUseImpl`, this predicate recurses through pointer-arithmetic + * instructions. + */ + private predicate isDefImpl( + Operand operand, BaseSourceVariableInstruction base, int ind, boolean certain + ) { + DataFlowImplCommon::forceCachingInSameStage() and + ind = 0 and + operand = base.getAUse() and + (if isCertainAddress(operand) then certain = true else certain = false) + or + exists(Operand mid, Instruction instr, boolean certain0, boolean isPointerArith | + isDefImpl(mid, base, ind, certain0) and + instr = operand.getDef() and + conversionFlow(mid, instr, isPointerArith, _) and + if isPointerArith = true then certain = false else certain = certain0 + ) + or + exists(Operand address, boolean certain0 | + isDereference(operand.getDef(), address) and + isDefImpl(address, base, ind - 1, certain0) + | + if isCertainAddress(operand) then certain = certain0 else certain = false + ) + or + isDefImpl(operand.getDef().(InitializeParameterInstruction).getAnOperand(), base, ind - 1, _) and + certain = true + } +} + +import Cached + +/** + * Inputs to the shared SSA library's parameterized module that is shared + * between the SSA pruning stage, and the final SSA stage. + */ +module InputSigCommon { + class BasicBlock = IRBlock; + + BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result.immediatelyDominates(bb) } + + BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() } + + class ExitBasicBlock extends IRBlock { + ExitBasicBlock() { this.getLastInstruction() instanceof ExitFunctionInstruction } + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index 9ad6dab432a..c3b8765a72a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -3,6 +3,9 @@ private import semmle.code.cpp.ir.dataflow.DataFlow private import ModelUtil private import semmle.code.cpp.models.interfaces.DataFlow private import semmle.code.cpp.models.interfaces.SideEffect +private import DataFlowUtil +private import DataFlowPrivate +private import SsaInternals as Ssa /** * Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local @@ -23,27 +26,17 @@ cached predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { operandToInstructionTaintStep(nodeFrom.asOperand(), nodeTo.asInstruction()) or - instructionToOperandTaintStep(nodeFrom.asInstruction(), nodeTo.asOperand()) -} - -private predicate instructionToOperandTaintStep(Instruction fromInstr, Operand toOperand) { - // Propagate flow from the definition of an operand to the operand, even when the overlap is inexact. - // We only do this in certain cases: - // 1. The instruction's result must not be conflated, and - // 2. The instruction's result type is one the types where we expect element-to-object flow. Currently - // this is array types and union types. This matches the other two cases of element-to-object flow in - // `DefaultTaintTracking`. - toOperand.getAnyDef() = fromInstr and - not fromInstr.isResultConflated() and - ( - fromInstr.getResultType() instanceof ArrayType or - fromInstr.getResultType() instanceof Union + modeledTaintStep(nodeFrom, nodeTo) + or + // Flow from (the indirection of) an operand of a pointer arithmetic instruction to the + // indirection of the pointer arithmetic instruction. This provides flow from `source` + // in `x[source]` to the result of the associated load instruction. + exists(PointerArithmeticInstruction pai, int indirectionIndex | + nodeHasOperand(nodeFrom, pai.getAnOperand(), pragma[only_bind_into](indirectionIndex)) and + hasInstructionAndIndex(nodeTo, pai, indirectionIndex + 1) ) or - exists(ReadSideEffectInstruction readInstr | - fromInstr = readInstr.getArgumentDef() and - toOperand = readInstr.getSideEffectOperand() - ) + any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo) } /** @@ -61,13 +54,11 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst instrTo instanceof BitwiseInstruction or instrTo instanceof PointerArithmeticInstruction - or - // The `CopyInstruction` case is also present in non-taint data flow, but - // that uses `getDef` rather than `getAnyDef`. For taint, we want flow - // from a definition of `myStruct` to a `myStruct.myField` expression. - instrTo instanceof CopyInstruction ) or + // Taint flow from an address to its dereference. + Ssa::isDereference(instrTo, opFrom) + or // Unary instructions tend to preserve enough information in practice that we // want taint to flow through. // The exception is `FieldAddressInstruction`. Together with the rules below for @@ -81,40 +72,6 @@ private predicate operandToInstructionTaintStep(Operand opFrom, Instruction inst or instrTo.(FieldAddressInstruction).getField().getDeclaringType() instanceof Union ) - or - // Flow from an element to an array or union that contains it. - instrTo.(ChiInstruction).getPartialOperand() = opFrom and - not instrTo.isResultConflated() and - exists(Type t | instrTo.getResultLanguageType().hasType(t, false) | - t instanceof Union - or - t instanceof ArrayType - ) - or - // Until we have flow through indirections across calls, we'll take flow out - // of the indirection and into the argument. - // When we get proper flow through indirections across calls, this code can be - // moved to `adjusedSink` or possibly into the `DataFlow::ExprNode` class. - exists(ReadSideEffectInstruction read | - read.getSideEffectOperand() = opFrom and - read.getArgumentDef() = instrTo - ) - or - // Until we have from through indirections across calls, we'll take flow out - // of the parameter and into its indirection. - // `InitializeIndirectionInstruction` only has a single operand: the address of the - // value whose indirection we are initializing. When initializing an indirection of a parameter `p`, - // the IR looks like this: - // ``` - // m1 = InitializeParameter[p] : &r1 - // r2 = Load[p] : r2, m1 - // m3 = InitializeIndirection[p] : &r2 - // ``` - // So by having flow from `r2` to `m3` we're enabling flow from `m1` to `m3`. This relies on the - // `LoadOperand`'s overlap being exact. - instrTo.(InitializeIndirectionInstruction).getAnOperand() = opFrom - or - modeledTaintStep(opFrom, instrTo) } /** @@ -164,16 +121,18 @@ predicate defaultImplicitTaintRead(DataFlow::Node node, DataFlow::Content c) { n predicate defaultTaintSanitizer(DataFlow::Node node) { none() } /** - * Holds if taint can flow from `instrIn` to `instrOut` through a call to a + * Holds if taint can flow from `nodeIn` to `nodeOut` through a call to a * modeled function. */ -predicate modeledTaintStep(Operand nodeIn, Instruction nodeOut) { +predicate modeledTaintStep(DataFlow::Node nodeIn, DataFlow::Node nodeOut) { + // Normal taint steps exists(CallInstruction call, TaintFunction func, FunctionInput modelIn, FunctionOutput modelOut | call.getStaticCallTarget() = func and func.hasTaintFlow(modelIn, modelOut) | - nodeIn = callInput(call, modelIn) and - nodeOut = callOutput(call, modelOut) + nodeIn = callInput(call, modelIn) and nodeOut = callOutput(call, modelOut) + or + exists(int d | nodeIn = callInput(call, modelIn, d) and nodeOut = callOutput(call, modelOut, d)) ) or // Taint flow from one argument to another and data flow from an argument to a @@ -197,12 +156,11 @@ predicate modeledTaintStep(Operand nodeIn, Instruction nodeOut) { // Taint flow from a pointer argument to an output, when the model specifies flow from the deref // to that output, but the deref is not modeled in the IR for the caller. exists( - CallInstruction call, ReadSideEffectInstruction read, Function func, FunctionInput modelIn, - FunctionOutput modelOut + CallInstruction call, DataFlow::SideEffectOperandNode indirectArgument, Function func, + FunctionInput modelIn, FunctionOutput modelOut | - read.getSideEffectOperand() = callInput(call, modelIn) and - read.getArgumentDef() = nodeIn.getDef() and - not read.getSideEffect().isResultModeled() and + indirectArgument = callInput(call, modelIn) and + indirectArgument.getAddressOperand() = nodeIn.asOperand() and call.getStaticCallTarget() = func and ( func.(DataFlowFunction).hasDataFlow(modelIn, modelOut) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll new file mode 100644 index 00000000000..aa6a43a2580 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ssa0/SsaInternals.qll @@ -0,0 +1,311 @@ +/** + * This module defines an initial SSA pruning stage that doesn't take + * indirections into account. + */ + +private import codeql.ssa.Ssa as SsaImplCommon +private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.internal.DataFlowImplCommon as DataFlowImplCommon +private import semmle.code.cpp.models.interfaces.Allocation as Alloc +private import semmle.code.cpp.models.interfaces.DataFlow as DataFlow +private import semmle.code.cpp.ir.implementation.raw.internal.SideEffects as SideEffects +private import semmle.code.cpp.ir.internal.IRCppLanguage +private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate +private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil +private import semmle.code.cpp.ir.dataflow.internal.SsaInternalsCommon + +private module SourceVariables { + class SourceVariable instanceof BaseSourceVariable { + string toString() { result = BaseSourceVariable.super.toString() } + + BaseSourceVariable getBaseVariable() { result = this } + } + + class SourceIRVariable = BaseIRVariable; + + class CallVariable = BaseCallVariable; +} + +import SourceVariables + +private newtype TDefOrUseImpl = + TDefImpl(Operand address) { isDef(_, _, address, _, _, _) } or + TUseImpl(Operand operand) { + isUse(_, operand, _, _, _) and + not isDef(true, _, operand, _, _, _) + } or + TIteratorDef(BaseSourceVariableInstruction container, Operand iteratorAddress) { + isIteratorDef(container, iteratorAddress, _, _, _) + } or + TIteratorUse(BaseSourceVariableInstruction container, Operand iteratorAddress) { + isIteratorUse(container, iteratorAddress, _, _) + } or + TFinalParameterUse(Parameter p) { + any(Indirection indirection).getType() = p.getUnspecifiedType() + } + +abstract private class DefOrUseImpl extends TDefOrUseImpl { + /** Gets a textual representation of this element. */ + abstract string toString(); + + /** Gets the block of this definition or use. */ + final IRBlock getBlock() { this.hasIndexInBlock(result, _) } + + /** Holds if this definition or use has index `index` in block `block`. */ + abstract predicate hasIndexInBlock(IRBlock block, int index); + + final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) { + this.hasIndexInBlock(block, index) and + sv = this.getSourceVariable() + } + + /** Gets the location of this element. */ + abstract Cpp::Location getLocation(); + + abstract BaseSourceVariableInstruction getBase(); + + final BaseSourceVariable getBaseSourceVariable() { + result = this.getBase().getBaseSourceVariable() + } + + /** Gets the variable that is defined or used. */ + final SourceVariable getSourceVariable() { + result.getBaseVariable() = this.getBaseSourceVariable() + } + + abstract predicate isCertain(); +} + +abstract class DefImpl extends DefOrUseImpl { + Operand address; + + Operand getAddressOperand() { result = address } + + abstract Node0Impl getValue(); + + override string toString() { result = address.toString() } + + override Cpp::Location getLocation() { result = this.getAddressOperand().getLocation() } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + this.getAddressOperand().getUse() = block.getInstruction(index) + } +} + +private class DirectDef extends DefImpl, TDefImpl { + DirectDef() { this = TDefImpl(address) } + + override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) } + + override Node0Impl getValue() { isDef(_, result, address, _, _, _) } + + override predicate isCertain() { isDef(true, _, address, _, _, _) } +} + +private class IteratorDef extends DefImpl, TIteratorDef { + BaseSourceVariableInstruction container; + + IteratorDef() { this = TIteratorDef(container, address) } + + override BaseSourceVariableInstruction getBase() { result = container } + + override Node0Impl getValue() { isIteratorDef(_, address, result, _, _) } + + override predicate isCertain() { none() } +} + +abstract class UseImpl extends DefOrUseImpl { } + +abstract private class OperandBasedUse extends UseImpl { + Operand operand; + + override string toString() { result = operand.toString() } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + operand.getUse() = block.getInstruction(index) + } + + final override Cpp::Location getLocation() { result = operand.getLocation() } +} + +private class DirectUse extends OperandBasedUse, TUseImpl { + DirectUse() { this = TUseImpl(operand) } + + override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, _) } + + override predicate isCertain() { isUse(true, operand, _, _, _) } +} + +private class IteratorUse extends OperandBasedUse, TIteratorUse { + BaseSourceVariableInstruction container; + + IteratorUse() { this = TIteratorUse(container, operand) } + + override BaseSourceVariableInstruction getBase() { result = container } + + override predicate isCertain() { none() } +} + +private class FinalParameterUse extends UseImpl, TFinalParameterUse { + Parameter p; + + FinalParameterUse() { this = TFinalParameterUse(p) } + + override string toString() { result = p.toString() } + + final override predicate hasIndexInBlock(IRBlock block, int index) { + // Ideally, this should always be a `ReturnInstruction`, but if + // someone forgets to write a `return` statement in a function + // with a non-void return type we generate an `UnreachedInstruction`. + // In this case we still want to generate flow out of such functions + // if they write to a parameter. So we pick the index of the + // `UnreachedInstruction` as the index of this use. + // Note that a function may have both a `ReturnInstruction` and an + // `UnreachedInstruction`. If that's the case this predicate will + // return multiple results. I don't think this is detrimental to + // performance, however. + exists(Instruction return | + return instanceof ReturnInstruction or + return instanceof UnreachedInstruction + | + block.getInstruction(index) = return and + return.getEnclosingFunction() = p.getFunction() + ) + } + + final override Cpp::Location getLocation() { + // Parameters can have multiple locations. When there's a unique location we use + // that one, but if multiple locations exist we default to an unknown location. + result = unique( | | p.getLocation()) + or + not exists(unique( | | p.getLocation())) and + result instanceof UnknownDefaultLocation + } + + override BaseSourceVariableInstruction getBase() { + exists(InitializeParameterInstruction init | + init.getParameter() = p and + // This is always a `VariableAddressInstruction` + result = init.getAnOperand().getDef() + ) + } + + override predicate isCertain() { any() } +} + +private module SsaInput implements SsaImplCommon::InputSig { + import InputSigCommon + import SourceVariables + + /** + * Holds if the `i`'th write in block `bb` writes to the variable `v`. + * `certain` is `true` if the write is guaranteed to overwrite the entire variable. + */ + predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) { + DataFlowImplCommon::forceCachingInSameStage() and + exists(DefImpl def | def.hasIndexInBlock(bb, i, v) | + if def.isCertain() then certain = true else certain = false + ) + } + + /** + * Holds if the `i`'th read in block `bb` reads to the variable `v`. + * `certain` is `true` if the read is guaranteed. + */ + predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) { + exists(UseImpl use | use.hasIndexInBlock(bb, i, v) | + if use.isCertain() then certain = true else certain = false + ) + } +} + +private newtype TSsaDefOrUse = + TDefOrUse(DefOrUseImpl defOrUse) { + defOrUse instanceof UseImpl + or + // If `defOrUse` is a definition we only include it if the + // SSA library concludes that it's live after the write. + exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i | + def.definesAt(sv, bb, i, _) and + defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv) + ) + } or + TPhi(PhiNode phi) + +abstract private class SsaDefOrUse extends TSsaDefOrUse { + string toString() { result = "SsaDefOrUse" } + + DefOrUseImpl asDefOrUse() { none() } + + PhiNode asPhi() { none() } + + abstract Location getLocation(); +} + +class DefOrUse extends TDefOrUse, SsaDefOrUse { + DefOrUseImpl defOrUse; + + DefOrUse() { this = TDefOrUse(defOrUse) } + + final override DefOrUseImpl asDefOrUse() { result = defOrUse } + + final override Location getLocation() { result = defOrUse.getLocation() } + + final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() } +} + +class Phi extends TPhi, SsaDefOrUse { + PhiNode phi; + + Phi() { this = TPhi(phi) } + + final override PhiNode asPhi() { result = phi } + + final override Location getLocation() { result = phi.getBasicBlock().getLocation() } +} + +class UseOrPhi extends SsaDefOrUse { + UseOrPhi() { + this.asDefOrUse() instanceof UseImpl + or + this instanceof Phi + } + + final override Location getLocation() { + result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation() + } + + override string toString() { + result = this.asDefOrUse().toString() + or + this instanceof Phi and + result = "Phi" + } +} + +class Def extends DefOrUse { + override DefImpl defOrUse; + + Operand getAddressOperand() { result = defOrUse.getAddressOperand() } + + Instruction getAddress() { result = this.getAddressOperand().getDef() } + + Node0Impl getValue() { result = defOrUse.getValue() } + + override string toString() { result = this.asDefOrUse().toString() } + + BaseSourceVariableInstruction getBase() { result = defOrUse.getBase() } + + predicate isIteratorDef() { defOrUse instanceof IteratorDef } +} + +private module SsaImpl = SsaImplCommon::Make; + +class PhiNode extends SsaImpl::DefinitionExt { + PhiNode() { + this instanceof SsaImpl::PhiNode or + this instanceof SsaImpl::PhiReadNode + } +} + +class DefinitionExt = SsaImpl::DefinitionExt; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll new file mode 100644 index 00000000000..7f96fe5e6fb --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTracking.qll @@ -0,0 +1,64 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ + +import TaintTrackingParameter::Public +private import TaintTrackingParameter::Private + +private module AddTaintDefaults implements + DataFlowInternal::FullStateConfigSig +{ + import Config + + predicate isBarrier(DataFlow::Node node) { + Config::isBarrier(node) or defaultTaintSanitizer(node) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + Config::isAdditionalFlowStep(node1, node2) or + defaultAdditionalTaintStep(node1, node2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + Config::allowImplicitRead(node, c) + or + ( + Config::isSink(node, _) or + Config::isAdditionalFlowStep(node, _) or + Config::isAdditionalFlowStep(node, _, _, _) + ) and + defaultImplicitTaintRead(node, c) + } +} + +/** + * Constructs a standard taint tracking computation. + */ +module Make implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import DataFlowInternal::DefaultState + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} + +/** + * Constructs a taint tracking computation using flow state. + */ +module MakeWithState implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll index 1a1d605bc74..19e10871a78 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/tainttracking1/TaintTrackingParameter.qll @@ -2,4 +2,5 @@ import semmle.code.cpp.ir.dataflow.internal.TaintTrackingUtil as Public module Private { import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as DataFlow + import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl as DataFlowInternal } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll index b4def7fe4ae..7b064340ffe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/Opcode.qll @@ -1082,7 +1082,8 @@ module Opcode { * See the `CallSideEffectInstruction` documentation for more details. */ class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode, - ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect { + ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect + { final override string toString() { result = "CallSideEffect" } } @@ -1092,7 +1093,8 @@ module Opcode { * See the `CallReadSideEffectInstruction` documentation for more details. */ class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, - TCallReadSideEffect { + TCallReadSideEffect + { final override string toString() { result = "CallReadSideEffect" } } @@ -1102,7 +1104,8 @@ module Opcode { * See the `IndirectReadSideEffectInstruction` documentation for more details. */ class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode, - TIndirectReadSideEffect { + TIndirectReadSideEffect + { final override string toString() { result = "IndirectReadSideEffect" } } @@ -1112,7 +1115,8 @@ module Opcode { * See the `IndirectMustWriteSideEffectInstruction` documentation for more details. */ class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, - TIndirectMustWriteSideEffect { + TIndirectMustWriteSideEffect + { final override string toString() { result = "IndirectMustWriteSideEffect" } } @@ -1122,7 +1126,8 @@ module Opcode { * See the `IndirectMayWriteSideEffectInstruction` documentation for more details. */ class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, - MayWriteOpcode, TIndirectMayWriteSideEffect { + MayWriteOpcode, TIndirectMayWriteSideEffect + { final override string toString() { result = "IndirectMayWriteSideEffect" } } @@ -1132,7 +1137,8 @@ module Opcode { * See the `BufferReadSideEffectInstruction` documentation for more details. */ class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode, - TBufferReadSideEffect { + TBufferReadSideEffect + { final override string toString() { result = "BufferReadSideEffect" } } @@ -1142,7 +1148,8 @@ module Opcode { * See the `BufferMustWriteSideEffectInstruction` documentation for more details. */ class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, - TBufferMustWriteSideEffect { + TBufferMustWriteSideEffect + { final override string toString() { result = "BufferMustWriteSideEffect" } } @@ -1152,7 +1159,8 @@ module Opcode { * See the `BufferMayWriteSideEffectInstruction` documentation for more details. */ class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, - MayWriteOpcode, TBufferMayWriteSideEffect { + MayWriteOpcode, TBufferMayWriteSideEffect + { final override string toString() { result = "BufferMayWriteSideEffect" } } @@ -1162,7 +1170,8 @@ module Opcode { * See the `SizedBufferReadSideEffectInstruction` documentation for more details. */ class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode, - TSizedBufferReadSideEffect { + TSizedBufferReadSideEffect + { final override string toString() { result = "SizedBufferReadSideEffect" } } @@ -1172,7 +1181,8 @@ module Opcode { * See the `SizedBufferMustWriteSideEffectInstruction` documentation for more details. */ class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, - TSizedBufferMustWriteSideEffect { + TSizedBufferMustWriteSideEffect + { final override string toString() { result = "SizedBufferMustWriteSideEffect" } } @@ -1182,7 +1192,8 @@ module Opcode { * See the `SizedBufferMayWriteSideEffectInstruction` documentation for more details. */ class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, - MayWriteOpcode, TSizedBufferMayWriteSideEffect { + MayWriteOpcode, TSizedBufferMayWriteSideEffect + { final override string toString() { result = "SizedBufferMayWriteSideEffect" } } @@ -1192,7 +1203,8 @@ module Opcode { * See the `InitializeDynamicAllocationInstruction` documentation for more details. */ class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode, - TInitializeDynamicAllocation { + TInitializeDynamicAllocation + { final override string toString() { result = "InitializeDynamicAllocation" } } @@ -1221,7 +1233,8 @@ module Opcode { * See the `InlineAsmInstruction` documentation for more details. */ class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode, - MayReadOpcode, TInlineAsm { + MayReadOpcode, TInlineAsm + { final override string toString() { result = "InlineAsm" } final override predicate hasOperandInternal(OperandTag tag) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll index 01405b08e80..edc785dfabe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll @@ -1,6 +1,7 @@ private import IR import InstructionConsistency // module is below import IRTypeConsistency // module is in IRType.qll +import internal.IRConsistencyImports module InstructionConsistency { private import internal.InstructionImports as Imports @@ -28,7 +29,7 @@ module InstructionConsistency { PresentIRFunction() { this = TPresentIRFunction(irFunc) } override string toString() { - result = concat(Language::getIdentityString(irFunc.getFunction()), "; ") + result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ") } override Language::Location getLocation() { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index 4bd58e6b96a..c1743acdbae 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -87,22 +87,6 @@ class Operand extends TStageOperand { this.getDefinitionOverlap() instanceof MustExactlyOverlap } - /** - * DEPRECATED: renamed to `getUse`. - * - * Gets the `Instruction` that consumes this operand. - */ - deprecated final Instruction getUseInstruction() { result = this.getUse() } - - /** - * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this - * predicate is `getAnyDef`, but most uses of this predicate should probably - * be replaced with `getDef`. - * - * Gets the `Instruction` whose result is the value of the operand. - */ - deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } - /** * Gets the overlap relationship between the operand's definition and its use. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll index 53cdc75512b..aae12b0047a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll @@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction override Language::Location getLocation() { result = irFunc.getLocation() } - override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) } + override string getLabel() { + result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction()) + } override int getOrder() { this = diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index 0a3e0287635..4e606c1f9c5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -1,7 +1,7 @@ import AliasAnalysis +import semmle.code.cpp.Location import semmle.code.cpp.ir.internal.Overlap private import semmle.code.cpp.ir.internal.IRCppLanguage as Language -private import semmle.code.cpp.Print private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as OldSsa private import semmle.code.cpp.ir.internal.IntegerConstant as Ints @@ -246,7 +246,8 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo } class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation, - AllocationMemoryLocation { + AllocationMemoryLocation +{ EntireAllocationMemoryLocation() { this = TEntireAllocationMemoryLocation(var, isMayAccess) } final override string toStringInternal() { result = var.toString() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRConsistencyImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRConsistencyImports.qll new file mode 100644 index 00000000000..beef0075752 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/IRConsistencyImports.qll @@ -0,0 +1 @@ +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintIRImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintIRImports.qll index 46254a6e3f2..3d0270b3be5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintIRImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintIRImports.qll @@ -1 +1,2 @@ import semmle.code.cpp.ir.IRConfiguration as IRConfiguration +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll index 873a3c635f8..0fb108f0b56 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,55 @@ -private import SSAConstruction as Ssa -import Ssa::SsaConsistency +import SsaConsistency +import SSAConsistencyImports + +module SsaConsistency { + /** + * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. + */ + query predicate multipleOperandMemoryLocations( + OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText + ) { + exists(int locationCount | + locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and + locationCount > 1 and + func = operand.getEnclosingIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + + " memory accesses in function '$@': " + + strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") + ) + } + + /** + * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. + */ + query predicate missingVirtualVariableForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + not exists(location.getVirtualVariable()) and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = "Memory location has no virtual variable in function '$@'." + } + + /** + * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. + */ + query predicate multipleVirtualVariablesForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + exists(int vvarCount | + vvarCount = strictcount(location.getVirtualVariable()) and + vvarCount > 1 and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + + concat(Alias::VirtualVariable vvar | + vvar = location.getVirtualVariable() + | + vvar.toString(), ", " + ) + ")." + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistencyImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistencyImports.qll new file mode 100644 index 00000000000..b09678e0f7e --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConsistencyImports.qll @@ -0,0 +1,3 @@ +import semmle.code.cpp.ir.implementation.raw.IR as OldIR +import AliasedSSA as Alias +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index bb07e9e4dd2..233db262118 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -996,7 +996,7 @@ deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1; /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the - * `DebugSSA` module, which is then imported by PrintSSA. + * `DebugSsa` module, which is then imported by PrintSSA. */ module DebugSsa { import PhiInsertion @@ -1063,62 +1063,6 @@ private module CachedForDebugging { int maxValue() { result = 2147483647 } } -module SsaConsistency { - /** - * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. - */ - query predicate multipleOperandMemoryLocations( - OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText - ) { - exists(int locationCount | - locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and - locationCount > 1 and - func = operand.getEnclosingIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + - " memory accesses in function '$@': " + - strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") - ) - } - - /** - * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. - */ - query predicate missingVirtualVariableForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - not exists(location.getVirtualVariable()) and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = "Memory location has no virtual variable in function '$@'." - } - - /** - * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. - */ - query predicate multipleVirtualVariablesForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - exists(int vvarCount | - vvarCount = strictcount(location.getVirtualVariable()) and - vvarCount > 1 and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + - concat(Alias::VirtualVariable vvar | - vvar = location.getVirtualVariable() - | - vvar.toString(), ", " - ) + ")." - ) - } -} - -/** DEPRECATED: Alias for SsaConsistency */ -deprecated module SSAConsistency = SsaConsistency; - /** * Provides the portion of the parameterized IR interface that is used to construct the SSA stages * of the IR. The raw stage of the IR does not expose these predicates. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll index 01405b08e80..edc785dfabe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll @@ -1,6 +1,7 @@ private import IR import InstructionConsistency // module is below import IRTypeConsistency // module is in IRType.qll +import internal.IRConsistencyImports module InstructionConsistency { private import internal.InstructionImports as Imports @@ -28,7 +29,7 @@ module InstructionConsistency { PresentIRFunction() { this = TPresentIRFunction(irFunc) } override string toString() { - result = concat(Language::getIdentityString(irFunc.getFunction()), "; ") + result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ") } override Language::Location getLocation() { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll index 4bd58e6b96a..c1743acdbae 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -87,22 +87,6 @@ class Operand extends TStageOperand { this.getDefinitionOverlap() instanceof MustExactlyOverlap } - /** - * DEPRECATED: renamed to `getUse`. - * - * Gets the `Instruction` that consumes this operand. - */ - deprecated final Instruction getUseInstruction() { result = this.getUse() } - - /** - * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this - * predicate is `getAnyDef`, but most uses of this predicate should probably - * be replaced with `getDef`. - * - * Gets the `Instruction` whose result is the value of the operand. - */ - deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } - /** * Gets the overlap relationship between the operand's definition and its use. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll index 53cdc75512b..aae12b0047a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll @@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction override Language::Location getLocation() { result = irFunc.getLocation() } - override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) } + override string getLabel() { + result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction()) + } override int getOrder() { this = diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConsistencyImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConsistencyImports.qll new file mode 100644 index 00000000000..beef0075752 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConsistencyImports.qll @@ -0,0 +1 @@ +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/PrintIRImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/PrintIRImports.qll index 46254a6e3f2..3d0270b3be5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/PrintIRImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/PrintIRImports.qll @@ -1 +1,2 @@ import semmle.code.cpp.ir.IRConfiguration as IRConfiguration +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 7d015654056..473b23e8b8d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -511,7 +511,8 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect { * calls other than constructor calls. */ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, - TTranslatedArgumentExprSideEffect { + TTranslatedArgumentExprSideEffect +{ Expr arg; TranslatedArgumentExprSideEffect() { @@ -546,7 +547,8 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, * calls to non-static member functions. */ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect, - TTranslatedStructorQualifierSideEffect { + TTranslatedStructorQualifierSideEffect +{ TranslatedStructorQualifierSideEffect() { this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and index = -1 diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll index 528acf4498b..2953c9eeb1f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll @@ -34,7 +34,8 @@ abstract class TranslatedCondition extends TranslatedElement { } abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext, - TTranslatedFlexibleCondition { + TTranslatedFlexibleCondition +{ TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) } final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 03a6422b114..2b2acfb94a3 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -75,7 +75,8 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit * The IR translation of a local variable declaration within a declaration statement. */ class TranslatedAutoVariableDeclarationEntry extends TranslatedLocalVariableDeclaration, - TranslatedDeclarationEntry { + TranslatedDeclarationEntry +{ StackVariable var; TranslatedAutoVariableDeclarationEntry() { var = entry.getDeclaration() } @@ -217,7 +218,8 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio * with a dynamic initializer. */ class TranslatedStaticLocalVariableInitialization extends TranslatedElement, - TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization { + TranslatedLocalVariableDeclaration, TTranslatedStaticLocalVariableInitialization +{ IRVariableDeclarationEntry entry; StaticLocalVariable var; diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index df5a974c45b..8e228d55279 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -131,7 +131,8 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { } class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, - TTranslatedConditionValue { + TTranslatedConditionValue +{ TranslatedConditionValue() { this = TTranslatedConditionValue(expr) } override TranslatedElement getChild(int id) { id = 0 and result = this.getCondition() } @@ -326,7 +327,8 @@ class TranslatedLoad extends TranslatedValueCategoryAdjustment, TTranslatedLoad * from the AST. */ class TranslatedSyntheticTemporaryObject extends TranslatedValueCategoryAdjustment, - TTranslatedSyntheticTemporaryObject { + TTranslatedSyntheticTemporaryObject +{ TranslatedSyntheticTemporaryObject() { this = TTranslatedSyntheticTemporaryObject(expr) } override string toString() { result = "Temporary materialization of " + expr.toString() } @@ -2302,7 +2304,8 @@ class TranslatedBinaryConditionalExpr extends TranslatedConditionalExpr { * its initializer. */ class TranslatedTemporaryObjectExpr extends TranslatedNonConstantExpr, - TranslatedVariableInitialization { + TranslatedVariableInitialization +{ override TemporaryObjectExpr expr; final override predicate hasTempVariable(TempVariableTag tag, CppType type) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index b4746ae58de..d29d8c80cf5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -566,7 +566,8 @@ private TranslatedConstructorInitList getTranslatedConstructorInitList(Function * instances for constructors can actually contain initializers. */ class TranslatedConstructorInitList extends TranslatedElement, InitializationContext, - TTranslatedConstructorInitList { + TTranslatedConstructorInitList +{ Function func; TranslatedConstructorInitList() { this = TTranslatedConstructorInitList(func) } @@ -637,7 +638,8 @@ private TranslatedDestructorDestructionList getTranslatedDestructorDestructionLi * destructions. */ class TranslatedDestructorDestructionList extends TranslatedElement, - TTranslatedDestructorDestructionList { + TTranslatedDestructorDestructionList +{ Function func; TranslatedDestructorDestructionList() { this = TTranslatedDestructorDestructionList(func) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll index dde5e00361a..5a4f7977ac8 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll @@ -9,7 +9,8 @@ private import InstructionTag private import semmle.code.cpp.ir.internal.IRUtilities class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, - TTranslatedGlobalOrNamespaceVarInit, InitializationContext { + TTranslatedGlobalOrNamespaceVarInit, InitializationContext +{ GlobalOrNamespaceVariable var; TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 452c9beedb9..4cd235a52bf 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -440,7 +440,8 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati } class TranslatedConstructorInitialization extends TranslatedDirectInitialization, - StructorCallContext { + StructorCallContext +{ override ConstructorCall expr; override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -528,7 +529,8 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { * explicit element in an initializer list. */ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization, - InitializationContext, TTranslatedExplicitFieldInitialization { + InitializationContext, TTranslatedExplicitFieldInitialization +{ Expr expr; TranslatedExplicitFieldInitialization() { @@ -565,7 +567,8 @@ private string getZeroValue(Type type) { * corresponding element in the initializer list. */ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, - TTranslatedFieldValueInitialization { + TTranslatedFieldValueInitialization +{ TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -700,7 +703,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement { * an explicit element in an initializer list. */ class TranslatedExplicitElementInitialization extends TranslatedElementInitialization, - TTranslatedExplicitElementInitialization, InitializationContext { + TTranslatedExplicitElementInitialization, InitializationContext +{ int elementIndex; TranslatedExplicitElementInitialization() { @@ -737,7 +741,8 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ * elements without corresponding elements in the initializer list. */ class TranslatedElementValueInitialization extends TranslatedElementInitialization, - TTranslatedElementValueInitialization { + TTranslatedElementValueInitialization +{ int elementIndex; int elementCount; @@ -881,7 +886,8 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru * Represents a call to a delegating or base class constructor from within a constructor. */ abstract class TranslatedConstructorCallFromConstructor extends TranslatedStructorCallFromStructor, - TTranslatedConstructorBaseInit { + TTranslatedConstructorBaseInit +{ TranslatedConstructorCallFromConstructor() { this = TTranslatedConstructorBaseInit(call) } } @@ -917,7 +923,8 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC * derived class constructor */ class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstructor, - TranslatedBaseStructorCall { + TranslatedBaseStructorCall +{ TranslatedConstructorBaseInit() { not call instanceof ConstructorDelegationInit } final override string toString() { result = "construct base: " + call.toString() } @@ -934,7 +941,8 @@ TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction( * derived class destructor. */ class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall, - TTranslatedDestructorBaseDestruction { + TTranslatedDestructorBaseDestruction +{ TranslatedDestructorBaseDestruction() { this = TTranslatedDestructorBaseDestruction(call) } final override string toString() { result = "destroy base: " + call.toString() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index 9140620cddc..da4183ca25c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -20,7 +20,8 @@ TranslatedMicrosoftTryExceptHandler getTranslatedMicrosoftTryExceptHandler( } class TranslatedMicrosoftTryExceptHandler extends TranslatedElement, - TTranslatedMicrosoftTryExceptHandler { + TTranslatedMicrosoftTryExceptHandler +{ MicrosoftTryExceptStmt tryExcept; TranslatedMicrosoftTryExceptHandler() { this = TTranslatedMicrosoftTryExceptHandler(tryExcept) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll index 01405b08e80..edc785dfabe 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll @@ -1,6 +1,7 @@ private import IR import InstructionConsistency // module is below import IRTypeConsistency // module is in IRType.qll +import internal.IRConsistencyImports module InstructionConsistency { private import internal.InstructionImports as Imports @@ -28,7 +29,7 @@ module InstructionConsistency { PresentIRFunction() { this = TPresentIRFunction(irFunc) } override string toString() { - result = concat(Language::getIdentityString(irFunc.getFunction()), "; ") + result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ") } override Language::Location getLocation() { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index 4bd58e6b96a..c1743acdbae 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -87,22 +87,6 @@ class Operand extends TStageOperand { this.getDefinitionOverlap() instanceof MustExactlyOverlap } - /** - * DEPRECATED: renamed to `getUse`. - * - * Gets the `Instruction` that consumes this operand. - */ - deprecated final Instruction getUseInstruction() { result = this.getUse() } - - /** - * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this - * predicate is `getAnyDef`, but most uses of this predicate should probably - * be replaced with `getDef`. - * - * Gets the `Instruction` whose result is the value of the operand. - */ - deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } - /** * Gets the overlap relationship between the operand's definition and its use. */ diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll index 53cdc75512b..aae12b0047a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll @@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction override Language::Location getLocation() { result = irFunc.getLocation() } - override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) } + override string getLabel() { + result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction()) + } override int getOrder() { this = diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll new file mode 100644 index 00000000000..beef0075752 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll @@ -0,0 +1 @@ +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll index 46254a6e3f2..3d0270b3be5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll @@ -1 +1,2 @@ import semmle.code.cpp.ir.IRConfiguration as IRConfiguration +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll index 873a3c635f8..0fb108f0b56 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,55 @@ -private import SSAConstruction as Ssa -import Ssa::SsaConsistency +import SsaConsistency +import SSAConsistencyImports + +module SsaConsistency { + /** + * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. + */ + query predicate multipleOperandMemoryLocations( + OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText + ) { + exists(int locationCount | + locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and + locationCount > 1 and + func = operand.getEnclosingIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + + " memory accesses in function '$@': " + + strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") + ) + } + + /** + * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. + */ + query predicate missingVirtualVariableForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + not exists(location.getVirtualVariable()) and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = "Memory location has no virtual variable in function '$@'." + } + + /** + * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. + */ + query predicate multipleVirtualVariablesForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + exists(int vvarCount | + vvarCount = strictcount(location.getVirtualVariable()) and + vvarCount > 1 and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + + concat(Alias::VirtualVariable vvar | + vvar = location.getVirtualVariable() + | + vvar.toString(), ", " + ) + ")." + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll new file mode 100644 index 00000000000..fea07435b4b --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll @@ -0,0 +1,3 @@ +import semmle.code.cpp.ir.implementation.raw.IR as OldIR +import SimpleSSA as Alias +import semmle.code.cpp.ir.internal.IRCppLanguageDebug as LanguageDebug diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index bb07e9e4dd2..233db262118 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -996,7 +996,7 @@ deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1; /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the - * `DebugSSA` module, which is then imported by PrintSSA. + * `DebugSsa` module, which is then imported by PrintSSA. */ module DebugSsa { import PhiInsertion @@ -1063,62 +1063,6 @@ private module CachedForDebugging { int maxValue() { result = 2147483647 } } -module SsaConsistency { - /** - * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. - */ - query predicate multipleOperandMemoryLocations( - OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText - ) { - exists(int locationCount | - locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and - locationCount > 1 and - func = operand.getEnclosingIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + - " memory accesses in function '$@': " + - strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") - ) - } - - /** - * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. - */ - query predicate missingVirtualVariableForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - not exists(location.getVirtualVariable()) and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = "Memory location has no virtual variable in function '$@'." - } - - /** - * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. - */ - query predicate multipleVirtualVariablesForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - exists(int vvarCount | - vvarCount = strictcount(location.getVirtualVariable()) and - vvarCount > 1 and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + - concat(Alias::VirtualVariable vvar | - vvar = location.getVirtualVariable() - | - vvar.toString(), ", " - ) + ")." - ) - } -} - -/** DEPRECATED: Alias for SsaConsistency */ -deprecated module SSAConsistency = SsaConsistency; - /** * Provides the portion of the parameterized IR interface that is used to construct the SSA stages * of the IR. The raw stage of the IR does not expose these predicates. diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll index f3130baec4e..bace59a872b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/CppType.qll @@ -1,5 +1,4 @@ private import cpp -private import semmle.code.cpp.Print private import semmle.code.cpp.ir.implementation.IRType private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction::Raw as Raw @@ -538,12 +537,14 @@ CppType getCanonicalOpaqueType(Type tag, int byteSize) { } /** - * Gets a string that uniquely identifies an `IROpaqueType` tag. This may be different from the usual - * `toString()` of the tag in order to ensure uniqueness. + * Gets a string that uniquely identifies an `IROpaqueType` tag. Using `toString` here might + * not be sufficient to ensure uniqueness, but suffices for our current debugging purposes. + * To ensure uniqueness `getOpaqueTagIdentityString` from `semmle.code.cpp.Print` could be used, + * but that comes at the cost of importing all the `Dump` classes defined in that library. */ string getOpaqueTagIdentityString(Type tag) { hasOpaqueType(tag, _) and - result = getTypeIdentityString(tag) + result = tag.toString() } module LanguageTypeConsistency { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll index 9f60c042523..6e6c632ae3d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -1,5 +1,4 @@ private import cpp as Cpp -private import semmle.code.cpp.Print as Print private import IRUtilities private import semmle.code.cpp.ir.implementation.IRType private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction @@ -65,8 +64,6 @@ class Expr = Cpp::Expr; class Class = Cpp::Class; // Used for inheritance conversions -predicate getIdentityString = Print::getIdentityString/1; - predicate hasCaseEdge(string minValue, string maxValue) { hasCaseEdge(_, minValue, maxValue) } predicate hasPositionalArgIndex(int argIndex) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll new file mode 100644 index 00000000000..9c90adfb54b --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguageDebug.qll @@ -0,0 +1,3 @@ +private import semmle.code.cpp.Print as Print + +predicate getIdentityString = Print::getIdentityString/1; diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll index 028ab1a0370..a1fa08daa7d 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Allocation.qll @@ -389,7 +389,8 @@ private class NewArrayAllocationExpr extends AllocationExpr, NewArrayExpr { private module HeuristicAllocation { /** A class that maps an `AllocationExpr` to an `HeuristicAllocationExpr`. */ - private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr { + private class HeuristicAllocationModeled extends HeuristicAllocationExpr instanceof AllocationExpr + { override Expr getSizeExpr() { result = AllocationExpr.super.getSizeExpr() } override int getSizeMult() { result = AllocationExpr.super.getSizeMult() } @@ -406,7 +407,8 @@ private module HeuristicAllocation { } /** A class that maps an `AllocationFunction` to an `HeuristicAllocationFunction`. */ - private class HeuristicAllocationFunctionModeled extends HeuristicAllocationFunction instanceof AllocationFunction { + private class HeuristicAllocationFunctionModeled extends HeuristicAllocationFunction instanceof AllocationFunction + { override int getSizeArg() { result = AllocationFunction.super.getSizeArg() } override int getSizeMult() { result = AllocationFunction.super.getSizeMult() } @@ -430,7 +432,8 @@ private module HeuristicAllocation { * 2. The function must return a pointer type * 3. There must be a unique parameter of unsigned integral type. */ - private class HeuristicAllocationFunctionByName extends HeuristicAllocationFunction instanceof Function { + private class HeuristicAllocationFunctionByName extends HeuristicAllocationFunction instanceof Function + { int sizeArg; HeuristicAllocationFunctionByName() { diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll index 6cf642bd4cb..4415dd0c3fc 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/GetDelim.qll @@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.FlowSource * The standard functions `getdelim`, `getwdelim` and the glibc variant `__getdelim`. */ private class GetDelimFunction extends TaintFunction, AliasFunction, SideEffectFunction, - RemoteFlowSourceFunction { + RemoteFlowSourceFunction +{ GetDelimFunction() { this.hasGlobalName(["getdelim", "getwdelim", "__getdelim"]) } override predicate hasTaintFlow(FunctionInput i, FunctionOutput o) { diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll index b89eb2c1f14..011818c71f4 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll @@ -14,7 +14,8 @@ import semmle.code.cpp.models.interfaces.FlowSource * The standard functions `fgets` and `fgetws`. */ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction, - SideEffectFunction, RemoteFlowSourceFunction { + SideEffectFunction, RemoteFlowSourceFunction +{ FgetsFunction() { // fgets(str, num, stream) // fgetws(wstr, num, stream) @@ -69,7 +70,8 @@ private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFuncti * The standard functions `gets`. */ private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction, - SideEffectFunction, LocalFlowSourceFunction { + SideEffectFunction, LocalFlowSourceFunction +{ GetsFunction() { // gets(str) this.hasGlobalOrStdOrBslName("gets") @@ -97,10 +99,11 @@ private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunctio } override predicate hasLocalFlowSource(FunctionOutput output, string description) { - output.isParameterDeref(0) and - description = "string read by " + this.getName() - or - output.isReturnValue() and + ( + output.isParameterDeref(0) or + output.isReturnValue() or + output.isReturnValueDeref() + ) and description = "string read by " + this.getName() } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/IdentityFunction.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/IdentityFunction.qll index 60afd2b25ef..f07e990dc16 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/IdentityFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/IdentityFunction.qll @@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.SideEffect * The standard function templates `std::move` and `std::forward`. */ private class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction, - FunctionTemplateInstantiation { + FunctionTemplateInstantiation +{ IdentityFunction() { this.hasQualifiedName("std", ["move", "forward"]) } override predicate hasOnlySpecificReadSideEffects() { any() } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll index 93b64c343bd..cafd9aeeef0 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll @@ -121,7 +121,8 @@ class IteratorCrementNonMemberOperator extends Operator { } private class IteratorCrementNonMemberOperatorModel extends IteratorCrementNonMemberOperator, - DataFlowFunction { + DataFlowFunction +{ override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input = getIteratorArgumentInput(this, 0) and output.isReturnValue() @@ -143,7 +144,8 @@ class IteratorCrementMemberOperator extends MemberFunction { } private class IteratorCrementMemberOperatorModel extends IteratorCrementMemberOperator, - DataFlowFunction, TaintFunction { + DataFlowFunction, TaintFunction +{ override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input.isQualifierAddress() and output.isReturnValue() @@ -204,7 +206,8 @@ class IteratorBinaryArithmeticMemberOperator extends MemberFunction { } private class IteratorBinaryArithmeticMemberOperatorModel extends IteratorBinaryArithmeticMemberOperator, - TaintFunction { + TaintFunction +{ override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isQualifierObject() and output.isReturnValue() @@ -258,7 +261,8 @@ class IteratorAssignArithmeticNonMemberOperator extends Operator { } private class IteratorAssignArithmeticNonMemberOperatorModel extends IteratorAssignArithmeticNonMemberOperator, - DataFlowFunction, TaintFunction { + DataFlowFunction, TaintFunction +{ override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input.isParameter(0) and output.isReturnValue() @@ -289,7 +293,8 @@ class IteratorAssignArithmeticMemberOperator extends MemberFunction { } private class IteratorAssignArithmeticMemberOperatorModel extends IteratorAssignArithmeticMemberOperator, - DataFlowFunction, TaintFunction { + DataFlowFunction, TaintFunction +{ override predicate hasDataFlow(FunctionInput input, FunctionOutput output) { input.isQualifierAddress() and output.isReturnValue() @@ -325,7 +330,8 @@ class IteratorAssignArithmeticOperator extends Function { * non-member and member versions, use `IteratorPointerDereferenceOperator`. */ class IteratorPointerDereferenceMemberOperator extends MemberFunction, TaintFunction, - IteratorReferenceFunction { + IteratorReferenceFunction +{ IteratorPointerDereferenceMemberOperator() { this.getClassAndName("operator*") instanceof Iterator } @@ -353,7 +359,8 @@ class IteratorPointerDereferenceNonMemberOperator extends Operator, IteratorRefe } private class IteratorPointerDereferenceNonMemberOperatorModel extends IteratorPointerDereferenceNonMemberOperator, - TaintFunction { + TaintFunction +{ override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input = getIteratorArgumentInput(this, 0) and output.isReturnValue() @@ -389,7 +396,8 @@ private class IteratorFieldMemberOperator extends Operator, TaintFunction { * An `operator[]` member function of an iterator class. */ private class IteratorArrayMemberOperator extends MemberFunction, TaintFunction, - IteratorReferenceFunction { + IteratorReferenceFunction +{ IteratorArrayMemberOperator() { this.getClassAndName("operator[]") instanceof Iterator } override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { @@ -418,7 +426,8 @@ class IteratorAssignmentMemberOperator extends MemberFunction { * `operator*` and use their own `operator=` to assign to the container. */ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMemberOperator, - TaintFunction { + TaintFunction +{ override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) { input.isParameterDeref(0) and output.isQualifierObject() diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll index a8d0e94f43c..2c47587f42e 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memcpy.qll @@ -15,7 +15,8 @@ import semmle.code.cpp.models.interfaces.Taint * `__builtin___memcpy_chk`. */ private class MemcpyFunction extends ArrayFunction, DataFlowFunction, SideEffectFunction, - AliasFunction { + AliasFunction +{ MemcpyFunction() { // memcpy(dest, src, num) // memmove(dest, src, num) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll index 11ef853a0bc..0d09173854c 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Memset.qll @@ -13,7 +13,8 @@ import semmle.code.cpp.models.interfaces.SideEffect * The standard function `memset` and its assorted variants */ private class MemsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, - SideEffectFunction { + SideEffectFunction +{ MemsetFunction() { this.hasGlobalOrStdOrBslName("memset") or diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll index 4efab29cabf..41bd9ae0db7 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Pure.qll @@ -8,7 +8,8 @@ import semmle.code.cpp.models.interfaces.SideEffect * guaranteed to be side-effect free. */ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, - SideEffectFunction { + SideEffectFunction +{ PureStrFunction() { this.hasGlobalOrStdOrBslName([ atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr", @@ -153,7 +154,8 @@ private class PureFunction extends TaintFunction, SideEffectFunction { * evaluation is guaranteed to be side-effect free. */ private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction, - SideEffectFunction { + SideEffectFunction +{ PureMemFunction() { this.hasGlobalOrStdOrBslName([ "memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem" diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll index 6a4dd524b86..7323df0eedc 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Recv.qll @@ -11,7 +11,8 @@ import semmle.code.cpp.models.interfaces.SideEffect /** The function `recv` and its assorted variants */ private class Recv extends AliasFunction, ArrayFunction, SideEffectFunction, - RemoteFlowSourceFunction { + RemoteFlowSourceFunction +{ Recv() { this.hasGlobalName([ "recv", // recv(socket, dest, len, flags) diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll index 9a9e02611f8..fbef5a8fcac 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Scanf.qll @@ -15,7 +15,8 @@ import semmle.code.cpp.models.interfaces.FlowSource * The `scanf` family of functions. */ abstract private class ScanfFunctionModel extends ArrayFunction, TaintFunction, AliasFunction, - SideEffectFunction { + SideEffectFunction +{ override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = this.(ScanfFunction).getFormatParameterIndex() } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll index 389ce6c5ab0..883596a8532 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/SmartPointer.qll @@ -17,6 +17,8 @@ private class SmartPtr extends Class, PointerWrapper { } override predicate pointsToConst() { this.getTemplateArgument(0).(Type).isConst() } + + override Type getBaseType() { result = this.getTemplateArgument(0) } } /** @@ -29,7 +31,8 @@ private class SmartPtr extends Class, PointerWrapper { * - `std::weak_ptr::operator*()` */ private class PointerUnwrapperFunction extends MemberFunction, TaintFunction, DataFlowFunction, - SideEffectFunction, AliasFunction { + SideEffectFunction, AliasFunction +{ PointerUnwrapperFunction() { exists(PointerWrapper wrapper | wrapper.getAnUnwrapperFunction() = this) } diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strset.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strset.qll index f4a80cbabac..e5b493cc2ee 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Strset.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Strset.qll @@ -13,7 +13,8 @@ import semmle.code.cpp.models.interfaces.SideEffect * The standard function `strset` and its assorted variants */ private class StrsetFunction extends ArrayFunction, DataFlowFunction, AliasFunction, - SideEffectFunction { + SideEffectFunction +{ StrsetFunction() { hasGlobalName([ "strset", "_strset", "_strset_l", "_wcsset", "_wcsset_l", "_mbsset", "_mbsset_l", diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/System.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/System.qll index 02a9d0d6744..de62517e5bb 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/implementations/System.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/System.qll @@ -7,7 +7,8 @@ import semmle.code.cpp.models.interfaces.CommandExecution * A function for running a command using a command interpreter. */ private class SystemFunction extends CommandExecutionFunction, ArrayFunction, AliasFunction, - SideEffectFunction { + SideEffectFunction +{ SystemFunction() { hasGlobalOrStdName("system") or // system(command) hasGlobalName("popen") or // popen(command, mode) diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll index de44913a39f..7fd36f26183 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll @@ -40,12 +40,6 @@ class FunctionInput extends TFunctionInput { */ predicate isParameter(ParameterIndex index) { none() } - /** - * Holds if this is the input value of the parameter with index `index`. - * DEPRECATED: Use `isParameter(index)` instead. - */ - deprecated final predicate isInParameter(ParameterIndex index) { this.isParameter(index) } - /** * Holds if this is the input value pointed to (through `ind` number of indirections) by a * pointer parameter to a function, or the input value referred to by a reference parameter @@ -84,16 +78,6 @@ class FunctionInput extends TFunctionInput { */ predicate isParameterDeref(ParameterIndex index) { this.isParameterDeref(index, 1) } - /** - * Holds if this is the input value pointed to by a pointer parameter to a function, or the input - * value referred to by a reference parameter to a function, where the parameter has index - * `index`. - * DEPRECATED: Use `isParameterDeref(index)` instead. - */ - deprecated final predicate isInParameterPointer(ParameterIndex index) { - this.isParameterDeref(index) - } - /** * Holds if this is the input value pointed to by the `this` pointer of an instance member * function. @@ -124,13 +108,6 @@ class FunctionInput extends TFunctionInput { */ predicate isQualifierObject() { this.isQualifierObject(1) } - /** - * Holds if this is the input value pointed to by the `this` pointer of an instance member - * function. - * DEPRECATED: Use `isQualifierObject()` instead. - */ - deprecated final predicate isInQualifier() { this.isQualifierObject() } - /** * Holds if this is the input value of the `this` pointer of an instance member function. * @@ -396,16 +373,6 @@ class FunctionOutput extends TFunctionOutput { */ predicate isParameterDeref(ParameterIndex i, int ind) { ind = 1 and this.isParameterDeref(i) } - /** - * Holds if this is the output value pointed to by a pointer parameter to a function, or the - * output value referred to by a reference parameter to a function, where the parameter has - * index `index`. - * DEPRECATED: Use `isParameterDeref(index)` instead. - */ - deprecated final predicate isOutParameterPointer(ParameterIndex index) { - this.isParameterDeref(index) - } - /** * Holds if this is the output value pointed to by the `this` pointer of an instance member * function. @@ -436,13 +403,6 @@ class FunctionOutput extends TFunctionOutput { */ predicate isQualifierObject(int ind) { ind = 1 and this.isQualifierObject() } - /** - * Holds if this is the output value pointed to by the `this` pointer of an instance member - * function. - * DEPRECATED: Use `isQualifierObject()` instead. - */ - deprecated final predicate isOutQualifier() { this.isQualifierObject() } - /** * Holds if this is the value returned by a function. * @@ -462,12 +422,6 @@ class FunctionOutput extends TFunctionOutput { */ predicate isReturnValue() { none() } - /** - * Holds if this is the value returned by a function. - * DEPRECATED: Use `isReturnValue()` instead. - */ - deprecated final predicate isOutReturnValue() { this.isReturnValue() } - /** * Holds if this is the output value pointed to by the return value of a function, if the function * returns a pointer, or the output value referred to by the return value of a function, if the @@ -508,14 +462,6 @@ class FunctionOutput extends TFunctionOutput { */ predicate isReturnValueDeref(int ind) { ind = 1 and this.isReturnValueDeref() } - /** - * Holds if this is the output value pointed to by the return value of a function, if the function - * returns a pointer, or the output value referred to by the return value of a function, if the - * function returns a reference. - * DEPRECATED: Use `isReturnValueDeref()` instead. - */ - deprecated final predicate isOutReturnPointer() { this.isReturnValueDeref() } - /** * Holds if `i >= 0` and `isParameterDeref(i, ind)` holds for this is the value, or * if `i = -1` and `isQualifierObject(ind)` holds for this value. diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/PointerWrapper.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/PointerWrapper.qll index 8948aee424b..26d83039a81 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/PointerWrapper.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/PointerWrapper.qll @@ -14,4 +14,7 @@ abstract class PointerWrapper extends Class { /** Holds if the type of the data that is pointed to by this pointer wrapper is `const`. */ abstract predicate pointsToConst(); + + /** Gets the type pointed to by this pointer wrapper type. */ + abstract Type getBaseType(); } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll index 02cd5cb7876..2503e4713d8 100644 --- a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/RangeSSA.qll @@ -96,15 +96,6 @@ class RangeSsaDefinition extends ControlFlowNodeBase { /** Whether this definition is a phi node for variable `v`. */ predicate isPhiNode(StackVariable v) { exists(RangeSsa x | x.phi_node(v, this)) } - /** - * DEPRECATED: Use isGuardPhi/4 instead - * If this definition is a phi node corresponding to a guard, - * then return the variable access and the guard. - */ - deprecated predicate isGuardPhi(VariableAccess va, Expr guard, boolean branch) { - guard_defn(va, guard, this, branch) - } - /** * If this definition is a phi node corresponding to a guard, * then return the variable guarded, the variable access and the guard. diff --git a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll index a183533534d..881c8894e3d 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/FlowSources.qll @@ -6,6 +6,7 @@ import cpp import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.IR import semmle.code.cpp.models.interfaces.FlowSource +private import semmle.code.cpp.ir.dataflow.internal.ModelUtil /** A data flow source of user input, whether local or remote. */ abstract class FlowSource extends DataFlow::Node { @@ -19,68 +20,28 @@ abstract class RemoteFlowSource extends FlowSource { } /** A data flow source of local user input. */ abstract class LocalFlowSource extends FlowSource { } -private class RemoteReturnSource extends RemoteFlowSource { +private class RemoteModelSource extends RemoteFlowSource { string sourceType; - RemoteReturnSource() { - exists(RemoteFlowSourceFunction func, CallInstruction instr, FunctionOutput output | - this.asInstruction() = instr and - instr.getStaticCallTarget() = func and + RemoteModelSource() { + exists(CallInstruction call, RemoteFlowSourceFunction func, FunctionOutput output | + call.getStaticCallTarget() = func and func.hasRemoteFlowSource(output, sourceType) and - ( - output.isReturnValue() - or - output.isReturnValueDeref() - ) + this = callOutput(call, output) ) } override string getSourceType() { result = sourceType } } -private class RemoteParameterSource extends RemoteFlowSource { +private class LocalModelSource extends LocalFlowSource { string sourceType; - RemoteParameterSource() { - exists(RemoteFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | - this.asInstruction() = instr and - instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and - func.hasRemoteFlowSource(output, sourceType) and - output.isParameterDerefOrQualifierObject(instr.getIndex()) - ) - } - - override string getSourceType() { result = sourceType } -} - -private class LocalReturnSource extends LocalFlowSource { - string sourceType; - - LocalReturnSource() { - exists(LocalFlowSourceFunction func, CallInstruction instr, FunctionOutput output | - this.asInstruction() = instr and - instr.getStaticCallTarget() = func and + LocalModelSource() { + exists(CallInstruction call, LocalFlowSourceFunction func, FunctionOutput output | + call.getStaticCallTarget() = func and func.hasLocalFlowSource(output, sourceType) and - ( - output.isReturnValue() - or - output.isReturnValueDeref() - ) - ) - } - - override string getSourceType() { result = sourceType } -} - -private class LocalParameterSource extends LocalFlowSource { - string sourceType; - - LocalParameterSource() { - exists(LocalFlowSourceFunction func, WriteSideEffectInstruction instr, FunctionOutput output | - this.asInstruction() = instr and - instr.getPrimaryInstruction().(CallInstruction).getStaticCallTarget() = func and - func.hasLocalFlowSource(output, sourceType) and - output.isParameterDerefOrQualifierObject(instr.getIndex()) + this = callOutput(call, output) ) } @@ -92,7 +53,7 @@ private class ArgvSource extends LocalFlowSource { exists(Function main, Parameter argv | main.hasGlobalName("main") and main.getParameter(1) = argv and - this.asParameter() = argv + this.asParameter(_) = argv ) } @@ -109,18 +70,10 @@ private class RemoteParameterSink extends RemoteFlowSink { string sourceType; RemoteParameterSink() { - exists(RemoteFlowSinkFunction func, FunctionInput input, CallInstruction call, int index | - func.hasRemoteFlowSink(input, sourceType) and call.getStaticCallTarget() = func - | - exists(ReadSideEffectInstruction read | - call = read.getPrimaryInstruction() and - read.getIndex() = index and - this.asOperand() = read.getSideEffectOperand() and - input.isParameterDerefOrQualifierObject(index) - ) - or - input.isParameterOrQualifierAddress(index) and - this.asOperand() = call.getArgumentOperand(index) + exists(CallInstruction call, RemoteFlowSinkFunction func, FunctionInput input | + call.getStaticCallTarget() = func and + func.hasRemoteFlowSink(input, sourceType) and + this = callInput(call, input) ) } diff --git a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll index 05a54b09385..285aba40e86 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/TaintTrackingImpl.qll @@ -591,7 +591,8 @@ deprecated library class DataSensitiveExprCall extends DataSensitiveCallExpr, Ex /** Call to a virtual function. */ deprecated library class DataSensitiveOverriddenFunctionCall extends DataSensitiveCallExpr, - FunctionCall { + FunctionCall +{ DataSensitiveOverriddenFunctionCall() { exists(getTarget().(VirtualFunction).getAnOverridingFunction()) } diff --git a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll index c9d6b6613d8..6a0841e13e2 100644 --- a/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/lib/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow module BoostorgAsio { /** @@ -357,7 +357,7 @@ module BoostorgAsio { * Abstract class for flows of protocol values to the first argument of a context * constructor. */ - abstract class SslContextCallAbstractConfig extends DataFlow::Configuration { + abstract deprecated class SslContextCallAbstractConfig extends DataFlow::Configuration { bindingset[this] SslContextCallAbstractConfig() { any() } @@ -369,10 +369,43 @@ module BoostorgAsio { } } + /** + * Signature for flows of protocol values to the first argument of a context + * constructor. + */ + signature module SslContextCallConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(DataFlow::Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + default predicate isSink(DataFlow::Node sink) { + exists(ConstructorCall cc, SslContextClass c, Expr e | e = sink.asExpr() | + c.getAContructorCall() = cc and + cc.getArgument(0) = e + ) + } + } + + /** + * Constructs a standard data flow computation for protocol values to the first argument + * of a context constructor. + */ + module SslContextCallMake { + private module C implements DataFlow::ConfigSig { + import Config + } + + import DataFlow::Make + } + /** * Any protocol value that flows to the first argument of a context constructor. */ - class SslContextCallConfig extends SslContextCallAbstractConfig { + deprecated class SslContextCallConfig extends SslContextCallAbstractConfig { SslContextCallConfig() { this = "SslContextCallConfig" } override predicate isSource(DataFlow::Node source) { @@ -383,10 +416,24 @@ module BoostorgAsio { } } + /** + * Any protocol value that flows to the first argument of a context constructor. + */ + private module SslContextCallConfig implements SslContextCallConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + } + + module SslContextCallFlow = SslContextCallMake; + /** * A banned protocol value that flows to the first argument of a context constructor. */ - class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { + deprecated class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" } override predicate isSource(DataFlow::Node source) { @@ -398,10 +445,25 @@ module BoostorgAsio { } } + /** + * A banned protocol value that flows to the first argument of a context constructor. + */ + private module SslContextCallBannedProtocolConfig implements SslContextCallConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprBannedBoostProtocol(e) + ) + } + } + + module SslContextCallBannedProtocolFlow = SslContextCallMake; + /** * A TLS 1.2 protocol value that flows to the first argument of a context constructor. */ - class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { + deprecated class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } override predicate isSource(DataFlow::Node source) { @@ -413,10 +475,25 @@ module BoostorgAsio { } } + /** + * A TLS 1.2 protocol value that flows to the first argument of a context constructor. + */ + private module SslContextCallTls12ProtocolConfig implements SslContextCallConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTls12BoostProtocol(e) + ) + } + } + + module SslContextCallTls12ProtocolFlow = SslContextCallMake; + /** * A TLS 1.3 protocol value that flows to the first argument of a context constructor. */ - class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { + deprecated class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } override predicate isSource(DataFlow::Node source) { @@ -428,10 +505,25 @@ module BoostorgAsio { } } + /** + * A TLS 1.3 protocol value that flows to the first argument of a context constructor. + */ + private module SslContextCallTls13ProtocolConfig implements SslContextCallConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTls13BoostProtocol(e) + ) + } + } + + module SslContextCallTls13ProtocolFlow = SslContextCallMake; + /** * A generic TLS protocol value that flows to the first argument of a context constructor. */ - class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { + deprecated class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" } override predicate isSource(DataFlow::Node source) { @@ -443,10 +535,25 @@ module BoostorgAsio { } } + /** + * A generic TLS protocol value that flows to the first argument of a context constructor. + */ + private module SslContextCallTlsProtocolConfig implements SslContextCallConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") and + isExprTlsBoostProtocol(e) + ) + } + } + + module SslContextCallTlsProtocolFlow = SslContextCallMake; + /** * A context constructor call that flows to a call to `SetOptions()`. */ - class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { + deprecated class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" } override predicate isSource(DataFlow::Node source) { @@ -467,10 +574,34 @@ module BoostorgAsio { } } + /** + * A context constructor call that flows to a call to `SetOptions()`. + */ + private module SslContextFlowsToSetOptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(SslContextClass c, ConstructorCall cc | + cc = source.asExpr() and + c.getAContructorCall() = cc + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc, SslSetOptionsFunction f, Variable v, VariableAccess va | + va = sink.asExpr() + | + f.getACallToThisFunction() = fc and + v.getAnAccess() = va and + va = fc.getQualifier() + ) + } + } + + module SslContextFlowsToSetOptionFlow = DataFlow::Make; + /** * An option value that flows to the first parameter of a call to `SetOptions()`. */ - class SslOptionConfig extends DataFlow::Configuration { + deprecated class SslOptionConfig extends DataFlow::Configuration { SslOptionConfig() { this = "SslOptionConfig" } override predicate isSource(DataFlow::Node source) { @@ -488,4 +619,26 @@ module BoostorgAsio { ) } } + + /** + * An option value that flows to the first parameter of a call to `SetOptions()`. + */ + private module SslOptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e | e = source.asExpr() | + e.fromSource() and + not e.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(SslSetOptionsFunction f, FunctionCall call | + sink.asExpr() = call.getArgument(0) and + f.getACallToThisFunction() = call and + not sink.getLocation().getFile().toString().matches("%/boost/asio/%") + ) + } + } + + module SslOptionFlow = DataFlow::Make; } diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md index f0364b77bab..2024538e99c 100644 --- a/cpp/ql/src/CHANGELOG.md +++ b/cpp/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.4 + +No user-facing changes. + ## 0.5.3 No user-facing changes. diff --git a/cpp/ql/src/Critical/MissingCheckScanf.ql b/cpp/ql/src/Critical/MissingCheckScanf.ql index d3171161f13..bca946641f9 100644 --- a/cpp/ql/src/Critical/MissingCheckScanf.ql +++ b/cpp/ql/src/Critical/MissingCheckScanf.ql @@ -16,7 +16,7 @@ import cpp import semmle.code.cpp.commons.Scanf import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.ValueNumbering diff --git a/cpp/ql/src/Critical/NewDelete.qll b/cpp/ql/src/Critical/NewDelete.qll index a8cfd56b653..7c0b8b72193 100644 --- a/cpp/ql/src/Critical/NewDelete.qll +++ b/cpp/ql/src/Critical/NewDelete.qll @@ -4,7 +4,7 @@ import cpp import semmle.code.cpp.controlflow.SSA -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * Holds if `alloc` is a use of `malloc` or `new`. `kind` is diff --git a/cpp/ql/src/Critical/OverflowCalculated.ql b/cpp/ql/src/Critical/OverflowCalculated.ql index d8a08cc6a69..8958da3b22f 100644 --- a/cpp/ql/src/Critical/OverflowCalculated.ql +++ b/cpp/ql/src/Critical/OverflowCalculated.ql @@ -12,7 +12,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.models.interfaces.Allocation predicate spaceProblem(FunctionCall append, string msg) { diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index 6d41281e443..39ce527e08a 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -17,7 +17,7 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.security.FlowSources -import DataFlow::PathGraph +import OverflowDestination::PathGraph /** * Holds if `fc` is a call to a copy operation where the size argument contains @@ -66,14 +66,12 @@ predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Va any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true) } -class OverflowDestinationConfig extends TaintTracking::Configuration { - OverflowDestinationConfig() { this = "OverflowDestinationConfig" } +module OverflowDestinationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof FlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof FlowSource } + predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asIndirectConvertedExpr()) } - override predicate isSink(DataFlow::Node sink) { sourceSized(_, sink.asConvertedExpr()) } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { exists(Variable checkedVar | readsVariable(node.asInstruction(), checkedVar) and hasUpperBoundsCheck(checkedVar) @@ -86,11 +84,11 @@ class OverflowDestinationConfig extends TaintTracking::Configuration { } } -from - FunctionCall fc, OverflowDestinationConfig conf, DataFlow::PathNode source, - DataFlow::PathNode sink +module OverflowDestination = TaintTracking::Make; + +from FunctionCall fc, OverflowDestination::PathNode source, OverflowDestination::PathNode sink where - conf.hasFlowPath(source, sink) and - sourceSized(fc, sink.getNode().asConvertedExpr()) + OverflowDestination::hasFlowPath(source, sink) and + sourceSized(fc, sink.getNode().asIndirectConvertedExpr()) select fc, source, sink, "To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size." diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index 63f84d78643..962d2ee89b0 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -15,6 +15,7 @@ import cpp import semmle.code.cpp.commons.Buffer +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import LoopBounds diff --git a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql index 18540ad6f02..03f622855ab 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/CastArrayPointerArithmetic.ql @@ -17,24 +17,40 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow -import DataFlow::PathGraph +import semmle.code.cpp.ir.dataflow.DataFlow +import CastToPointerArithFlow::PathGraph -class CastToPointerArithFlow extends DataFlow::Configuration { - CastToPointerArithFlow() { this = "CastToPointerArithFlow" } +Type getFullyConvertedType(DataFlow::Node node) { + result = node.asExpr().getFullyConverted().getUnspecifiedType() +} - override predicate isSource(DataFlow::Node node) { +module CastToPointerArithFlowConfig implements DataFlow::StateConfigSig { + class FlowState = Type; + + predicate isSource(DataFlow::Node node, FlowState state) { not node.asExpr() instanceof Conversion and exists(Type baseType1, Type baseType2 | hasBaseType(node.asExpr(), baseType1) and hasBaseType(node.asExpr().getConversion*(), baseType2) and introducesNewField(baseType1, baseType2) - ) + ) and + getFullyConvertedType(node) = state } - override predicate isSink(DataFlow::Node node) { - exists(PointerAddExpr pae | pae.getAnOperand() = node.asExpr()) or - exists(ArrayExpr ae | ae.getArrayBase() = node.asExpr()) + predicate isSink(DataFlow::Node node, FlowState state) { + ( + exists(PointerAddExpr pae | pae.getAnOperand() = node.asExpr()) or + exists(ArrayExpr ae | ae.getArrayBase() = node.asExpr()) + ) and + getFullyConvertedType(node) = state + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + none() } } @@ -64,10 +80,9 @@ predicate introducesNewField(Class derived, Class base) { ) } -from DataFlow::PathNode source, DataFlow::PathNode sink, CastToPointerArithFlow cfg -where - cfg.hasFlowPath(source, sink) and - source.getNode().asExpr().getFullyConverted().getUnspecifiedType() = - sink.getNode().asExpr().getFullyConverted().getUnspecifiedType() +module CastToPointerArithFlow = DataFlow::MakeWithState; + +from CastToPointerArithFlow::PathNode source, CastToPointerArithFlow::PathNode sink +where CastToPointerArithFlow::hasFlowPath(source, sink) select sink, source, sink, "This pointer arithmetic may be done with the wrong type because of $@.", source, "this cast" diff --git a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql index ff775ae6110..906aa3da61e 100644 --- a/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql +++ b/cpp/ql/src/Likely Bugs/Conversion/LossyFunctionResultCast.ql @@ -10,7 +10,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow predicate whitelist(Function f) { f.getName() = diff --git a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql index ceb1d647d8b..2b2e9f6bf8b 100644 --- a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql +++ b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.ql @@ -15,7 +15,7 @@ * external/cwe/cwe-134 */ -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.commons.Printf // For the following `...gettext` functions, we assume that @@ -55,14 +55,23 @@ predicate underscoreMacro(Expr e) { /** * Holds if `t` cannot hold a character array, directly or indirectly. */ -predicate cannotContainString(Type t) { - t.getUnspecifiedType() instanceof BuiltInType - or - t.getUnspecifiedType() instanceof IntegralOrEnumType +predicate cannotContainString(Type t, boolean isIndirect) { + isIndirect = false and + exists(Type unspecified | + unspecified = t.getUnspecifiedType() and + not unspecified instanceof UnknownType + | + unspecified instanceof BuiltInType or + unspecified instanceof IntegralOrEnumType + ) } -predicate isNonConst(DataFlow::Node node) { - exists(Expr e | e = node.asExpr() | +predicate isNonConst(DataFlow::Node node, boolean isIndirect) { + exists(Expr e | + e = node.asExpr() and isIndirect = false + or + e = node.asIndirectExpr() and isIndirect = true + | exists(FunctionCall fc | fc = e | not ( whitelistFunction(fc.getTarget(), _) or @@ -106,37 +115,45 @@ predicate isNonConst(DataFlow::Node node) { ) ) or - node instanceof DataFlow::DefinitionByReferenceNode + node instanceof DataFlow::DefinitionByReferenceNode and + isIndirect = true } pragma[noinline] -predicate isSanitizerNode(DataFlow::Node node) { - underscoreMacro(node.asExpr()) +predicate isBarrierNode(DataFlow::Node node) { + underscoreMacro([node.asExpr(), node.asIndirectExpr()]) or - cannotContainString(node.getType()) + exists(node.asExpr()) and + cannotContainString(node.getType(), false) } -class NonConstFlow extends TaintTracking::Configuration { - NonConstFlow() { this = "NonConstFlow" } - - override predicate isSource(DataFlow::Node source) { - isNonConst(source) and - not cannotContainString(source.getType()) - } - - override predicate isSink(DataFlow::Node sink) { - exists(FormattingFunctionCall fc | sink.asExpr() = fc.getArgument(fc.getFormatParameterIndex())) - } - - override predicate isSanitizer(DataFlow::Node node) { isSanitizerNode(node) } +predicate isSinkImpl(DataFlow::Node sink, Expr formatString) { + [sink.asExpr(), sink.asIndirectExpr()] = formatString and + exists(FormattingFunctionCall fc | formatString = fc.getArgument(fc.getFormatParameterIndex())) } +module NonConstFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(boolean isIndirect, Type t | + isNonConst(source, isIndirect) and + t = source.getType() and + not cannotContainString(t, isIndirect) + ) + } + + predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) } + + predicate isBarrier(DataFlow::Node node) { isBarrierNode(node) } +} + +module NonConstFlow = TaintTracking::Make; + from FormattingFunctionCall call, Expr formatString where call.getArgument(call.getFormatParameterIndex()) = formatString and - exists(NonConstFlow cf, DataFlow::Node sink | - cf.hasFlowTo(sink) and - sink.asExpr() = formatString + exists(DataFlow::Node sink | + NonConstFlow::hasFlowTo(sink) and + isSinkImpl(sink, formatString) ) select formatString, "The format string argument to " + call.getTarget().getName() + diff --git a/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql b/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql index 083dd998403..fe6581340de 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql +++ b/cpp/ql/src/Likely Bugs/Leap Year/Adding365DaysPerYear.ql @@ -14,8 +14,10 @@ import cpp import LeapYear -from Expr source, Expr sink, PossibleYearArithmeticOperationCheckConfiguration config -where config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(sink)) +from Expr source, Expr sink +where + PossibleYearArithmeticOperationCheckFlow::hasFlow(DataFlow::exprNode(source), + DataFlow::exprNode(sink)) select sink, "An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios.", source, source.toString() diff --git a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll index 719c16281f2..a838f4c6a0d 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll +++ b/cpp/ql/src/Likely Bugs/Leap Year/LeapYear.qll @@ -3,7 +3,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.commons.DateTime /** @@ -206,10 +206,10 @@ class ChecksForLeapYearFunctionCall extends FunctionCall { } /** - * `DataFlow::Configuration` for finding a variable access that would flow into + * Data flow configuration for finding a variable access that would flow into * a function call that includes an operation to check for leap year. */ -class LeapYearCheckConfiguration extends DataFlow::Configuration { +deprecated class LeapYearCheckConfiguration extends DataFlow::Configuration { LeapYearCheckConfiguration() { this = "LeapYearCheckConfiguration" } override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess } @@ -220,9 +220,24 @@ class LeapYearCheckConfiguration extends DataFlow::Configuration { } /** - * `DataFlow::Configuration` for finding an operation with hardcoded 365 that will flow into a `FILEINFO` field. + * Data flow configuration for finding a variable access that would flow into + * a function call that includes an operation to check for leap year. */ -class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration { +private module LeapYearCheckConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof VariableAccess } + + predicate isSink(DataFlow::Node sink) { + exists(ChecksForLeapYearFunctionCall fc | sink.asExpr() = fc.getAnArgument()) + } +} + +module LeapYearCheckFlow = DataFlow::Make; + +/** + * Data flow configuration for finding an operation with hardcoded 365 that will flow into + * a `FILEINFO` field. + */ +deprecated class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration { FiletimeYearArithmeticOperationCheckConfiguration() { this = "FiletimeYearArithmeticOperationCheckConfiguration" } @@ -246,26 +261,56 @@ class FiletimeYearArithmeticOperationCheckConfiguration extends DataFlow::Config } /** - * `DataFlow::Configuration` for finding an operation with hardcoded 365 that will flow into any known date/time field. + * Data flow configuration for finding an operation with hardcoded 365 that will flow into + * a `FILEINFO` field. */ -class PossibleYearArithmeticOperationCheckConfiguration extends DataFlow::Configuration { +private module FiletimeYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Expr e, Operation op | e = source.asExpr() | + op.getAChild*().getValue().toInt() = 365 and + op.getAChild*() = e + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr, Expr e | e = sink.asExpr() | + dds instanceof PackedTimeType and + fa.getQualifier().getUnderlyingType() = dds and + fa.isModified() and + aexpr.getAChild() = fa and + aexpr.getChild(1).getAChild*() = e + ) + } +} + +module FiletimeYearArithmeticOperationCheckFlow = + DataFlow::Make; + +/** + * Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field. + */ +deprecated class PossibleYearArithmeticOperationCheckConfiguration extends TaintTracking::Configuration +{ PossibleYearArithmeticOperationCheckConfiguration() { this = "PossibleYearArithmeticOperationCheckConfiguration" } override predicate isSource(DataFlow::Node source) { - exists(Operation op | op = source.asExpr() | + exists(Operation op | op = source.asConvertedExpr() | op.getAChild*().getValue().toInt() = 365 and - not op.getParent() instanceof Expr + ( + not op.getParent() instanceof Expr or + op.getParent() instanceof Assignment + ) ) } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { // flow from anything on the RHS of an assignment to a time/date structure to that // assignment. - exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr, Expr e | + exists(StructLikeClass dds, FieldAccess fa, Assignment aexpr, Expr e | e = node1.asExpr() and - aexpr = node2.asExpr() + fa = node2.asExpr() | (dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and fa.getQualifier().getUnderlyingType() = dds and @@ -275,7 +320,9 @@ class PossibleYearArithmeticOperationCheckConfiguration extends DataFlow::Config } override predicate isSink(DataFlow::Node sink) { - exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr | aexpr = sink.asExpr() | + exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr | + aexpr.getRValue() = sink.asConvertedExpr() + | (dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and fa.getQualifier().getUnderlyingType() = dds and fa.isModified() and @@ -283,3 +330,46 @@ class PossibleYearArithmeticOperationCheckConfiguration extends DataFlow::Config ) } } + +/** + * Taint configuration for finding an operation with hardcoded 365 that will flow into any known date/time field. + */ +private module PossibleYearArithmeticOperationCheckConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(Operation op | op = source.asConvertedExpr() | + op.getAChild*().getValue().toInt() = 365 and + ( + not op.getParent() instanceof Expr or + op.getParent() instanceof Assignment + ) + ) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + // flow from anything on the RHS of an assignment to a time/date structure to that + // assignment. + exists(StructLikeClass dds, FieldAccess fa, Assignment aexpr, Expr e | + e = node1.asExpr() and + fa = node2.asExpr() + | + (dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and + fa.getQualifier().getUnderlyingType() = dds and + aexpr.getLValue() = fa and + aexpr.getRValue().getAChild*() = e + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(StructLikeClass dds, FieldAccess fa, AssignExpr aexpr | + aexpr.getRValue() = sink.asConvertedExpr() + | + (dds instanceof PackedTimeType or dds instanceof UnpackedTimeType) and + fa.getQualifier().getUnderlyingType() = dds and + fa.isModified() and + aexpr.getLValue() = fa + ) + } +} + +module PossibleYearArithmeticOperationCheckFlow = + TaintTracking::Make; diff --git a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql index 7668ca71463..f85270d523e 100644 --- a/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql +++ b/cpp/ql/src/Likely Bugs/Leap Year/UncheckedLeapYearAfterYearModification.ql @@ -29,21 +29,18 @@ where ) or // If there is a data flow from the variable that was modified to a function that seems to check for leap year - exists( - VariableAccess source, ChecksForLeapYearFunctionCall fc, LeapYearCheckConfiguration config - | + exists(VariableAccess source, ChecksForLeapYearFunctionCall fc | source = var.getAnAccess() and - config.hasFlow(DataFlow::exprNode(source), DataFlow::exprNode(fc.getAnArgument())) + LeapYearCheckFlow::hasFlow(DataFlow::exprNode(source), + DataFlow::exprNode(fc.getAnArgument())) ) or // If there is a data flow from the field that was modified to a function that seems to check for leap year - exists( - VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc, - LeapYearCheckConfiguration config - | + exists(VariableAccess vacheck, YearFieldAccess yfacheck, ChecksForLeapYearFunctionCall fc | vacheck = var.getAnAccess() and yfacheck.getQualifier() = vacheck and - config.hasFlow(DataFlow::exprNode(yfacheck), DataFlow::exprNode(fc.getAnArgument())) + LeapYearCheckFlow::hasFlow(DataFlow::exprNode(yfacheck), + DataFlow::exprNode(fc.getAnArgument())) ) or // If there is a successor or predecessor that sets the month = 1 diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql index 8770d249497..3e7cdbe43b9 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/UsingStrcpyAsBoolean.ql @@ -12,7 +12,7 @@ import cpp import semmle.code.cpp.models.implementations.Strcpy -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * A string copy function that returns a string, rather than an error code (for diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql b/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql index 38cda5d0560..958d7aa3c55 100644 --- a/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql +++ b/cpp/ql/src/Likely Bugs/Likely Typos/inconsistentLoopDirection.ql @@ -12,7 +12,7 @@ import cpp import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * A `for` statement whose update is a crement operation on a variable. @@ -46,7 +46,7 @@ predicate illDefinedDecrForStmt( candidateDecrForStmt(forstmt, v, lesserOperand, terminalCondition) and // `initialCondition` is a value of `v` in the for loop v.getAnAssignedValue() = initialCondition and - DataFlow::localFlowStep(DataFlow::exprNode(initialCondition), DataFlow::exprNode(lesserOperand)) and + DataFlow::localFlowStep+(DataFlow::exprNode(initialCondition), DataFlow::exprNode(lesserOperand)) and // `initialCondition` < `terminalCondition` ( upperBound(initialCondition) < lowerBound(terminalCondition) and @@ -82,7 +82,8 @@ predicate illDefinedIncrForStmt( candidateIncrForStmt(forstmt, v, greaterOperand, terminalCondition) and // `initialCondition` is a value of `v` in the for loop v.getAnAssignedValue() = initialCondition and - DataFlow::localFlowStep(DataFlow::exprNode(initialCondition), DataFlow::exprNode(greaterOperand)) and + DataFlow::localFlowStep+(DataFlow::exprNode(initialCondition), + DataFlow::exprNode(greaterOperand)) and // `terminalCondition` < `initialCondition` ( upperBound(terminalCondition) < lowerBound(initialCondition) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql index f2b6c71f99d..e08f2a2a4c1 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** Gets a loop that contains `e`. */ Loop getAnEnclosingLoopOfExpr(Expr e) { result = getAnEnclosingLoopOfStmt(e.getEnclosingStmt()) } @@ -185,6 +185,19 @@ class LoopWithAlloca extends Stmt { not this.conditionReachesWithoutUpdate(var, this.(Loop).getCondition()) } + /** + * Gets an expression associated with a dataflow node. + */ + private Expr getExpr(DataFlow::Node node) { + result = node.asInstruction().getAst() + or + result = node.asOperand().getUse().getAst() + or + result = node.(DataFlow::RawIndirectInstruction).getInstruction().getAst() + or + result = node.(DataFlow::RawIndirectOperand).getOperand().getUse().getAst() + } + /** * Gets a definition that may be the most recent definition of the * controlling variable `var` before this loop. @@ -194,14 +207,10 @@ class LoopWithAlloca extends Stmt { va = var.getAnAccess() and this.conditionRequiresInequality(va, _, _) and DataFlow::localFlow(result, DataFlow::exprNode(va)) and + // Phi nodes will be preceded by nodes that represent actual definitions + not result instanceof DataFlow::SsaPhiNode and // A source is outside the loop if it's not inside the loop - not exists(Expr e | - e = result.asExpr() - or - e = result.asDefiningArgument() - | - this = getAnEnclosingLoopOfExpr(e) - ) + not exists(Expr e | e = this.getExpr(result) | this = getAnEnclosingLoopOfExpr(e)) ) } @@ -211,7 +220,11 @@ class LoopWithAlloca extends Stmt { */ private int getAControllingVarInitialValue(Variable var, DataFlow::Node source) { source = this.getAPrecedingDef(var) and - result = source.asExpr().getValue().toInt() + ( + result = this.getExpr(source).getValue().toInt() + or + result = this.getExpr(source).(Assignment).getRValue().getValue().toInt() + ) } /** diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql index 5d03ccc44ea..c23eda355c4 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.ql @@ -11,6 +11,6 @@ import cpp import NtohlArrayNoBound -from NetworkToBufferSizeConfiguration bufConfig, DataFlow::Node source, DataFlow::Node sink -where bufConfig.hasFlow(source, sink) +from DataFlow::Node source, DataFlow::Node sink +where NetworkToBufferSizeFlow::hasFlow(source, sink) select sink, "Unchecked use of data from network function $@.", source, source.toString() diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll index be780789fd5..e3b095d74dd 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll @@ -1,5 +1,5 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.valuenumbering.GlobalValueNumbering @@ -129,7 +129,7 @@ class NetworkFunctionCall extends FunctionCall { NetworkFunctionCall() { this.getTarget().hasName(["ntohd", "ntohf", "ntohl", "ntohll", "ntohs"]) } } -class NetworkToBufferSizeConfiguration extends DataFlow::Configuration { +deprecated class NetworkToBufferSizeConfiguration extends DataFlow::Configuration { NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" } override predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall } @@ -146,3 +146,19 @@ class NetworkToBufferSizeConfiguration extends DataFlow::Configuration { ) } } + +private module NetworkToBufferSizeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof NetworkFunctionCall } + + predicate isSink(DataFlow::Node node) { node.asExpr() = any(BufferAccess ba).getAccessedLength() } + + predicate isBarrier(DataFlow::Node node) { + exists(GuardCondition gc, GVN gvn | + gc.getAChild*() = gvn.getAnExpr() and + globalValueNumber(node.asExpr()) = gvn and + gc.controls(node.asExpr().getBasicBlock(), _) + ) + } +} + +module NetworkToBufferSizeFlow = DataFlow::Make; diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql b/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql index 3888e9a4ef5..feca6558ef6 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/ReturnCstrOfLocalStdString.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.controlflow.SSA -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** The `std::string` class. */ class StdString extends Class { @@ -36,20 +36,20 @@ class StdString extends Class { * Holds if `e` is a direct or indirect reference to a locally * allocated `std::string`. */ -predicate refToStdString(Expr e, ConstructorCall source) { +predicate refToStdString(DataFlow::Node node, ConstructorCall source) { exists(StdString stdstring | stdstring.getAMemberFunction() = source.getTarget() and not exists(LocalVariable v | source = v.getInitializer().getExpr() and v.isStatic() ) and - e = source + node.asExpr() = source ) or // Indirect use. - exists(Expr prev | + exists(DataFlow::Node prev | refToStdString(prev, source) and - DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e)) + DataFlow::localFlowStep(prev, node) ) } @@ -74,29 +74,30 @@ predicate flowFunction(Function fcn, int argIndex) { * Holds if `e` is a direct or indirect reference to the result of calling * `c_str` on a locally allocated `std::string`. */ -predicate refToCStr(Expr e, ConstructorCall source) { - exists(MemberFunction f, FunctionCall call | +predicate refToCStr(DataFlow::Node node, ConstructorCall source) { + exists(MemberFunction f, FunctionCall call, DataFlow::Node qualifier | f.getName() = "c_str" and - call = e and + call = node.asExpr() and call.getTarget() = f and - refToStdString(call.getQualifier(), source) + qualifier.asIndirectArgument() = call.getQualifier() and + refToStdString(qualifier, source) ) or // Indirect use. - exists(Expr prev | + exists(DataFlow::Node prev | refToCStr(prev, source) and - DataFlow::localFlowStep(DataFlow::exprNode(prev), DataFlow::exprNode(e)) + DataFlow::localFlowStep(prev, node) ) or // Some functions, such as `JNIEnv::NewStringUTF()` (from Java's JNI) // embed return a structure containing a reference to the C-style string. exists(Function f, int argIndex | flowFunction(f, argIndex) and - f = e.(Call).getTarget() and - refToCStr(e.(Call).getArgument(argIndex), source) + f = node.asExpr().(Call).getTarget() and + refToCStr(DataFlow::exprNode(node.asExpr().(Call).getArgument(argIndex)), source) ) } from ReturnStmt r, ConstructorCall source -where refToCStr(r.getExpr(), source) +where refToCStr(DataFlow::exprNode(r.getExpr()), source) select r, "Return value may contain a dangling pointer to $@.", source, "this local std::string" diff --git a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql index 814a723826c..e7baf96615e 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/TlsSettingsMisconfiguration.ql @@ -12,14 +12,12 @@ import cpp import semmle.code.cpp.security.boostorg.asio.protocols -class ExistsAnyFlowConfig extends DataFlow::Configuration { - ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } - - override predicate isSource(DataFlow::Node source) { +module ExistsAnyFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(BoostorgAsio::SslContextClass c | c.getAContructorCall() = source.asExpr()) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions | f.getACallToThisFunction() = fcSetOptions and fcSetOptions.getQualifier() = sink.asExpr() @@ -27,19 +25,18 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { } } +module ExistsAnyFlow = DataFlow::Make; + bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions | - anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(VariableAccess contextSetOptions | + ExistsAnyFlow::hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | + forall(Expr optionArgument, Expr optionArgumentSource | optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + BoostorgAsio::SslOptionFlow::hasFlow(DataFlow::exprNode(optionArgumentSource), + DataFlow::exprNode(optionArgument)) | optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag ) @@ -50,11 +47,10 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { bindingset[flag] predicate isOptionNotSet(ConstructorCall cc, int flag) { not isOptionSet(cc, flag, _) } -from - BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource, - Expr protocolSink, ConstructorCall cc, Expr e, string msg +from Expr protocolSource, Expr protocolSink, ConstructorCall cc, Expr e, string msg where - configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and + BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and ( BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and diff --git a/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql b/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql index 752db39f1f1..140cf8e2ccf 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/UseOfDeprecatedHardcodedProtocol.ql @@ -12,18 +12,15 @@ import cpp import semmle.code.cpp.security.boostorg.asio.protocols -from - BoostorgAsio::SslContextCallConfig config, Expr protocolSource, Expr protocolSink, - ConstructorCall cc +from Expr protocolSource, Expr protocolSink, ConstructorCall cc where - config.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and - not exists(BoostorgAsio::SslContextCallTlsProtocolConfig tlsConfig | - tlsConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) - ) and + BoostorgAsio::SslContextCallFlow::hasFlow(DataFlow::exprNode(protocolSource), + DataFlow::exprNode(protocolSink)) and + not BoostorgAsio::SslContextCallTlsProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and - exists(BoostorgAsio::SslContextCallBannedProtocolConfig bannedConfig | - bannedConfig.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) - ) + BoostorgAsio::SslContextCallBannedProtocolFlow::hasFlow(DataFlow::exprNode(protocolSource), + DataFlow::exprNode(protocolSink)) select protocolSink, "Usage of $@ specifying a deprecated hardcoded protocol $@ in function $@.", cc, "boost::asio::ssl::context::context", protocolSource, protocolSource.toString(), cc.getEnclosingFunction(), cc.getEnclosingFunction().toString() diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll index de7d043ad59..6d6f17daf0e 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIs.qll @@ -10,12 +10,10 @@ import ExternalAPIsSpecific /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) } /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { - any(UntrustedDataToExternalApiConfig c).hasFlow(result, this) - } + DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) } } /** DEPRECATED: Alias for UntrustedExternalApiDataNode */ diff --git a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll index db236b510b9..d2ab4f0309f 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ExternalAPIsSpecific.qll @@ -2,7 +2,7 @@ * Provides AST-specific definitions for use in the `ExternalAPI` library. */ -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.models.interfaces.DataFlow import SafeExternalAPIFunction @@ -45,7 +45,7 @@ class ExternalApiDataNode extends DataFlow::Node { deprecated class ExternalAPIDataNode = ExternalApiDataNode; /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ -class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { +deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" } override predicate isSource(DataFlow::Node source) { @@ -60,3 +60,17 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { /** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */ deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig; + +/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ +private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + exists(RemoteFlowSourceFunction remoteFlow | + remoteFlow = source.asExpr().(Call).getTarget() and + remoteFlow.hasRemoteFlowSource(_, _) + ) + } + + predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } +} + +module UntrustedDataToExternalApiFlow = TaintTracking::Make; diff --git a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql index 4860fc5356f..d16ce6376dd 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/IRUntrustedDataToExternalAPI.ql @@ -13,10 +13,10 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import ir.ExternalAPIs import semmle.code.cpp.security.FlowSources -import DataFlow::PathGraph +import UntrustedDataToExternalApiFlow::PathGraph -from UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink +where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink) select sink, source, sink, "Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() + " with untrusted data from $@.", source, source.getNode().(RemoteFlowSource).getSourceType() diff --git a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql index 01067425190..a00accd4d29 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +++ b/cpp/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql @@ -10,12 +10,12 @@ */ import cpp -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import ExternalAPIs -import DataFlow::PathGraph +import UntrustedDataToExternalApiFlow::PathGraph -from UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink +where UntrustedDataToExternalApiFlow::hasFlowPath(source, sink) select sink, source, sink, "Call to " + sink.getNode().(ExternalApiDataNode).getExternalFunction().toString() + " with untrusted data from $@.", source, source.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll index de7d043ad59..6d6f17daf0e 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIs.qll @@ -10,12 +10,10 @@ import ExternalAPIsSpecific /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::hasFlow(_, this) } /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { - any(UntrustedDataToExternalApiConfig c).hasFlow(result, this) - } + DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::hasFlow(result, this) } } /** DEPRECATED: Alias for UntrustedExternalApiDataNode */ diff --git a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll index b0fa685d1a4..4dd077f24ce 100644 --- a/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll +++ b/cpp/ql/src/Security/CWE/CWE-020/ir/ExternalAPIsSpecific.qll @@ -45,7 +45,7 @@ class ExternalApiDataNode extends DataFlow::Node { deprecated class ExternalAPIDataNode = ExternalApiDataNode; /** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ -class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { +deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfigIR" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -55,3 +55,12 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { /** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */ deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig; + +/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ +private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } +} + +module UntrustedDataToExternalApiFlow = TaintTracking::Make; diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index cbae4baad84..89d8f975680 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -19,7 +19,7 @@ import semmle.code.cpp.security.FunctionWithWrappers import semmle.code.cpp.security.FlowSources import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.TaintTracking -import DataFlow::PathGraph +import TaintedPath::PathGraph /** * A function for opening a file. @@ -47,16 +47,6 @@ class FileFunction extends FunctionWithWrappers { override predicate interestingArg(int arg) { arg = 0 } } -Expr asSinkExpr(DataFlow::Node node) { - result = - node.asOperand() - .(SideEffectOperand) - .getUse() - .(ReadSideEffectInstruction) - .getArgumentDef() - .getUnconvertedResultExpression() -} - /** * Holds for a variable that has any kind of upper-bound check anywhere in the program. * This is biased towards being inclusive and being a coarse overapproximation because @@ -80,18 +70,16 @@ predicate hasUpperBoundsCheck(Variable var) { ) } -class TaintedPathConfiguration extends TaintTracking::Configuration { - TaintedPathConfiguration() { this = "TaintedPathConfiguration" } +module TaintedPathConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof FlowSource } - override predicate isSource(DataFlow::Node node) { node instanceof FlowSource } - - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { exists(FileFunction fileFunction | - fileFunction.outermostWrapperFunctionCall(asSinkExpr(node), _) + fileFunction.outermostWrapperFunctionCall(node.asIndirectArgument(), _) ) } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.asExpr().(Call).getTarget().getUnspecifiedType() instanceof ArithmeticType or exists(LoadInstruction load, Variable checkedVar | @@ -102,13 +90,15 @@ class TaintedPathConfiguration extends TaintTracking::Configuration { } } +module TaintedPath = TaintTracking::Make; + from - FileFunction fileFunction, Expr taintedArg, FlowSource taintSource, TaintedPathConfiguration cfg, - DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, string callChain + FileFunction fileFunction, Expr taintedArg, FlowSource taintSource, + TaintedPath::PathNode sourceNode, TaintedPath::PathNode sinkNode, string callChain where - taintedArg = asSinkExpr(sinkNode.getNode()) and + taintedArg = sinkNode.getNode().asIndirectArgument() and fileFunction.outermostWrapperFunctionCall(taintedArg, callChain) and - cfg.hasFlowPath(sourceNode, sinkNode) and + TaintedPath::hasFlowPath(sourceNode, sinkNode) and taintSource = sourceNode.getNode() select taintedArg, sourceNode, sinkNode, "This argument to a file access function is derived from $@ and then passed to " + callChain + ".", diff --git a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql index dca20ef3199..c7e01e0b983 100644 --- a/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql +++ b/cpp/ql/src/Security/CWE/CWE-078/ExecTainted.ql @@ -22,73 +22,74 @@ import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.ir.dataflow.TaintTracking2 import semmle.code.cpp.security.FlowSources import semmle.code.cpp.models.implementations.Strcat -import DataFlow::PathGraph - -Expr sinkAsArgumentIndirection(DataFlow::Node sink) { - result = - sink.asOperand() - .(SideEffectOperand) - .getAddressOperand() - .getAnyDef() - .getUnconvertedResultExpression() -} +import ExecTaint::PathGraph /** - * Holds if `fst` is a string that is used in a format or concatenation function resulting in `snd`, - * and is *not* placed at the start of the resulting string. This indicates that the author did not - * expect `fst` to control what program is run if the resulting string is eventually interpreted as - * a command line, for example as an argument to `system`. + * Holds if `incoming` is a string that is used in a format or concatenation function resulting + * in `outgoing`, and is *not* placed at the start of the resulting string. This indicates that + * the author did not expect `incoming` to control what program is run if the resulting string + * is eventually interpreted as a command line, for example as an argument to `system`. */ -predicate interestingConcatenation(DataFlow::Node fst, DataFlow::Node snd) { +predicate interestingConcatenation(DataFlow::Node incoming, DataFlow::Node outgoing) { exists(FormattingFunctionCall call, int index, FormatLiteral literal | - sinkAsArgumentIndirection(fst) = call.getConversionArgument(index) and - snd.asDefiningArgument() = call.getOutputArgument(false) and + incoming.asIndirectArgument() = call.getConversionArgument(index) and + outgoing.asDefiningArgument() = call.getOutputArgument(false) and literal = call.getFormat() and not literal.getConvSpecOffset(index) = 0 and literal.getConversionChar(index) = ["s", "S"] ) or // strcat and friends - exists(StrcatFunction strcatFunc, CallInstruction call, ReadSideEffectInstruction rse | - call.getStaticCallTarget() = strcatFunc and - rse.getArgumentDef() = call.getArgument(strcatFunc.getParamSrc()) and - fst.asOperand() = rse.getSideEffectOperand() and - snd.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() = - call.getArgument(strcatFunc.getParamDest()) + exists(StrcatFunction strcatFunc, Call call | + call.getTarget() = strcatFunc and + incoming.asIndirectArgument() = call.getArgument(strcatFunc.getParamSrc()) and + outgoing.asDefiningArgument() = call.getArgument(strcatFunc.getParamDest()) ) or - exists(CallInstruction call, Operator op, ReadSideEffectInstruction rse | - call.getStaticCallTarget() = op and + exists(Call call, Operator op | + call.getTarget() = op and op.hasQualifiedName("std", "operator+") and op.getType().(UserType).hasQualifiedName("std", "basic_string") and - call.getArgument(1) = rse.getArgumentOperand().getAnyDef() and // left operand - fst.asOperand() = rse.getSideEffectOperand() and - call = snd.asInstruction() + incoming.asIndirectArgument() = call.getArgument(1) and // left operand + call = outgoing.asInstruction().getUnconvertedResultExpression() ) } -class ConcatState extends DataFlow::FlowState { - ConcatState() { this = "ConcatState" } +newtype TState = + TConcatState() or + TExecState(DataFlow::Node incoming, DataFlow::Node outgoing) { + interestingConcatenation(pragma[only_bind_into](incoming), pragma[only_bind_into](outgoing)) + } + +class ConcatState extends TConcatState { + string toString() { result = "ConcatState" } } -class ExecState extends DataFlow::FlowState { - DataFlow::Node fst; - DataFlow::Node snd; +class ExecState extends TExecState { + DataFlow::Node incoming; + DataFlow::Node outgoing; - ExecState() { - this = - "ExecState (" + fst.getLocation() + " | " + fst + ", " + snd.getLocation() + " | " + snd + ")" and - interestingConcatenation(pragma[only_bind_into](fst), pragma[only_bind_into](snd)) - } + ExecState() { this = TExecState(incoming, outgoing) } - DataFlow::Node getFstNode() { result = fst } + DataFlow::Node getIncomingNode() { result = incoming } - DataFlow::Node getSndNode() { result = snd } + DataFlow::Node getOutgoingNode() { result = outgoing } /** Holds if this is a possible `ExecState` for `sink`. */ - predicate isFeasibleForSink(DataFlow::Node sink) { - any(ExecStateConfiguration conf).hasFlow(snd, sink) - } + predicate isFeasibleForSink(DataFlow::Node sink) { ExecState::hasFlow(outgoing, sink) } + + string toString() { result = "ExecState" } +} + +predicate isSinkImpl(DataFlow::Node sink, Expr command, string callChain) { + command = sink.asIndirectArgument() and + shellCommand(command, callChain) +} + +predicate isBarrierImpl(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType + or + node.asExpr().getUnspecifiedType() instanceof FloatingPointType } /** @@ -96,67 +97,61 @@ class ExecState extends DataFlow::FlowState { * given sink. This avoids a cartesian product between all sinks and all `ExecState`s in * `ExecTaintConfiguration::isSink`. */ -class ExecStateConfiguration extends TaintTracking2::Configuration { - ExecStateConfiguration() { this = "ExecStateConfiguration" } +module ExecStateConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { any(ExecState state).getOutgoingNode() = source } - override predicate isSource(DataFlow::Node source) { - exists(ExecState state | state.getSndNode() = source) - } + predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) } - override predicate isSink(DataFlow::Node sink) { - shellCommand(sinkAsArgumentIndirection(sink), _) - } + predicate isBarrier(DataFlow::Node node) { isBarrierImpl(node) } - override predicate isSanitizerOut(DataFlow::Node node) { - isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers + predicate isBarrierOut(DataFlow::Node node) { + isSink(node) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers } } -class ExecTaintConfiguration extends TaintTracking::Configuration { - ExecTaintConfiguration() { this = "ExecTaintConfiguration" } +module ExecState = TaintTracking::Make; - override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { +module ExecTaintConfig implements DataFlow::StateConfigSig { + class FlowState = TState; + + predicate isSource(DataFlow::Node source, FlowState state) { source instanceof FlowSource and state instanceof ConcatState } - override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { - any(ExecStateConfiguration conf).isSink(sink) and + predicate isSink(DataFlow::Node sink, FlowState state) { + ExecStateConfig::isSink(sink) and state.(ExecState).isFeasibleForSink(sink) } - override predicate isAdditionalTaintStep( - DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, - DataFlow::FlowState state2 + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { state1 instanceof ConcatState and - state2.(ExecState).getFstNode() = node1 and - state2.(ExecState).getSndNode() = node2 + state2.(ExecState).getIncomingNode() = node1 and + state2.(ExecState).getOutgoingNode() = node2 } - override predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { - ( - node.asInstruction().getResultType() instanceof IntegralType - or - node.asInstruction().getResultType() instanceof FloatingPointType - ) and - state instanceof ConcatState - } + predicate isBarrier(DataFlow::Node node) { isBarrierImpl(node) } - override predicate isSanitizerOut(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + predicate isBarrierOut(DataFlow::Node node) { isSink(node, _) // Prevent duplicates along a call chain, since `shellCommand` will include wrappers } } +module ExecTaint = TaintTracking::MakeWithState; + from - ExecTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode, - string taintCause, string callChain, DataFlow::Node concatResult + ExecTaint::PathNode sourceNode, ExecTaint::PathNode sinkNode, string taintCause, string callChain, + DataFlow::Node concatResult, Expr command where - conf.hasFlowPath(sourceNode, sinkNode) and + ExecTaint::hasFlowPath(sourceNode, sinkNode) and taintCause = sourceNode.getNode().(FlowSource).getSourceType() and - shellCommand(sinkAsArgumentIndirection(sinkNode.getNode()), callChain) and - concatResult = sinkNode.getState().(ExecState).getSndNode() -select sinkAsArgumentIndirection(sinkNode.getNode()), sourceNode, sinkNode, + isSinkImpl(sinkNode.getNode(), command, callChain) and + concatResult = sinkNode.getState().(ExecState).getOutgoingNode() +select command, sourceNode, sinkNode, "This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to " + callChain + ".", sourceNode, "user input (" + taintCause + ")", concatResult, concatResult.toString() diff --git a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql index 2001b1a308c..598e242b0ef 100644 --- a/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql +++ b/cpp/ql/src/Security/CWE/CWE-129/ImproperArrayIndexValidation.ql @@ -17,7 +17,7 @@ import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.security.FlowSources import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils -import DataFlow::PathGraph +import ImproperArrayIndexValidation::PathGraph import semmle.code.cpp.security.Security predicate hasUpperBound(VariableAccess offsetExpr) { @@ -65,12 +65,10 @@ predicate predictableInstruction(Instruction instr) { predictableInstruction(instr.(UnaryInstruction).getUnary()) } -class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration { - ImproperArrayIndexValidationConfig() { this = "ImproperArrayIndexValidationConfig" } +module ImproperArrayIndexValidationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isFlowSource(source, _) } - override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { hasUpperBound(node.asExpr()) or // These barriers are ported from `DefaultTaintTracking` because this query is quite noisy @@ -107,7 +105,7 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(ArrayExpr arrayExpr, VariableAccess offsetExpr | offsetExpr = arrayExpr.getArrayOffset() and sink.asExpr() = offsetExpr and @@ -116,11 +114,13 @@ class ImproperArrayIndexValidationConfig extends TaintTracking::Configuration { } } +module ImproperArrayIndexValidation = TaintTracking::Make; + from - ImproperArrayIndexValidationConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink, + ImproperArrayIndexValidation::PathNode source, ImproperArrayIndexValidation::PathNode sink, string sourceType where - conf.hasFlowPath(source, sink) and + ImproperArrayIndexValidation::hasFlowPath(source, sink) and isFlowSource(source.getNode(), sourceType) select sink.getNode(), source, sink, "An array indexing expression depends on $@ that might be outside the bounds of the array.", diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql index 8632bdee3ef..8e817cfafa5 100644 --- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql @@ -16,7 +16,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.commons.NullTermination diff --git a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql index 964b2ff33d8..a4d37eb4875 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/ArithmeticUncontrolled.ql @@ -17,7 +17,7 @@ import semmle.code.cpp.security.Overflow import semmle.code.cpp.security.Security import semmle.code.cpp.security.FlowSources import semmle.code.cpp.ir.dataflow.TaintTracking -import DataFlow::PathGraph +import UncontrolledArith::PathGraph import Bounded /** @@ -90,10 +90,8 @@ predicate missingGuard(VariableAccess va, string effect) { ) } -class UncontrolledArithConfiguration extends TaintTracking::Configuration { - UncontrolledArithConfiguration() { this = "UncontrolledArithConfiguration" } - - override predicate isSource(DataFlow::Node source) { +module UncontrolledArithConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(RandomFunction rand, Call call | call.getTarget() = rand | rand.getFunctionOutput().isReturnValue() and source.asExpr() = call @@ -105,9 +103,9 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) } + predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { bounded(node.asExpr()) or // If this expression is part of bitwise 'and' or 'or' operation it's likely that the value is @@ -124,14 +122,16 @@ class UncontrolledArithConfiguration extends TaintTracking::Configuration { } } +module UncontrolledArith = TaintTracking::Make; + /** Gets the expression that corresponds to `node`, if any. */ Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] } from - UncontrolledArithConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink, - VariableAccess va, string effect + UncontrolledArith::PathNode source, UncontrolledArith::PathNode sink, VariableAccess va, + string effect where - config.hasFlowPath(source, sink) and + UncontrolledArith::hasFlowPath(source, sink) and sink.getNode().asExpr() = va and missingGuard(va, effect) select sink.getNode(), source, sink, diff --git a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql index 1116ceee574..4d242890528 100644 --- a/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql +++ b/cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql @@ -19,7 +19,7 @@ import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.ir.IR import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.security.FlowSources -import DataFlow::PathGraph +import TaintedAllocationSize::PathGraph /** * Holds if `alloc` is an allocation, and `tainted` is a child of it that is a @@ -46,20 +46,20 @@ predicate hasUpperBoundsCheck(Variable var) { } predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) { - readsVariable(node.asInstruction(), checkedVar) and - any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true) + exists(Instruction instr | instr = node.asOperand().getDef() | + readsVariable(instr, checkedVar) and + any(IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true) + ) } predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() } -class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { - TaintedAllocationSizeConfiguration() { this = "TaintedAllocationSizeConfiguration" } +module TaintedAllocationSizeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isFlowSource(source, _) } - override predicate isSource(DataFlow::Node source) { isFlowSource(source, _) } + predicate isSink(DataFlow::Node sink) { allocSink(_, sink) } - override predicate isSink(DataFlow::Node sink) { allocSink(_, sink) } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { exists(Expr e | e = node.asExpr() | // There can be two separate reasons for `convertedExprMightOverflow` not holding: // 1. `e` really cannot overflow. @@ -79,8 +79,8 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { e = any(PointerDiffExpr diff).getAnOperand() ) or - exists(Variable checkedVar | - readsVariable(node.asInstruction(), checkedVar) and + exists(Variable checkedVar, Instruction instr | instr = node.asOperand().getDef() | + readsVariable(instr, checkedVar) and hasUpperBoundsCheck(checkedVar) ) or @@ -95,12 +95,14 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration { } } +module TaintedAllocationSize = TaintTracking::Make; + from - Expr alloc, DataFlow::PathNode source, DataFlow::PathNode sink, string taintCause, - TaintedAllocationSizeConfiguration conf + Expr alloc, TaintedAllocationSize::PathNode source, TaintedAllocationSize::PathNode sink, + string taintCause where isFlowSource(source.getNode(), taintCause) and - conf.hasFlowPath(source, sink) and + TaintedAllocationSize::hasFlowPath(source, sink) and allocSink(alloc, sink.getNode()) select alloc, source, sink, "This allocation size is derived from $@ and might overflow.", source.getNode(), "user input (" + taintCause + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql index fec9431ce29..5f7d88e9a71 100644 --- a/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql +++ b/cpp/ql/src/Security/CWE/CWE-191/UnsignedDifferenceExpressionComparedZero.ql @@ -16,7 +16,7 @@ import semmle.code.cpp.commons.Exclusions import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * Holds if `sub` is guarded by a condition which ensures that diff --git a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql index 0d706affd0b..34d211a53ae 100644 --- a/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql +++ b/cpp/ql/src/Security/CWE/CWE-295/SSLResultConflation.ql @@ -12,7 +12,7 @@ import cpp import semmle.code.cpp.controlflow.Guards -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * A call to `SSL_get_verify_result`. @@ -25,24 +25,22 @@ class SslGetVerifyResultCall extends FunctionCall { * Data flow from a call to `SSL_get_verify_result` to a guard condition * that references the result. */ -class VerifyResultConfig extends DataFlow::Configuration { - VerifyResultConfig() { this = "VerifyResultConfig" } +module VerifyResultConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SslGetVerifyResultCall } - override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof SslGetVerifyResultCall - } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(GuardCondition guard | guard.getAChild*() = sink.asExpr()) } } +module VerifyResult = DataFlow::Make; + from - VerifyResultConfig config, DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2, - GuardCondition guard, Expr c1, Expr c2, boolean testIsTrue + DataFlow::Node source, DataFlow::Node sink1, DataFlow::Node sink2, GuardCondition guard, Expr c1, + Expr c2, boolean testIsTrue where - config.hasFlow(source, sink1) and - config.hasFlow(source, sink2) and + VerifyResult::hasFlow(source, sink1) and + VerifyResult::hasFlow(source, sink2) and guard.comparesEq(sink1.asExpr(), c1, 0, false, testIsTrue) and // (value != c1) => testIsTrue guard.comparesEq(sink2.asExpr(), c2, 0, false, testIsTrue) and // (value != c2) => testIsTrue c1.getValue().toInt() = 0 and diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql index 6858dffbfa8..d7bb69582d7 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextBufferWrite.ql @@ -16,7 +16,7 @@ import semmle.code.cpp.security.BufferWrite as BufferWrite import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.FlowSources import semmle.code.cpp.ir.dataflow.TaintTracking -import DataFlow::PathGraph +import ToBufferFlow::PathGraph /** * A buffer write into a sensitive expression. @@ -39,27 +39,29 @@ class SensitiveBufferWrite extends Expr instanceof BufferWrite::BufferWrite { * A taint flow configuration for flow from user input to a buffer write * into a sensitive expression. */ -class ToBufferConfiguration extends TaintTracking::Configuration { - ToBufferConfiguration() { this = "ToBufferConfiguration" } +module ToBufferConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof FlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof FlowSource } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } - override predicate isSink(DataFlow::Node sink) { - exists(SensitiveBufferWrite w | w.getASource() = sink.asExpr()) - } + predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _) } +} + +module ToBufferFlow = TaintTracking::Make; + +predicate isSinkImpl(DataFlow::Node sink, SensitiveBufferWrite w) { + w.getASource() = sink.asIndirectExpr() } from - ToBufferConfiguration config, SensitiveBufferWrite w, DataFlow::PathNode sourceNode, - DataFlow::PathNode sinkNode, FlowSource source + SensitiveBufferWrite w, ToBufferFlow::PathNode sourceNode, ToBufferFlow::PathNode sinkNode, + FlowSource source where - config.hasFlowPath(sourceNode, sinkNode) and + ToBufferFlow::hasFlowPath(sourceNode, sinkNode) and sourceNode.getNode() = source and - w.getASource() = sinkNode.getNode().asExpr() + isSinkImpl(sinkNode.getNode(), w) select w, sourceNode, sinkNode, "This write into buffer '" + w.getDest().toString() + "' may contain unencrypted data from $@.", source, "user input (" + source.getSourceType() + ")" diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql index 0e3ec3bf998..3c1a78b14c5 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextFileWrite.ql @@ -15,26 +15,43 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.FileWrite -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import semmle.code.cpp.dataflow.TaintTracking -import DataFlow::PathGraph +import semmle.code.cpp.ir.dataflow.TaintTracking +import FromSensitiveFlow::PathGraph /** * A taint flow configuration for flow from a sensitive expression to a `FileWrite` sink. */ -class FromSensitiveConfiguration extends TaintTracking::Configuration { - FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } +module FromSensitiveConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isSourceImpl(source, _) } - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } + predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) } - override predicate isSink(DataFlow::Node sink) { any(FileWrite w).getASource() = sink.asExpr() } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } } +module FromSensitiveFlow = TaintTracking::Make; + +predicate isSinkImpl(DataFlow::Node sink, FileWrite w, Expr dest) { + exists(Expr e | + e = [sink.asExpr(), sink.asIndirectExpr()] and + w.getASource() = e and + dest = w.getDest() and + // ignore things written with other conversion characters + not exists(string convChar | convChar = w.getSourceConvChar(e) | not convChar = ["s", "S"]) and + // exclude calls with standard streams + not dest.(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"] + ) +} + +predicate isSourceImpl(DataFlow::Node source, SensitiveExpr sensitive) { + not isFileName(globalValueNumber(sensitive)) and // file names are not passwords + source.asExpr() = sensitive +} + /** * An operation on a filename. */ @@ -61,17 +78,12 @@ predicate isFileName(GVN gvn) { } from - FromSensitiveConfiguration config, SensitiveExpr source, DataFlow::PathNode sourceNode, Expr mid, - DataFlow::PathNode midNode, FileWrite w, Expr dest + SensitiveExpr source, FromSensitiveFlow::PathNode sourceNode, FromSensitiveFlow::PathNode midNode, + FileWrite w, Expr dest where - config.hasFlowPath(sourceNode, midNode) and - sourceNode.getNode().asExpr() = source and - midNode.getNode().asExpr() = mid and - mid = w.getASource() and - dest = w.getDest() and - not dest.(VariableAccess).getTarget().getName() = ["stdin", "stdout", "stderr"] and // exclude calls with standard streams - not isFileName(globalValueNumber(source)) and // file names are not passwords - not exists(string convChar | convChar = w.getSourceConvChar(mid) | not convChar = ["s", "S"]) // ignore things written with other conversion characters + FromSensitiveFlow::hasFlowPath(sourceNode, midNode) and + isSourceImpl(sourceNode.getNode(), source) and + isSinkImpl(midNode.getNode(), w, dest) select w, sourceNode, midNode, "This write into file '" + dest.toString() + "' may contain unencrypted data from $@.", source, "this source." diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql index 86e101d6095..a0fb6bd2dac 100644 --- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql +++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql @@ -15,10 +15,10 @@ import cpp import semmle.code.cpp.security.SensitiveExprs import semmle.code.cpp.security.PrivateData -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.commons.File -import DataFlow::PathGraph +import FromSensitiveFlow::PathGraph class SourceVariable extends Variable { SourceVariable() { @@ -34,21 +34,6 @@ class SourceFunction extends Function { } } -/** - * A DataFlow node corresponding to a variable or function call that - * might contain or return a password or other sensitive information. - */ -class SourceNode extends DataFlow::Node { - SourceNode() { - this.asExpr() = any(SourceVariable sv).getInitializer().getExpr() or - this.asExpr().(VariableAccess).getTarget() = any(SourceVariable sv).(GlobalOrNamespaceVariable) or - this.asExpr().(VariableAccess).getTarget() = any(SourceVariable v | v instanceof Field) or - this.asUninitialized() instanceof SourceVariable or - this.asParameter() instanceof SourceVariable or - this.asExpr().(FunctionCall).getTarget() instanceof SourceFunction - } -} - /** * A function that sends or receives data over a network. */ @@ -217,42 +202,102 @@ class Encrypted extends Expr { } /** - * A taint flow configuration for flow from a sensitive expression to a network - * operation or encryption operation. + * Holds if `sink` is a node that represents data transmitted through a network + * operation `nsr`. */ -class FromSensitiveConfiguration extends TaintTracking::Configuration { - FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } +predicate isSinkSendRecv(DataFlow::Node sink, NetworkSendRecv nsr) { + [sink.asIndirectConvertedExpr(), sink.asConvertedExpr()] = nsr.getDataExpr().getFullyConverted() +} - override predicate isSource(DataFlow::Node source) { source instanceof SourceNode } +/** + * Holds if `sink` is a node that is encrypted by `enc`. + */ +predicate isSinkEncrypt(DataFlow::Node sink, Encrypted enc) { + sink.asConvertedExpr() = enc.getFullyConverted() +} - override predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(NetworkSendRecv nsr).getDataExpr() - or - sink.asExpr() instanceof Encrypted +/** + * Holds if `source` represents a use of a sensitive variable, or data returned by a + * function returning sensitive data. + */ +predicate isSourceImpl(DataFlow::Node source) { + exists(Expr e | + e = source.asConvertedExpr() and + e.getUnconverted().(VariableAccess).getTarget() instanceof SourceVariable and + not e.hasConversion() + ) + or + source.asExpr().(FunctionCall).getTarget() instanceof SourceFunction +} + +/** + * A taint flow configuration for flow from a sensitive expression to a network + * operation. + */ +module FromSensitiveConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isSourceImpl(source) } + + predicate isSink(DataFlow::Node sink) { isSinkSendRecv(sink, _) } + + predicate isBarrier(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType } - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { - // flow through encryption functions to the return value (in case we can reach other sinks) - node2.asExpr().(Encrypted).(FunctionCall).getAnArgument() = node1.asExpr() + predicate isBarrierIn(DataFlow::Node node) { + // As any use of a sensitive variable is a potential source, we need to block flow into + // sources to not get path duplication. + isSource(node) + } +} + +module FromSensitiveFlow = TaintTracking::Make; + +/** + * A taint flow configuration for flow from a sensitive expression to an encryption operation. + */ +module ToEncryptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { FromSensitiveFlow::hasFlow(source, _) } + + predicate isSink(DataFlow::Node sink) { isSinkEncrypt(sink, _) } + + predicate isBarrier(DataFlow::Node node) { + node.asExpr().getUnspecifiedType() instanceof IntegralType } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrierIn(DataFlow::Node node) { + // As any use of a sensitive variable is a potential source, we need to block flow into + // sources to not get path duplication. + isSource(node) + } +} + +module ToEncryptionFlow = TaintTracking::Make; + +/** + * A taint flow configuration for flow from an encryption operation to a network operation. + */ +module FromEncryptionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { isSinkEncrypt(source, _) } + + predicate isSink(DataFlow::Node sink) { FromSensitiveFlow::hasFlowTo(sink) } + + predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } } +module FromEncryptionFlow = TaintTracking::Make; + from - FromSensitiveConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink, + FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink, NetworkSendRecv networkSendRecv, string msg where // flow from sensitive -> network data - config.hasFlowPath(source, sink) and - sink.getNode().asExpr() = networkSendRecv.getDataExpr() and + FromSensitiveFlow::hasFlowPath(source, sink) and + isSinkSendRecv(sink.getNode(), networkSendRecv) and // no flow from sensitive -> evidence of encryption - not exists(DataFlow::Node encrypted | - config.hasFlow(source.getNode(), encrypted) and - encrypted.asExpr() instanceof Encrypted - ) and + not ToEncryptionFlow::hasFlow(source.getNode(), _) and + not FromEncryptionFlow::hasFlowTo(sink.getNode()) and // construct result if networkSendRecv instanceof NetworkSend then @@ -263,4 +308,4 @@ where msg = "This operation receives into '" + sink.toString() + "', which may put unencrypted sensitive data into $@." -select networkSendRecv, source, sink, msg, source, source.getNode().toString() +select networkSendRecv, source, sink, msg, source.getNode(), source.getNode().toString() diff --git a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql index f4285692811..797302be5a4 100644 --- a/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql +++ b/cpp/ql/src/Security/CWE/CWE-313/CleartextSqliteDatabase.ql @@ -13,13 +13,57 @@ import cpp import semmle.code.cpp.security.SensitiveExprs -import semmle.code.cpp.dataflow.TaintTracking -import DataFlow::PathGraph +import semmle.code.cpp.ir.dataflow.TaintTracking +import FromSensitiveFlow::PathGraph -class SqliteFunctionCall extends FunctionCall { - SqliteFunctionCall() { this.getTarget().getName().matches("sqlite%") } +abstract class SqliteFunctionCall extends FunctionCall { + abstract Expr getASource(); +} - Expr getASource() { result = this.getAnArgument() } +class SqliteFunctionPrepareCall extends SqliteFunctionCall { + SqliteFunctionPrepareCall() { this.getTarget().getName().matches("sqlite3\\_prepare%") } + + override Expr getASource() { result = this.getArgument(1) } +} + +class SqliteFunctionExecCall extends SqliteFunctionCall { + SqliteFunctionExecCall() { this.getTarget().hasName("sqlite3_exec") } + + override Expr getASource() { result = this.getArgument(1) } +} + +class SqliteFunctionAppendfCall extends SqliteFunctionCall { + SqliteFunctionAppendfCall() { + this.getTarget().hasName(["sqlite3_str_appendf", "sqlite3_str_vappendf"]) + } + + override Expr getASource() { result = this.getArgument(any(int n | n > 0)) } +} + +class SqliteFunctionAppendNonCharCall extends SqliteFunctionCall { + SqliteFunctionAppendNonCharCall() { + this.getTarget().hasName(["sqlite3_str_append", "sqlite3_str_appendall"]) + } + + override Expr getASource() { result = this.getArgument(1) } +} + +class SqliteFunctionAppendCharCall extends SqliteFunctionCall { + SqliteFunctionAppendCharCall() { this.getTarget().hasName("sqlite3_str_appendchar") } + + override Expr getASource() { result = this.getArgument(2) } +} + +class SqliteFunctionBindCall extends SqliteFunctionCall { + SqliteFunctionBindCall() { + this.getTarget() + .hasName([ + "sqlite3_bind_blob", "sqlite3_bind_blob64", "sqlite3_bind_text", "sqlite3_bind_text16", + "sqlite3_bind_text64", "sqlite3_bind_value", "sqlite3_bind_pointer" + ]) + } + + override Expr getASource() { result = this.getArgument(2) } } predicate sqlite_encryption_used() { @@ -36,44 +80,60 @@ Field getRecField(Class c) { result = getRecField(c.getAField().getUnspecifiedType().stripType()) } +/** + * Holds if `source` is a use of a sensitive expression `sensitive`, or + * if `source` is the output argument (with a sensitive name) of a function. + */ +predicate isSourceImpl(DataFlow::Node source, SensitiveExpr sensitive) { + [source.asExpr(), source.asDefiningArgument()] = sensitive +} + +/** Holds if `sink` is an argument to an Sqlite function call `c`. */ +predicate isSinkImpl(DataFlow::Node sink, SqliteFunctionCall c, Type t) { + exists(Expr e | + e = c.getASource() and + e = [sink.asExpr(), sink.asIndirectExpr()] and + t = e.getUnspecifiedType() + ) +} + /** * A taint flow configuration for flow from a sensitive expression to a `SqliteFunctionCall` sink. */ -class FromSensitiveConfiguration extends TaintTracking::Configuration { - FromSensitiveConfiguration() { this = "FromSensitiveConfiguration" } - - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveExpr } - - override predicate isSink(DataFlow::Node sink) { - any(SqliteFunctionCall c).getASource() = sink.asExpr() and - not sqlite_encryption_used() +module FromSensitiveConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + isSourceImpl(source, _) and not sqlite_encryption_used() } - override predicate isSanitizer(DataFlow::Node node) { + predicate isSink(DataFlow::Node sink) { isSinkImpl(sink, _, _) } + + predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } - override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) { + predicate isBarrierIn(DataFlow::Node node) { isSource(node) } + + predicate isBarrierOut(DataFlow::Node node) { isSink(node) } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet content) { // flow out from fields at the sink (only). - this.isSink(node) and // constrain `content` to a field inside the node. - exists(Class c | - node.asExpr().getUnspecifiedType().stripType() = c and - content.(DataFlow::FieldContent).getField() = getRecField(c) + exists(Type t | + isSinkImpl(node, _, t) and + content.(DataFlow::FieldContent).getField() = getRecField(t.stripType()) ) - or - // any default implicit reads - super.allowImplicitRead(node, content) } } +module FromSensitiveFlow = TaintTracking::Make; + from - FromSensitiveConfiguration config, SensitiveExpr sensitive, DataFlow::PathNode source, - DataFlow::PathNode sink, SqliteFunctionCall sqliteCall + SensitiveExpr sensitive, FromSensitiveFlow::PathNode source, FromSensitiveFlow::PathNode sink, + SqliteFunctionCall sqliteCall where - config.hasFlowPath(source, sink) and - source.getNode().asExpr() = sensitive and - sqliteCall.getASource() = sink.getNode().asExpr() + FromSensitiveFlow::hasFlowPath(source, sink) and + isSourceImpl(source.getNode(), sensitive) and + isSinkImpl(sink.getNode(), sqliteCall, _) select sqliteCall, source, sink, "This SQLite call may store $@ in a non-encrypted SQLite database.", sensitive, "sensitive information" diff --git a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql index 240f07589f3..ceddfbf9f40 100644 --- a/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql +++ b/cpp/ql/src/Security/CWE/CWE-319/UseOfHttp.ql @@ -12,9 +12,9 @@ */ import cpp -import semmle.code.cpp.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import DataFlow::PathGraph +import HttpStringToUrlOpen::PathGraph /** * A string matching private host names of IPv4 and IPv6, which only matches @@ -54,20 +54,18 @@ class HttpStringLiteral extends StringLiteral { /** * Taint tracking configuration for HTTP connections. */ -class HttpStringToUrlOpenConfig extends TaintTracking::Configuration { - HttpStringToUrlOpenConfig() { this = "HttpStringToUrlOpenConfig" } - - override predicate isSource(DataFlow::Node src) { +module HttpStringToUrlOpenConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { // Sources are strings containing an HTTP URL not in a private domain. - src.asExpr() instanceof HttpStringLiteral and + src.asIndirectExpr() instanceof HttpStringLiteral and // block taint starting at `strstr`, which is likely testing an existing URL, rather than constructing an HTTP URL. not exists(FunctionCall fc | fc.getTarget().getName() = ["strstr", "strcasestr"] and - fc.getArgument(1) = globalValueNumber(src.asExpr()).getAnExpr() + fc.getArgument(1) = globalValueNumber(src.asIndirectExpr()).getAnExpr() ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { // Sinks can be anything that demonstrates the string is likely to be // accessed as a URL, for example using it in a network access. Some // URLs are only ever displayed or used for data processing. @@ -77,24 +75,24 @@ class HttpStringToUrlOpenConfig extends TaintTracking::Configuration { "system", "gethostbyname", "gethostbyname2", "gethostbyname_r", "getaddrinfo", "X509_load_http", "X509_CRL_load_http" ]) and - sink.asExpr() = fc.getArgument(0) + sink.asIndirectExpr() = fc.getArgument(0) or fc.getTarget().hasGlobalOrStdName(["send", "URLDownloadToFile", "URLDownloadToCacheFile"]) and - sink.asExpr() = fc.getArgument(1) + sink.asIndirectExpr() = fc.getArgument(1) or fc.getTarget().hasGlobalOrStdName(["curl_easy_setopt", "getnameinfo"]) and - sink.asExpr() = fc.getArgument(2) + sink.asIndirectExpr() = fc.getArgument(2) or fc.getTarget().hasGlobalOrStdName(["ShellExecute", "ShellExecuteA", "ShellExecuteW"]) and - sink.asExpr() = fc.getArgument(3) + sink.asIndirectExpr() = fc.getArgument(3) ) } } -from - HttpStringToUrlOpenConfig config, DataFlow::PathNode source, DataFlow::PathNode sink, - HttpStringLiteral str +module HttpStringToUrlOpen = TaintTracking::Make; + +from HttpStringToUrlOpen::PathNode source, HttpStringToUrlOpen::PathNode sink, HttpStringLiteral str where - config.hasFlowPath(source, sink) and - str = source.getNode().asExpr() + HttpStringToUrlOpen::hasFlowPath(source, sink) and + str = source.getNode().asIndirectExpr() select str, source, sink, "This URL may be constructed with the HTTP protocol." diff --git a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql index 202e9fb225d..f899889a59b 100644 --- a/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/cpp/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.ir.IR -import DataFlow::PathGraph +import KeyStrengthFlow::PathGraph // Gets the recommended minimum key size (in bits) of `func`, the name of an encryption function that accepts a key size as parameter `paramIndex` int getMinimumKeyStrength(string func, int paramIndex) { @@ -28,10 +28,8 @@ int getMinimumKeyStrength(string func, int paramIndex) { result = 2048 } -class KeyStrengthFlow extends DataFlow::Configuration { - KeyStrengthFlow() { this = "KeyStrengthFlow" } - - override predicate isSource(DataFlow::Node node) { +module KeyStrengthFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { exists(int bits | node.asInstruction().(IntegerConstantInstruction).getValue().toInt() = bits and bits < getMinimumKeyStrength(_, _) and @@ -39,7 +37,7 @@ class KeyStrengthFlow extends DataFlow::Configuration { ) } - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { exists(FunctionCall fc, string name, int param | node.asExpr() = fc.getArgument(param) and fc.getTarget().hasGlobalName(name) and @@ -48,11 +46,13 @@ class KeyStrengthFlow extends DataFlow::Configuration { } } +module KeyStrengthFlow = DataFlow::Make; + from - DataFlow::PathNode source, DataFlow::PathNode sink, KeyStrengthFlow conf, FunctionCall fc, - int param, string name, int minimumBits, int bits + KeyStrengthFlow::PathNode source, KeyStrengthFlow::PathNode sink, FunctionCall fc, int param, + string name, int minimumBits, int bits where - conf.hasFlowPath(source, sink) and + KeyStrengthFlow::hasFlowPath(source, sink) and sink.getNode().asExpr() = fc.getArgument(param) and fc.getTarget().hasGlobalName(name) and minimumBits = getMinimumKeyStrength(name, param) and diff --git a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql index f575b359ddf..e6dd4e7046e 100644 --- a/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-428/UnsafeCreateProcessCall.ql @@ -12,8 +12,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.DataFlow2 +import semmle.code.cpp.ir.dataflow.DataFlow predicate isCreateProcessFunction(FunctionCall call, int applicationNameIndex, int commandLineIndex) { call.getTarget().hasGlobalName("CreateProcessA") and @@ -55,42 +54,39 @@ class CreateProcessFunctionCall extends FunctionCall { /** * Dataflow that detects a call to CreateProcess with a NULL value for lpApplicationName argument */ -class NullAppNameCreateProcessFunctionConfiguration extends DataFlow::Configuration { - NullAppNameCreateProcessFunctionConfiguration() { - this = "NullAppNameCreateProcessFunctionConfiguration" - } +module NullAppNameCreateProcessFunctionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | val = call.getArgument(call.getApplicationNameArgumentId()) ) } } +module NullAppNameCreateProcessFunction = DataFlow::Make; + /** * Dataflow that detects a call to CreateProcess with an unquoted commandLine argument */ -class QuotedCommandInCreateProcessFunctionConfiguration extends DataFlow2::Configuration { - QuotedCommandInCreateProcessFunctionConfiguration() { - this = "QuotedCommandInCreateProcessFunctionConfiguration" - } - - override predicate isSource(DataFlow2::Node source) { +module QuotedCommandInCreateProcessFunctionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(string s | s = source.asExpr().getValue().toString() and not isQuotedOrNoSpaceApplicationNameOnCmd(s) ) } - override predicate isSink(DataFlow2::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(CreateProcessFunctionCall call, Expr val | val = sink.asExpr() | val = call.getArgument(call.getCommandLineArgumentId()) ) } } +module QuotedCommandInCreateProcessFunction = + DataFlow::Make; + bindingset[s] predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) { s.regexpMatch("\"([^\"])*\"[\\s\\S]*") // The first element (path) is quoted @@ -100,14 +96,14 @@ predicate isQuotedOrNoSpaceApplicationNameOnCmd(string s) { from CreateProcessFunctionCall call, string msg1, string msg2 where - exists(Expr appName, NullAppNameCreateProcessFunctionConfiguration nullAppConfig | + exists(Expr appName | appName = call.getArgument(call.getApplicationNameArgumentId()) and - nullAppConfig.hasFlowToExpr(appName) and + NullAppNameCreateProcessFunction::hasFlowToExpr(appName) and msg1 = call.toString() + " with lpApplicationName == NULL (" + appName + ")" ) and - exists(Expr cmd, QuotedCommandInCreateProcessFunctionConfiguration quotedConfig | + exists(Expr cmd | cmd = call.getArgument(call.getCommandLineArgumentId()) and - quotedConfig.hasFlowToExpr(cmd) and + QuotedCommandInCreateProcessFunction::hasFlowToExpr(cmd) and msg2 = " and with an unquoted lpCommandLine (" + cmd + ") introduces a security vulnerability if the path contains spaces." diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql index 78247b8a1ae..7e76cf76c12 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql @@ -15,31 +15,31 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.models.interfaces.FlowSource -import DataFlow::PathGraph +import ExposedSystemData::PathGraph import SystemData -class ExposedSystemDataConfiguration extends TaintTracking::Configuration { - ExposedSystemDataConfiguration() { this = "ExposedSystemDataConfiguration" } +module ExposedSystemDataConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() } - override predicate isSource(DataFlow::Node source) { source = any(SystemData sd).getAnExpr() } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(FunctionCall fc, FunctionInput input, int arg | fc.getTarget().(RemoteFlowSinkFunction).hasRemoteFlowSink(input, _) and input.isParameterDeref(arg) and - fc.getArgument(arg).getAChild*() = sink.asExpr() + fc.getArgument(arg).getAChild*() = sink.asIndirectExpr() ) } } -from ExposedSystemDataConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink +module ExposedSystemData = TaintTracking::Make; + +from ExposedSystemData::PathNode source, ExposedSystemData::PathNode sink where - config.hasFlowPath(source, sink) and + ExposedSystemData::hasFlowPath(source, sink) and not exists( DataFlow::Node alt // remove duplicate results on conversions | - config.hasFlow(source.getNode(), alt) and - alt.asConvertedExpr() = sink.getNode().asExpr() and + ExposedSystemData::hasFlow(source.getNode(), alt) and + alt.asConvertedExpr() = sink.getNode().asIndirectExpr() and alt != sink.getNode() ) select sink, source, sink, "This operation exposes system data from $@.", source, diff --git a/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql index f1854c41b1b..a06314e3c97 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/PotentiallyExposedSystemData.ql @@ -28,24 +28,32 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.models.interfaces.FlowSource import semmle.code.cpp.security.OutputWrite -import DataFlow::PathGraph +import PotentiallyExposedSystemData::PathGraph import SystemData -class PotentiallyExposedSystemDataConfiguration extends TaintTracking::Configuration { - PotentiallyExposedSystemDataConfiguration() { this = "PotentiallyExposedSystemDataConfiguration" } - - override predicate isSource(DataFlow::Node source) { +module PotentiallyExposedSystemDataConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source = any(SystemData sd | sd.isSensitive()).getAnExpr() } - override predicate isSink(DataFlow::Node sink) { - exists(OutputWrite ow | ow.getASource().getAChild*() = sink.asExpr()) + predicate isSink(DataFlow::Node sink) { + exists(OutputWrite ow, Expr child | child = ow.getASource().getAChild*() | + // Most sinks receive a pointer as an argument (for example `printf`), + // and we use an indirect sink for those. + // However, some sinks (for example `puts`) receive a single character + // as an argument. For those we have to use a direct sink. + if + child.getUnspecifiedType() instanceof PointerType or + child.getUnspecifiedType() instanceof ArrayType + then child = sink.asIndirectExpr() + else child = sink.asExpr() + ) } } -from - PotentiallyExposedSystemDataConfiguration config, DataFlow::PathNode source, - DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +module PotentiallyExposedSystemData = TaintTracking::Make; + +from PotentiallyExposedSystemData::PathNode source, PotentiallyExposedSystemData::PathNode sink +where PotentiallyExposedSystemData::hasFlowPath(source, sink) select sink, source, sink, "This operation potentially exposes sensitive system data from $@.", source, source.getNode().toString() diff --git a/cpp/ql/src/Security/CWE/CWE-497/SystemData.qll b/cpp/ql/src/Security/CWE/CWE-497/SystemData.qll index 0c04264892c..0914bb4d790 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/SystemData.qll +++ b/cpp/ql/src/Security/CWE/CWE-497/SystemData.qll @@ -34,7 +34,7 @@ class EnvData extends SystemData { .regexpMatch(".*(user|host|admin|root|home|path|http|ssl|snmp|sock|port|proxy|pass|token|crypt|key).*") } - override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this } + override DataFlow::Node getAnExpr() { result.asIndirectConvertedExpr() = this } override predicate isSensitive() { this.(EnvironmentRead) @@ -50,7 +50,7 @@ class EnvData extends SystemData { class SqlClientInfo extends SystemData { SqlClientInfo() { this.(FunctionCall).getTarget().hasName("mysql_get_client_info") } - override DataFlow::Node getAnExpr() { result.asConvertedExpr() = this } + override DataFlow::Node getAnExpr() { result.asIndirectConvertedExpr() = this } override predicate isSensitive() { any() } } @@ -72,7 +72,7 @@ private predicate sqlConnectInfo(FunctionCall source, Expr use) { class SqlConnectInfo extends SystemData { SqlConnectInfo() { sqlConnectInfo(this, _) } - override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asConvertedExpr()) } + override DataFlow::Node getAnExpr() { sqlConnectInfo(this, result.asIndirectExpr(1)) } override predicate isSensitive() { any() } } @@ -114,7 +114,7 @@ private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) { source .getTarget() .hasName(["getpwnam", "getpwuid", "getpwent", "getgrnam", "getgrgid", "getgrent"]) and - use.asConvertedExpr() = source + use.asIndirectExpr() = source or // int getpwnam_r(const char *name, struct passwd *pwd, // char *buf, size_t buflen, struct passwd **result); @@ -126,7 +126,7 @@ private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) { // char *buf, size_t buflen, struct group **result); source.getTarget().hasName(["getpwnam_r", "getpwuid_r", "getgrgid_r", "getgrnam_r"]) and ( - use.asConvertedExpr() = source.getArgument([1, 2]) or + use.asExpr() = source.getArgument([1, 2]) or use.asDefiningArgument() = source.getArgument(4) ) or @@ -136,7 +136,7 @@ private predicate posixPWInfo(FunctionCall source, DataFlow::Node use) { // size_t buflen, struct group **gbufp); source.getTarget().hasName(["getpwent_r", "getgrent_r"]) and ( - use.asConvertedExpr() = source.getArgument([0, 1]) or + use.asExpr() = source.getArgument([0, 1]) or use.asDefiningArgument() = source.getArgument(3) ) } @@ -155,7 +155,7 @@ class PosixPWInfo extends SystemData { private predicate windowsSystemInfo(FunctionCall source, DataFlow::Node use) { // DWORD WINAPI GetVersion(void); source.getTarget().hasGlobalName("GetVersion") and - use.asConvertedExpr() = source + use.asExpr() = source or // BOOL WINAPI GetVersionEx(_Inout_ LPOSVERSIONINFO lpVersionInfo); // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); @@ -236,7 +236,7 @@ class WindowsFolderPath extends SystemData { override DataFlow::Node getAnExpr() { windowsFolderPath(this, result.asDefiningArgument()) } } -private predicate logonUser(FunctionCall source, VariableAccess use) { +private predicate logonUser(FunctionCall source, Expr use) { source.getTarget().hasGlobalName(["LogonUser", "LogonUserW", "LogonUserA"]) and use = source.getAnArgument() } @@ -247,7 +247,7 @@ private predicate logonUser(FunctionCall source, VariableAccess use) { class LogonUser extends SystemData { LogonUser() { logonUser(this, _) } - override DataFlow::Node getAnExpr() { logonUser(this, result.asConvertedExpr()) } + override DataFlow::Node getAnExpr() { logonUser(this, result.asIndirectExpr()) } override predicate isSensitive() { any() } } diff --git a/cpp/ql/src/Security/CWE/CWE-611/Libxml2.qll b/cpp/ql/src/Security/CWE/CWE-611/Libxml2.qll index c20849fcd9e..69fc9369cd8 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/Libxml2.qll +++ b/cpp/ql/src/Security/CWE/CWE-611/Libxml2.qll @@ -48,7 +48,7 @@ class Libxml2BadOption extends EnumConstant { class LibXml2Library extends XmlLibrary { LibXml2Library() { this = "LibXml2Library" } - override predicate configurationSource(DataFlow::Node node, string flowstate) { + override predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate) { // source is an `options` argument on a libxml2 parse call that specifies // at least one unsafe option. // @@ -59,7 +59,7 @@ class LibXml2Library extends XmlLibrary { exists(Libxml2ParseCall call, Expr options | options = call.getOptions() and node.asExpr() = options and - flowstate = "libxml2" and + flowstate instanceof TLibXml2FlowState and exists(Libxml2BadOption opt | globalValueNumber(options).getAnExpr().getValue().toInt().bitAnd(opt.getValue().toInt()) != 0 @@ -67,12 +67,12 @@ class LibXml2Library extends XmlLibrary { ) } - override predicate configurationSink(DataFlow::Node node, string flowstate) { + override predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate) { // sink is the `options` argument on a `libxml2` parse call. exists(Libxml2ParseCall call, Expr options | options = call.getOptions() and node.asExpr() = options and - flowstate = "libxml2" + flowstate instanceof TLibXml2FlowState ) } } diff --git a/cpp/ql/src/Security/CWE/CWE-611/XML.qll b/cpp/ql/src/Security/CWE/CWE-611/XML.qll index 5d071ed7654..824e786151a 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/XML.qll +++ b/cpp/ql/src/Security/CWE/CWE-611/XML.qll @@ -11,10 +11,20 @@ import Libxml2 /** * A flow state representing a possible configuration of an XML object. */ -abstract class XxeFlowState extends DataFlow::FlowState { - bindingset[this] - XxeFlowState() { any() } // required characteristic predicate -} +newtype TXxeFlowState = + /** + * Flow state for `AbstractDOMParser` or `SAXParser`, where: + * - `disabledDefaultEntityResolution` is 1 if `setDisableDefaultEntityResolution` + * is `true`, 0 otherwise. + * - `createEntityReferenceNodes` is 1 if `setCreateEntityReferenceNodes` + * is `true`, 0 otherwise. + */ + TXercesFlowState(int disabledDefaultEntityResolution, int createEntityReferenceNodes) { + disabledDefaultEntityResolution in [0, 1] and + createEntityReferenceNodes in [0, 1] + } or + /** Flow state for libxml2 */ + TLibXml2FlowState() /** * An XML library or interface. @@ -28,13 +38,13 @@ abstract class XmlLibrary extends string { * object for this XML library, along with `flowstate` representing its * initial state. */ - abstract predicate configurationSource(DataFlow::Node node, string flowstate); + abstract predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate); /** * Holds if `node` is the sink node where an unsafe configuration object is * used to interpret XML. */ - abstract predicate configurationSink(DataFlow::Node node, string flowstate); + abstract predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate); } /** @@ -51,5 +61,5 @@ abstract class XxeFlowStateTransformer extends Expr { * transform(transform(x)) = transform(x) * ``` */ - abstract XxeFlowState transform(XxeFlowState flowstate); + abstract TXxeFlowState transform(TXxeFlowState flowstate); } diff --git a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql index abd1773afd8..1b611a42b8d 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/XXE.ql +++ b/cpp/ql/src/Security/CWE/CWE-611/XXE.ql @@ -14,38 +14,40 @@ import cpp import XML -import DataFlow::PathGraph +import XxeFlow::PathGraph /** * A configuration for tracking XML objects and their states. */ -class XxeConfiguration extends DataFlow::Configuration { - XxeConfiguration() { this = "XXEConfiguration" } +module XxeConfig implements DataFlow::StateConfigSig { + class FlowState = TXxeFlowState; - override predicate isSource(DataFlow::Node node, string flowstate) { + predicate isSource(DataFlow::Node node, FlowState flowstate) { any(XmlLibrary l).configurationSource(node, flowstate) } - override predicate isSink(DataFlow::Node node, string flowstate) { + predicate isSink(DataFlow::Node node, FlowState flowstate) { any(XmlLibrary l).configurationSink(node, flowstate) } - override predicate isAdditionalFlowStep( - DataFlow::Node node1, string state1, DataFlow::Node node2, string state2 + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 ) { // create additional flow steps for `XxeFlowStateTransformer`s - state2 = node2.asConvertedExpr().(XxeFlowStateTransformer).transform(state1) and + state2 = node2.asIndirectExpr().(XxeFlowStateTransformer).transform(state1) and DataFlow::simpleLocalFlowStep(node1, node2) } - override predicate isBarrier(DataFlow::Node node, string flowstate) { + predicate isBarrier(DataFlow::Node node, FlowState flowstate) { // when the flowstate is transformed at a call node, block the original // flowstate value. - node.asConvertedExpr().(XxeFlowStateTransformer).transform(flowstate) != flowstate + node.asIndirectExpr().(XxeFlowStateTransformer).transform(flowstate) != flowstate } } -from XxeConfiguration conf, DataFlow::PathNode source, DataFlow::PathNode sink -where conf.hasFlowPath(source, sink) +module XxeFlow = DataFlow::MakeWithState; + +from XxeFlow::PathNode source, XxeFlow::PathNode sink +where XxeFlow::hasFlowPath(source, sink) select sink, source, sink, "This $@ is not configured to prevent an XML external entity (XXE) attack.", source, "XML parser" diff --git a/cpp/ql/src/Security/CWE/CWE-611/Xerces.qll b/cpp/ql/src/Security/CWE/CWE-611/Xerces.qll index 7b971f00293..f84cd6d48eb 100644 --- a/cpp/ql/src/Security/CWE/CWE-611/Xerces.qll +++ b/cpp/ql/src/Security/CWE/CWE-611/Xerces.qll @@ -7,39 +7,33 @@ import XML import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.ir.IR -/** - * Gets a valid flow state for `AbstractDOMParser` or `SAXParser` flow. - * - * These flow states take the form `Xerces-A-B`, where: - * - A is 1 if `setDisableDefaultEntityResolution` is `true`, 0 otherwise. - * - B is 1 if `setCreateEntityReferenceNodes` is `true`, 0 otherwise. - */ -predicate encodeXercesFlowState( - string flowstate, int disabledDefaultEntityResolution, int createEntityReferenceNodes -) { - flowstate = "Xerces-0-0" and - disabledDefaultEntityResolution = 0 and - createEntityReferenceNodes = 0 - or - flowstate = "Xerces-0-1" and - disabledDefaultEntityResolution = 0 and - createEntityReferenceNodes = 1 - or - flowstate = "Xerces-1-0" and - disabledDefaultEntityResolution = 1 and - createEntityReferenceNodes = 0 - or - flowstate = "Xerces-1-1" and - disabledDefaultEntityResolution = 1 and - createEntityReferenceNodes = 1 -} - /** * A flow state representing the configuration of an `AbstractDOMParser` or * `SAXParser` object. */ -class XercesFlowState extends XxeFlowState { - XercesFlowState() { encodeXercesFlowState(this, _, _) } +class XercesFlowState extends TXxeFlowState { + int disabledDefaultEntityResolution; + int createEntityReferenceNodes; + + XercesFlowState() { + this = TXercesFlowState(disabledDefaultEntityResolution, createEntityReferenceNodes) + } + + int getDisabledDefaultEntityResolution() { result = disabledDefaultEntityResolution } + + int getCreateEntityReferenceNodes() { result = createEntityReferenceNodes } + + string toString() { result = "XercesFlowState" } +} + +/** + * Gets a valid flow state for `AbstractDOMParser` or `SAXParser` flow. + */ +predicate encodeXercesFlowState( + XercesFlowState flowstate, int disabledDefaultEntityResolution, int createEntityReferenceNodes +) { + flowstate.getDisabledDefaultEntityResolution() = disabledDefaultEntityResolution and + flowstate.getCreateEntityReferenceNodes() = createEntityReferenceNodes } /** @@ -62,22 +56,21 @@ class XercesDomParserClass extends Class { class XercesDomParserLibrary extends XmlLibrary { XercesDomParserLibrary() { this = "XercesDomParserLibrary" } - override predicate configurationSource(DataFlow::Node node, string flowstate) { + override predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate) { // source is the write on `this` of a call to the `XercesDOMParser` // constructor. - exists(CallInstruction call | - call.getStaticCallTarget() = any(XercesDomParserClass c).getAConstructor() and - node.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() = - call.getThisArgument() and + exists(Call call | + call.getTarget() = any(XercesDomParserClass c).getAConstructor() and + node.asExpr() = call and encodeXercesFlowState(flowstate, 0, 1) // default configuration ) } - override predicate configurationSink(DataFlow::Node node, string flowstate) { + override predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate) { // sink is the read of the qualifier of a call to `AbstractDOMParser.parse`. exists(Call call | call.getTarget().getClassAndName("parse") instanceof AbstractDomParserClass and - call.getQualifier() = node.asConvertedExpr() + call.getQualifier() = node.asIndirectConvertedExpr() ) and flowstate instanceof XercesFlowState and not encodeXercesFlowState(flowstate, 1, 1) // safe configuration @@ -108,20 +101,20 @@ class CreateLSParser extends Function { class CreateLSParserLibrary extends XmlLibrary { CreateLSParserLibrary() { this = "CreateLSParserLibrary" } - override predicate configurationSource(DataFlow::Node node, string flowstate) { + override predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate) { // source is the result of a call to `createLSParser`. exists(Call call | call.getTarget() instanceof CreateLSParser and - call = node.asExpr() and + call = node.asIndirectExpr() and encodeXercesFlowState(flowstate, 0, 1) // default configuration ) } - override predicate configurationSink(DataFlow::Node node, string flowstate) { + override predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate) { // sink is the read of the qualifier of a call to `DOMLSParserClass.parse`. exists(Call call | call.getTarget().getClassAndName("parse") instanceof DomLSParserClass and - call.getQualifier() = node.asConvertedExpr() + call.getQualifier() = node.asIndirectConvertedExpr() ) and flowstate instanceof XercesFlowState and not encodeXercesFlowState(flowstate, 1, 1) // safe configuration @@ -148,22 +141,21 @@ class Sax2XmlReader extends Class { class SaxParserLibrary extends XmlLibrary { SaxParserLibrary() { this = "SaxParserLibrary" } - override predicate configurationSource(DataFlow::Node node, string flowstate) { + override predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate) { // source is the write on `this` of a call to the `SAXParser` // constructor. - exists(CallInstruction call | - call.getStaticCallTarget() = any(SaxParserClass c).getAConstructor() and - node.asInstruction().(WriteSideEffectInstruction).getDestinationAddress() = - call.getThisArgument() and + exists(Call call | + call.getTarget() = any(SaxParserClass c).getAConstructor() and + node.asExpr() = call and encodeXercesFlowState(flowstate, 0, 1) // default configuration ) } - override predicate configurationSink(DataFlow::Node node, string flowstate) { + override predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate) { // sink is the read of the qualifier of a call to `SAXParser.parse`. exists(Call call | call.getTarget().getClassAndName("parse") instanceof SaxParserClass and - call.getQualifier() = node.asConvertedExpr() + call.getQualifier() = node.asIndirectConvertedExpr() ) and flowstate instanceof XercesFlowState and not encodeXercesFlowState(flowstate, 1, 1) // safe configuration @@ -187,20 +179,20 @@ class CreateXmlReader extends Function { class Sax2XmlReaderLibrary extends XmlLibrary { Sax2XmlReaderLibrary() { this = "Sax2XmlReaderLibrary" } - override predicate configurationSource(DataFlow::Node node, string flowstate) { + override predicate configurationSource(DataFlow::Node node, TXxeFlowState flowstate) { // source is the result of a call to `createXMLReader`. exists(Call call | call.getTarget() instanceof CreateXmlReader and - call = node.asExpr() and + call = node.asIndirectExpr() and encodeXercesFlowState(flowstate, 0, 1) // default configuration ) } - override predicate configurationSink(DataFlow::Node node, string flowstate) { + override predicate configurationSink(DataFlow::Node node, TXxeFlowState flowstate) { // sink is the read of the qualifier of a call to `SAX2XMLReader.parse`. exists(Call call | call.getTarget().getClassAndName("parse") instanceof Sax2XmlReader and - call.getQualifier() = node.asConvertedExpr() + call.getQualifier() = node.asIndirectConvertedExpr() ) and flowstate instanceof XercesFlowState and not encodeXercesFlowState(flowstate, 1, 1) // safe configuration @@ -229,7 +221,7 @@ class DisableDefaultEntityResolutionTransformer extends XxeFlowStateTransformer ) } - final override XxeFlowState transform(XxeFlowState flowstate) { + final override TXxeFlowState transform(TXxeFlowState flowstate) { exists(int createEntityReferenceNodes | encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and ( @@ -260,7 +252,7 @@ class CreateEntityReferenceNodesTransformer extends XxeFlowStateTransformer { ) } - final override XxeFlowState transform(XxeFlowState flowstate) { + final override TXxeFlowState transform(TXxeFlowState flowstate) { exists(int disabledDefaultEntityResolution | encodeXercesFlowState(flowstate, disabledDefaultEntityResolution, _) and ( @@ -303,7 +295,7 @@ class SetFeatureTransformer extends XxeFlowStateTransformer { ) } - final override XxeFlowState transform(XxeFlowState flowstate) { + final override TXxeFlowState transform(TXxeFlowState flowstate) { exists(int createEntityReferenceNodes | encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and ( @@ -361,7 +353,7 @@ class DomConfigurationSetParameterTransformer extends XxeFlowStateTransformer { ) } - final override XxeFlowState transform(XxeFlowState flowstate) { + final override TXxeFlowState transform(TXxeFlowState flowstate) { exists(int createEntityReferenceNodes | encodeXercesFlowState(flowstate, _, createEntityReferenceNodes) and ( diff --git a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c index 3c984aa6a62..b015770ad80 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c +++ b/cpp/ql/src/Security/CWE/CWE-732/DoNotCreateWorldWritable.c @@ -1,11 +1,11 @@ -int write_default_config_bad() { +void write_default_config_bad() { // BAD - this is world-writable so any user can overwrite the config - FILE* out = creat(OUTFILE, 0666); - fprintf(out, DEFAULT_CONFIG); + int out = creat(OUTFILE, 0666); + dprintf(out, DEFAULT_CONFIG); } -int write_default_config_good() { +void write_default_config_good() { // GOOD - this allows only the current user to modify the file - FILE* out = creat(OUTFILE, S_IWUSR | S_IRUSR); - fprintf(out, DEFAULT_CONFIG); + int out = creat(OUTFILE, S_IWUSR | S_IRUSR); + dprintf(out, DEFAULT_CONFIG); } diff --git a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql index d6cac657978..8f36ab50aa8 100644 --- a/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql +++ b/cpp/ql/src/Security/CWE/CWE-732/UnsafeDaclSecurityDescriptor.ql @@ -14,8 +14,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.DataFlow2 +import semmle.code.cpp.ir.dataflow.DataFlow /** * A function call to SetSecurityDescriptorDacl to set the ACL, specified by (2nd argument) bDaclPresent = TRUE @@ -30,26 +29,24 @@ class SetSecurityDescriptorDaclFunctionCall extends FunctionCall { /** * Dataflow that detects a call to SetSecurityDescriptorDacl with a NULL DACL as the pDacl argument */ -class NullDaclConfig extends DataFlow::Configuration { - NullDaclConfig() { this = "NullDaclConfig" } +module NullDaclConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof NullValue } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(SetSecurityDescriptorDaclFunctionCall call, VariableAccess val | val = sink.asExpr() | val = call.getArgument(2) ) } } +module NullDaclFlow = DataFlow::Make; + /** * Dataflow that detects a call to SetSecurityDescriptorDacl with a pDacl * argument that's _not_ likely to be NULL. */ -class NonNullDaclConfig extends DataFlow2::Configuration { - NonNullDaclConfig() { this = "NonNullDaclConfig" } - - override predicate isSource(DataFlow::Node source) { +module NonNullDaclConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.getType().getUnspecifiedType().(PointerType).getBaseType() = any(Type t | t.getName() = "ACL").getUnspecifiedType() and ( @@ -68,11 +65,13 @@ class NonNullDaclConfig extends DataFlow2::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(SetSecurityDescriptorDaclFunctionCall call | sink.asExpr() = call.getArgument(2)) } } +module NonNullDaclFlow = DataFlow::Make; + from SetSecurityDescriptorDaclFunctionCall call, string message where exists(NullValue nullExpr | @@ -83,13 +82,13 @@ where call.getArgument(2) = nullExpr ) or - exists(VariableAccess var, NullDaclConfig nullDaclConfig, NonNullDaclConfig nonNullDaclConfig | + exists(VariableAccess var | message = "Setting a DACL to NULL in a SECURITY_DESCRIPTOR using variable " + var + " that is set to NULL will result in an unprotected object." | var = call.getArgument(2) and - nullDaclConfig.hasFlowToExpr(var) and - not nonNullDaclConfig.hasFlowToExpr(var) + NullDaclFlow::hasFlowToExpr(var) and + not NonNullDaclFlow::hasFlowToExpr(var) ) select call, message diff --git a/cpp/ql/src/change-notes/2023-03-08-deprecated-dataflow-configurations.md b/cpp/ql/src/change-notes/2023-03-08-deprecated-dataflow-configurations.md new file mode 100644 index 00000000000..46952f5b1a3 --- /dev/null +++ b/cpp/ql/src/change-notes/2023-03-08-deprecated-dataflow-configurations.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `NetworkToBufferSizeConfiguration` and `UntrustedDataToExternalApiConfig` dataflow configurations have been deprecated. Please use `NetworkToBufferSizeFlow` and `UntrustedDataToExternalApiFlow`. diff --git a/cpp/ql/src/change-notes/2023-03-08-deprecated-leap-year-dataflow-configurations.md b/cpp/ql/src/change-notes/2023-03-08-deprecated-leap-year-dataflow-configurations.md new file mode 100644 index 00000000000..1ea59f77680 --- /dev/null +++ b/cpp/ql/src/change-notes/2023-03-08-deprecated-leap-year-dataflow-configurations.md @@ -0,0 +1,4 @@ +--- +category: deprecated +--- +* The `LeapYearCheckConfiguration`, `FiletimeYearArithmeticOperationCheckConfiguration`, and `PossibleYearArithmeticOperationCheckConfiguration` dataflow configurations have been deprecated. Please use `LeapYearCheckFlow`, `FiletimeYearArithmeticOperationCheckFlow` and `PossibleYearArithmeticOperationCheckFlow`. diff --git a/cpp/ql/src/change-notes/released/0.5.4.md b/cpp/ql/src/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..1686ab4354d --- /dev/null +++ b/cpp/ql/src/change-notes/released/0.5.4.md @@ -0,0 +1,3 @@ +## 0.5.4 + +No user-facing changes. diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/cpp/ql/src/codeql-pack.release.yml +++ b/cpp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql b/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql index 8a93e93476e..0be612e4e60 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser.ql @@ -16,7 +16,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow /** * A Linux system call. diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql b/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql index f4de1251e8b..7b72b2684e6 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-078/WordexpTainted.ql @@ -15,7 +15,7 @@ import cpp import semmle.code.cpp.ir.dataflow.TaintTracking import semmle.code.cpp.security.FlowSources -import DataFlow::PathGraph +import WordexpTaint::PathGraph /** * The `wordexp` function, which can perform command substitution. @@ -35,24 +35,24 @@ private predicate isCommandSubstitutionDisabled(FunctionCall fc) { /** * A configuration to track user-supplied data to the `wordexp` function. */ -class WordexpTaintConfiguration extends TaintTracking::Configuration { - WordexpTaintConfiguration() { this = "WordexpTaintConfiguration" } +module WordexpTaintConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof FlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof FlowSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction | fc.getArgument(0) = sink.asExpr() and not isCommandSubstitutionDisabled(fc) ) } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.asExpr().getUnspecifiedType() instanceof IntegralType } } -from WordexpTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode -where conf.hasFlowPath(sourceNode, sinkNode) +module WordexpTaint = TaintTracking::Make; + +from WordexpTaint::PathNode sourceNode, WordexpTaint::PathNode sinkNode +where WordexpTaint::hasFlowPath(sourceNode, sinkNode) select sinkNode.getNode(), sourceNode, sinkNode, "Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection." diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql index 7de48c0d1e1..71958eaad91 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-190/AllocMultiplicationOverflow.ql @@ -14,13 +14,11 @@ import cpp import semmle.code.cpp.models.interfaces.Allocation -import semmle.code.cpp.dataflow.DataFlow -import DataFlow::PathGraph +import semmle.code.cpp.ir.dataflow.DataFlow +import MultToAlloc::PathGraph -class MultToAllocConfig extends DataFlow::Configuration { - MultToAllocConfig() { this = "MultToAllocConfig" } - - override predicate isSource(DataFlow::Node node) { +module MultToAllocConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { // a multiplication of two non-constant expressions exists(MulExpr me | me = node.asExpr() and @@ -28,14 +26,16 @@ class MultToAllocConfig extends DataFlow::Configuration { ) } - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { // something that affects an allocation size node.asExpr() = any(HeuristicAllocationExpr ae).getSizeExpr().getAChild*() } } -from MultToAllocConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +module MultToAlloc = DataFlow::Make; + +from MultToAlloc::PathNode source, MultToAlloc::PathNode sink +where MultToAlloc::hasFlowPath(source, sink) select sink, source, sink, "Potentially overflowing value from $@ is used in the size of this allocation.", source, "multiplication" diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql index b7c2810541f..bdf8d175a48 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql @@ -14,8 +14,8 @@ import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis import experimental.semmle.code.cpp.semantic.SemanticBound import experimental.semmle.code.cpp.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR -import experimental.semmle.code.cpp.ir.dataflow.DataFlow -import experimental.semmle.code.cpp.ir.dataflow.DataFlow2 +import semmle.code.cpp.ir.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow2 import DataFlow2::PathGraph pragma[nomagic] diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql index 8ecd855a3bc..a35ed79a440 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -17,7 +17,7 @@ import cpp import experimental.semmle.code.cpp.dataflow.ProductFlow -import experimental.semmle.code.cpp.ir.dataflow.DataFlow3 +import semmle.code.cpp.ir.dataflow.DataFlow3 import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis import experimental.semmle.code.cpp.semantic.SemanticBound import experimental.semmle.code.cpp.semantic.SemanticExprSpecific diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-285/PamAuthorization.ql b/cpp/ql/src/experimental/Security/CWE/CWE-285/PamAuthorization.ql index 59c4a68c92a..d605aa5e066 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-285/PamAuthorization.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-285/PamAuthorization.ql @@ -10,7 +10,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.valuenumbering.GlobalValueNumbering private class PamAuthCall extends FunctionCall { diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql index 273e3b7855a..c09277f38f2 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-359/PrivateCleartextWrite.ql @@ -13,10 +13,10 @@ import cpp import experimental.semmle.code.cpp.security.PrivateCleartextWrite import experimental.semmle.code.cpp.security.PrivateCleartextWrite::PrivateCleartextWrite -import DataFlow::PathGraph +import WriteFlow::PathGraph -from WriteConfig b, DataFlow::PathNode source, DataFlow::PathNode sink -where b.hasFlowPath(source, sink) +from WriteFlow::PathNode source, WriteFlow::PathNode sink +where WriteFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This write into the external location '" + sink.getNode() + "' may contain unencrypted data from $@.", source, "this source of private data." diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql index a6b70d9c506..9b9684f12e2 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-415/DoubleFree.ql @@ -14,8 +14,8 @@ import cpp from FunctionCall fc, FunctionCall fc2, LocalScopeVariable v where - freeCall(fc, v.getAnAccess()) and - freeCall(fc2, v.getAnAccess()) and + fc.(DeallocationExpr).getFreedExpr() = v.getAnAccess() and + fc2.(DeallocationExpr).getFreedExpr() = v.getAnAccess() and fc != fc2 and fc.getASuccessor*() = fc2 and not exists(Expr exptmp | diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-787/UnsignedToSignedPointerArith.ql b/cpp/ql/src/experimental/Security/CWE/CWE-787/UnsignedToSignedPointerArith.ql index 8cc1a1ec497..d0a362564b0 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-787/UnsignedToSignedPointerArith.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-787/UnsignedToSignedPointerArith.ql @@ -11,7 +11,7 @@ */ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow import semmle.code.cpp.security.Overflow from FunctionCall call, Function f, Parameter p, DataFlow::Node sink, PointerArithmeticOperation pao diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql index 083d7b1a669..cfb60d7ca90 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-788/AccessOfMemoryLocationAfterEndOfBufferUsingStrlen.ql @@ -14,7 +14,7 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow from StrlenCall fc, AssignExpr expr, ArrayExpr exprarr where diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml index 025587014e6..9c312b5a568 100644 --- a/cpp/ql/src/qlpack.yml +++ b/cpp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/cpp-queries -version: 0.5.4-dev +version: 0.5.5-dev groups: - cpp - queries diff --git a/cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll b/cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll index c765ba89a00..d2172604384 100644 --- a/cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll +++ b/cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll @@ -25,7 +25,12 @@ class IRFlowTest extends InlineExpectationsTest { exists(IRDataFlow::Node source, IRDataFlow::Node sink, IRDataFlow::Configuration conf, int n | tag = "ir" and conf.hasFlow(source, sink) and - n = strictcount(IRDataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and + n = + strictcount(int line, int column | + conf.hasFlow(any(IRDataFlow::Node otherSource | + otherSource.hasLocationInfo(_, line, column, _, _) + ), sink) + ) and ( n = 1 and value = "" or @@ -53,7 +58,12 @@ class AstFlowTest extends InlineExpectationsTest { | tag = "ast" and conf.hasFlow(source, sink) and - n = strictcount(AstDataFlow::Node otherSource | conf.hasFlow(otherSource, sink)) and + n = + strictcount(int line, int column | + conf.hasFlow(any(AstDataFlow::Node otherSource | + otherSource.hasLocationInfo(_, line, column, _, _) + ), sink) + ) and ( n = 1 and value = "" or diff --git a/cpp/ql/test/examples/docs-examples/README.md b/cpp/ql/test/examples/docs-examples/README.md new file mode 100644 index 00000000000..c89cea75bce --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/README.md @@ -0,0 +1,2 @@ +This directory contains the C++ demo queries from the docs directory. +Maintaining this copy should ensure that they continue to work. diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.expected new file mode 100644 index 00000000000..b9b4ea0c4ce --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.expected @@ -0,0 +1,2 @@ +| gethostbyname.cpp:6:25:6:44 | https://github.com | gethostbyname.cpp:11:23:11:35 | call to gethostbyname | +| gethostbyname.cpp:9:37:9:56 | https://github.com | gethostbyname.cpp:9:23:9:35 | call to gethostbyname | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.ql new file mode 100644 index 00000000000..8ff24b8a8f0 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise1.ql @@ -0,0 +1,10 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink +where + fc.getTarget().hasName("gethostbyname") and + source.asIndirectExpr(1) = sl and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) +select sl, fc diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.expected new file mode 100644 index 00000000000..b9b4ea0c4ce --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.expected @@ -0,0 +1,2 @@ +| gethostbyname.cpp:6:25:6:44 | https://github.com | gethostbyname.cpp:11:23:11:35 | call to gethostbyname | +| gethostbyname.cpp:9:37:9:56 | https://github.com | gethostbyname.cpp:9:23:9:35 | call to gethostbyname | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql new file mode 100644 index 00000000000..10c0bcf5ee8 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise2.ql @@ -0,0 +1,26 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +class LiteralToGethostbynameConfiguration extends DataFlow::Configuration { + LiteralToGethostbynameConfiguration() { this = "LiteralToGethostbynameConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source.asIndirectExpr(1) instanceof StringLiteral + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasName("gethostbyname") + ) + } +} + +from + StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg, DataFlow::Node source, + DataFlow::Node sink +where + source.asIndirectExpr(1) = sl and + sink.asIndirectExpr(1) = fc.getArgument(0) and + cfg.hasFlow(source, sink) +select sl, fc diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.expected new file mode 100644 index 00000000000..e012df73807 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.expected @@ -0,0 +1,2 @@ +| gethostbyname.cpp:7:30:7:35 | call to getenv | gethostbyname.cpp:13:23:13:35 | call to gethostbyname | +| gethostbyname.cpp:12:37:12:42 | call to getenv | gethostbyname.cpp:12:23:12:35 | call to gethostbyname | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql new file mode 100644 index 00000000000..09c01b953e3 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/exercise4.ql @@ -0,0 +1,28 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +class GetenvSource extends DataFlow::Node { + GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") } +} + +class GetenvToGethostbynameConfiguration extends DataFlow::Configuration { + GetenvToGethostbynameConfiguration() { this = "GetenvToGethostbynameConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof GetenvSource } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasName("gethostbyname") + ) + } +} + +from + Expr getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg, DataFlow::Node source, + DataFlow::Node sink +where + source.asIndirectExpr(1) = getenv and + sink.asIndirectExpr(1) = fc.getArgument(0) and + cfg.hasFlow(source, sink) +select getenv, fc diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.expected new file mode 100644 index 00000000000..7493f891ef5 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.expected @@ -0,0 +1,10 @@ +| fopen.cpp:6:30:6:37 | a_file | +| fopen.cpp:8:26:8:33 | a_file | +| fopen.cpp:9:26:9:34 | filename1 | +| fopen.cpp:10:26:10:34 | filename2 | +| fopen.cpp:18:18:18:25 | filename | +| fopen.cpp:23:30:23:38 | call to do_getenv | +| fopen.cpp:24:30:24:35 | call to getenv | +| fopen.cpp:27:26:27:31 | call to getenv | +| fopen.cpp:28:26:28:34 | filename1 | +| fopen.cpp:29:26:29:34 | filename2 | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.ql new file mode 100644 index 00000000000..9f552574972 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-expr.ql @@ -0,0 +1,11 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +from Function fopen, FunctionCall fc, Expr src, DataFlow::Node source, DataFlow::Node sink +where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen and + source.asIndirectExpr(1) = src and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) +select src diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.expected new file mode 100644 index 00000000000..f86ad2557fa --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.expected @@ -0,0 +1,5 @@ +| fopen.cpp:18:18:18:25 | filename | This 'fopen' uses data from $@. | fopen.cpp:25:30:25:35 | call to getenv | call to 'getenv' | +| fopen.cpp:18:18:18:25 | filename | This 'fopen' uses data from $@. | fopen.cpp:30:29:30:34 | call to getenv | call to 'getenv' | +| fopen.cpp:27:26:27:31 | call to getenv | This 'fopen' uses data from $@. | fopen.cpp:27:26:27:31 | call to getenv | call to 'getenv' | +| fopen.cpp:28:26:28:34 | filename1 | This 'fopen' uses data from $@. | fopen.cpp:14:12:14:17 | call to getenv | call to 'getenv' | +| fopen.cpp:29:26:29:34 | filename2 | This 'fopen' uses data from $@. | fopen.cpp:24:30:24:35 | call to getenv | call to 'getenv' | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql new file mode 100644 index 00000000000..d21ae4ae52e --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-getenv.ql @@ -0,0 +1,29 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +class EnvironmentToFileConfiguration extends DataFlow::Configuration { + EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" } + + override predicate isSource(DataFlow::Node source) { + exists(Function getenv | + source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and + getenv.hasGlobalName("getenv") + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasGlobalName("fopen") + ) + } +} + +from + Expr getenv, Expr fopen, EnvironmentToFileConfiguration config, DataFlow::Node source, + DataFlow::Node sink +where + source.asIndirectExpr(1) = getenv and + sink.asIndirectExpr(1) = fopen and + config.hasFlow(source, sink) +select fopen, "This 'fopen' uses data from $@.", getenv, "call to 'getenv'" diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.expected new file mode 100644 index 00000000000..0398843f3d4 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.expected @@ -0,0 +1,2 @@ +| fopen.cpp:5:24:5:32 | filename1 | +| fopen.cpp:17:30:17:37 | filename | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.ql new file mode 100644 index 00000000000..423645ae0a9 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-flow-from-param.ql @@ -0,0 +1,11 @@ +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +from Function fopen, FunctionCall fc, Parameter p, DataFlow::Node source, DataFlow::Node sink +where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen and + source.asParameter(1) = p and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) +select p diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.expected new file mode 100644 index 00000000000..47cc0ee6c93 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.expected @@ -0,0 +1,7 @@ +| fopen.cpp:8:26:8:33 | a_file | +| fopen.cpp:9:26:9:34 | filename1 | +| fopen.cpp:10:26:10:34 | filename2 | +| fopen.cpp:18:18:18:25 | filename | +| fopen.cpp:27:26:27:31 | call to getenv | +| fopen.cpp:28:26:28:34 | filename1 | +| fopen.cpp:29:26:29:34 | filename2 | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.ql new file mode 100644 index 00000000000..48c124352b7 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen-no-flow.ql @@ -0,0 +1,7 @@ +import cpp + +from Function fopen, FunctionCall fc +where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen +select fc.getArgument(0) diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen.cpp b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen.cpp new file mode 100644 index 00000000000..33edc8c1b7d --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/fopen.cpp @@ -0,0 +1,32 @@ +struct FILE; +FILE *fopen(const char * path, const char * mode); +char * getenv(const char * name); + +void test_fopen(char * filename1) { + const char * filename2 = "a_file"; + + FILE * file0 = fopen("a_file", "r"); + FILE * file1 = fopen(filename1, "r"); + FILE * file2 = fopen(filename2, "r"); +} + +const char * do_getenv() { + return getenv("FILENAME1"); +} + +FILE * do_fopen(const char * filename) { + return fopen(filename, "r"); +} + +void test_getenv() +{ + const char * filename1 = do_getenv(); + const char * filename2 = getenv("FILENAME2"); + const char * filename4 = getenv("FILENAME4"); + + FILE * file0 = fopen(getenv("FILENAME0"), "r"); + FILE * file1 = fopen(filename1, "r"); + FILE * file2 = fopen(filename2, "r"); + FILE * file3 = do_fopen(getenv("FILENAME3")); + FILE * file4 = do_fopen(filename4); +} diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/gethostbyname.cpp b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/gethostbyname.cpp new file mode 100644 index 00000000000..fded85ba8f9 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/gethostbyname.cpp @@ -0,0 +1,14 @@ +struct hostent; +hostent * gethostbyname(const char * name); +char * getenv(const char * name); + +void test_gethostbyname(const char * url1) { + const char * url2 = "https://github.com"; + const char * hostname1 = getenv("HOSTNAME1"); + + hostent * host0 = gethostbyname("https://github.com"); + hostent * host1 = gethostbyname(url1); + hostent * host2 = gethostbyname(url2); + hostent * host3 = gethostbyname(getenv("HOSTNAME0")); + hostent * host4 = gethostbyname(hostname1); +} diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.expected new file mode 100644 index 00000000000..8cf81e6a6dc --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.expected @@ -0,0 +1,2 @@ +| ntohl.cpp:10:20:10:28 | hostlong0 | This array offset may be influenced by $@. | ntohl.cpp:6:30:6:34 | call to ntohl | converted data from the network | +| ntohl.cpp:17:24:17:24 | i | This array offset may be influenced by $@. | ntohl.cpp:8:30:8:34 | call to ntohl | converted data from the network | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql new file mode 100644 index 00000000000..e6452137053 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/index-flow-from-ntohl.ql @@ -0,0 +1,38 @@ +import cpp +import semmle.code.cpp.controlflow.Guards +import semmle.code.cpp.dataflow.new.TaintTracking + +class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration { + NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" } + + override predicate isSource(DataFlow::Node node) { + node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl") + } + + override predicate isSink(DataFlow::Node node) { + exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset()) + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Loop loop, LoopCounter lc | + loop = lc.getALoop() and + loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr() + | + succ.asExpr() = lc.getVariableAccessInLoop(loop) + ) + } + + override predicate isSanitizer(DataFlow::Node node) { + exists(GuardCondition gc, Variable v | + gc.getAChild*() = v.getAnAccess() and + node.asExpr() = v.getAnAccess() and + gc.controls(node.asExpr().getBasicBlock(), _) and + not exists(Loop loop | loop.getControllingExpr() = gc) + ) + } +} + +from DataFlow::Node ntohl, DataFlow::Node offset, NetworkToBufferSizeConfiguration conf +where conf.hasFlow(ntohl, offset) +select offset, "This array offset may be influenced by $@.", ntohl, + "converted data from the network" diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/ntohl.cpp b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/ntohl.cpp new file mode 100644 index 00000000000..3cc354a8b32 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/ntohl.cpp @@ -0,0 +1,19 @@ +unsigned int ntohl(unsigned int netlong); + +void test_ntohl( + unsigned int netlong0, unsigned int netlong1, unsigned int netlong2, + int * arr, unsigned int arr_size) { + unsigned int hostlong0 = ntohl(netlong0); + unsigned int hostlong1 = ntohl(netlong1); + unsigned int hostlong2 = ntohl(netlong2); + + int val0 = arr[hostlong0]; + + if (hostlong1 < arr_size) { + int val1 = arr[hostlong1]; + } + + for (unsigned int i = 0; i < hostlong2; ++i) { + int val2 = arr[i]; + } +} diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.expected b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.expected new file mode 100644 index 00000000000..57d3172769b --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.expected @@ -0,0 +1,2 @@ +| printf.cpp:5:5:5:10 | call to printf | Argument to printf isn't hard-coded. | +| printf.cpp:6:5:6:10 | call to printf | Argument to printf isn't hard-coded. | diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.ql b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.ql new file mode 100644 index 00000000000..cd2c7238fc1 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf-format-not-hard-coded.ql @@ -0,0 +1,13 @@ +import semmle.code.cpp.dataflow.new.DataFlow +import semmle.code.cpp.commons.Printf + +from FormattingFunction format, FunctionCall call, Expr formatString, DataFlow::Node sink +where + call.getTarget() = format and + call.getArgument(format.getFormatParameterIndex()) = formatString and + sink.asIndirectExpr(1) = formatString and + not exists(DataFlow::Node source | + DataFlow::localFlow(source, sink) and + source.asIndirectExpr(1) instanceof StringLiteral + ) +select call, "Argument to " + format.getQualifiedName() + " isn't hard-coded." diff --git a/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf.cpp b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf.cpp new file mode 100644 index 00000000000..19d7f5c1132 --- /dev/null +++ b/cpp/ql/test/examples/docs-examples/analyzing-data-flow-in-cpp/printf.cpp @@ -0,0 +1,11 @@ +int printf(const char * format, ...); + +void test_printf(const char * fmt1, bool choice, const char * str) { + printf("%s", str); + printf(fmt1, str); + printf(choice ? "%s" : "%s\n", str); + + return; + + printf("%s", str); // Unreachable +} diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected index 69985fd2791..e69de29bb2d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/NoCheckBeforeUnsafePutUser.expected @@ -1,3 +0,0 @@ -| test.cpp:20:21:20:22 | ref arg & ... | This 'unsafe_put_user' writes a user-mode pointer without a security check. | -| test.cpp:41:21:41:22 | ref arg & ... | This 'unsafe_put_user' writes a user-mode pointer without a security check. | -| test.cpp:69:21:69:27 | ref arg & ... | This 'unsafe_put_user' writes a user-mode pointer without a security check. | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp index 277b9a545e2..f474b33c65d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-020/NoCheckBeforeUnsafePutUser/test.cpp @@ -19,7 +19,7 @@ void test1(int p) { sys_somesystemcall(&p); - unsafe_put_user(123, &p); // BAD + unsafe_put_user(123, &p); // BAD [NOT DETECTED] } void test2(int p) @@ -40,7 +40,7 @@ void test3() sys_somesystemcall(&v); - unsafe_put_user(123, &v); // BAD + unsafe_put_user(123, &v); // BAD [NOT DETECTED] } void test4() @@ -68,7 +68,7 @@ void test5() sys_somesystemcall(&myData); - unsafe_put_user(123, &(myData.x)); // BAD + unsafe_put_user(123, &(myData.x)); // BAD [NOT DETECTED] } void test6() diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-078/WordexpTainted.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-078/WordexpTainted.expected index b9b424f4513..bf126e4656d 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-078/WordexpTainted.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-078/WordexpTainted.expected @@ -1,11 +1,16 @@ edges -| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | (const char *)... | | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | +| test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | +| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | +| test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | nodes | test.cpp:22:27:22:30 | argv | semmle.label | argv | -| test.cpp:29:13:29:20 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:22:27:22:30 | argv indirection | semmle.label | argv indirection | +| test.cpp:29:13:29:20 | filePath | semmle.label | filePath | | test.cpp:29:13:29:20 | filePath | semmle.label | filePath | subpaths #select -| test.cpp:29:13:29:20 | (const char *)... | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | (const char *)... | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | | test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | +| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | +| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | +| test.cpp:29:13:29:20 | filePath | test.cpp:22:27:22:30 | argv indirection | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected index 0f852e37cf6..93351da51f1 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-119/OverrunWriteProductFlow.expected @@ -1,344 +1,393 @@ edges -| test.cpp:16:11:16:21 | VariableAddress indirection [string] | test.cpp:24:21:24:31 | Call indirection [string] | -| test.cpp:16:11:16:21 | VariableAddress indirection [string] | test.cpp:34:21:34:31 | Call indirection [string] | -| test.cpp:16:11:16:21 | VariableAddress indirection [string] | test.cpp:39:21:39:31 | Call indirection [string] | -| test.cpp:18:5:18:30 | Store | test.cpp:18:10:18:15 | Load indirection [post update] [string] | -| test.cpp:18:10:18:15 | Load indirection [post update] [string] | test.cpp:16:11:16:21 | VariableAddress indirection [string] | -| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | Store | -| test.cpp:24:21:24:31 | Call indirection [string] | test.cpp:26:13:26:15 | Load indirection [string] | -| test.cpp:26:13:26:15 | Load indirection [string] | test.cpp:26:18:26:23 | FieldAddress indirection | -| test.cpp:26:18:26:23 | FieldAddress indirection | test.cpp:26:18:26:23 | Load | -| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | Load indirection [string] | -| test.cpp:30:13:30:15 | Load indirection [string] | test.cpp:30:18:30:23 | FieldAddress indirection | -| test.cpp:30:18:30:23 | FieldAddress indirection | test.cpp:30:18:30:23 | Load | -| test.cpp:34:21:34:31 | Call indirection [string] | test.cpp:35:21:35:23 | str indirection [string] | +| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | +| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | +| test.cpp:16:11:16:21 | mk_string_t indirection [string] | test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | +| test.cpp:18:5:18:30 | ... = ... | test.cpp:18:10:18:15 | str indirection [post update] [string] | +| test.cpp:18:10:18:15 | str indirection [post update] [string] | test.cpp:16:11:16:21 | mk_string_t indirection [string] | +| test.cpp:18:19:18:24 | call to malloc | test.cpp:18:5:18:30 | ... = ... | +| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | test.cpp:26:13:26:15 | str indirection [string] | +| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string | +| test.cpp:26:13:26:15 | str indirection [string] | test.cpp:26:18:26:23 | string indirection | +| test.cpp:26:18:26:23 | string indirection | test.cpp:26:18:26:23 | string | +| test.cpp:29:32:29:34 | str indirection [string] | test.cpp:30:13:30:15 | str indirection [string] | +| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string | +| test.cpp:30:13:30:15 | str indirection [string] | test.cpp:30:18:30:23 | string indirection | +| test.cpp:30:18:30:23 | string indirection | test.cpp:30:18:30:23 | string | +| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | test.cpp:35:21:35:23 | str indirection [string] | | test.cpp:35:21:35:23 | str indirection [string] | test.cpp:29:32:29:34 | str indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:41:13:41:15 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:42:13:42:15 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:44:13:44:15 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:45:13:45:15 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:48:17:48:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:52:17:52:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:56:17:56:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:60:17:60:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:64:17:64:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:68:17:68:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:72:17:72:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:76:17:76:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:80:17:80:19 | Load indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | test.cpp:84:17:84:19 | Load indirection [string] | -| test.cpp:41:13:41:15 | Load indirection [string] | test.cpp:41:18:41:23 | FieldAddress indirection | -| test.cpp:41:18:41:23 | FieldAddress indirection | test.cpp:41:18:41:23 | Load | -| test.cpp:42:13:42:15 | Load indirection [string] | test.cpp:42:18:42:23 | FieldAddress indirection | -| test.cpp:42:18:42:23 | FieldAddress indirection | test.cpp:42:18:42:23 | Load | -| test.cpp:44:13:44:15 | Load indirection [string] | test.cpp:44:18:44:23 | FieldAddress indirection | -| test.cpp:44:18:44:23 | FieldAddress indirection | test.cpp:44:18:44:23 | Load | -| test.cpp:45:13:45:15 | Load indirection [string] | test.cpp:45:18:45:23 | FieldAddress indirection | -| test.cpp:45:18:45:23 | FieldAddress indirection | test.cpp:45:18:45:23 | Load | -| test.cpp:48:17:48:19 | Load indirection [string] | test.cpp:48:22:48:27 | FieldAddress indirection | -| test.cpp:48:22:48:27 | FieldAddress indirection | test.cpp:48:22:48:27 | Load | -| test.cpp:52:17:52:19 | Load indirection [string] | test.cpp:52:22:52:27 | FieldAddress indirection | -| test.cpp:52:22:52:27 | FieldAddress indirection | test.cpp:52:22:52:27 | Load | -| test.cpp:56:17:56:19 | Load indirection [string] | test.cpp:56:22:56:27 | FieldAddress indirection | -| test.cpp:56:22:56:27 | FieldAddress indirection | test.cpp:56:22:56:27 | Load | -| test.cpp:60:17:60:19 | Load indirection [string] | test.cpp:60:22:60:27 | FieldAddress indirection | -| test.cpp:60:22:60:27 | FieldAddress indirection | test.cpp:60:22:60:27 | Load | -| test.cpp:64:17:64:19 | Load indirection [string] | test.cpp:64:22:64:27 | FieldAddress indirection | -| test.cpp:64:22:64:27 | FieldAddress indirection | test.cpp:64:22:64:27 | Load | -| test.cpp:68:17:68:19 | Load indirection [string] | test.cpp:68:22:68:27 | FieldAddress indirection | -| test.cpp:68:22:68:27 | FieldAddress indirection | test.cpp:68:22:68:27 | Load | -| test.cpp:72:17:72:19 | Load indirection [string] | test.cpp:72:22:72:27 | FieldAddress indirection | -| test.cpp:72:22:72:27 | FieldAddress indirection | test.cpp:72:22:72:27 | Load | -| test.cpp:76:17:76:19 | Load indirection [string] | test.cpp:76:22:76:27 | FieldAddress indirection | -| test.cpp:76:22:76:27 | FieldAddress indirection | test.cpp:76:22:76:27 | Load | -| test.cpp:80:17:80:19 | Load indirection [string] | test.cpp:80:22:80:27 | FieldAddress indirection | -| test.cpp:80:22:80:27 | FieldAddress indirection | test.cpp:80:22:80:27 | Load | -| test.cpp:84:17:84:19 | Load indirection [string] | test.cpp:84:22:84:27 | FieldAddress indirection | -| test.cpp:84:22:84:27 | FieldAddress indirection | test.cpp:84:22:84:27 | Load | -| test.cpp:88:11:88:30 | VariableAddress indirection [string] | test.cpp:96:21:96:40 | Call indirection [string] | -| test.cpp:90:5:90:34 | Store | test.cpp:90:10:90:15 | Load indirection [post update] [string] | -| test.cpp:90:10:90:15 | Load indirection [post update] [string] | test.cpp:88:11:88:30 | VariableAddress indirection [string] | -| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | Store | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:98:13:98:15 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:99:13:99:15 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:101:13:101:15 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:102:13:102:15 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:105:17:105:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:109:17:109:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:113:17:113:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:117:17:117:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:121:17:121:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:125:17:125:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:129:17:129:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:133:17:133:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:137:17:137:19 | Load indirection [string] | -| test.cpp:96:21:96:40 | Call indirection [string] | test.cpp:141:17:141:19 | Load indirection [string] | -| test.cpp:98:13:98:15 | Load indirection [string] | test.cpp:98:18:98:23 | FieldAddress indirection | -| test.cpp:98:18:98:23 | FieldAddress indirection | test.cpp:98:18:98:23 | Load | -| test.cpp:99:13:99:15 | Load indirection [string] | test.cpp:99:18:99:23 | FieldAddress indirection | -| test.cpp:99:18:99:23 | FieldAddress indirection | test.cpp:99:18:99:23 | Load | -| test.cpp:101:13:101:15 | Load indirection [string] | test.cpp:101:18:101:23 | FieldAddress indirection | -| test.cpp:101:18:101:23 | FieldAddress indirection | test.cpp:101:18:101:23 | Load | -| test.cpp:102:13:102:15 | Load indirection [string] | test.cpp:102:18:102:23 | FieldAddress indirection | -| test.cpp:102:18:102:23 | FieldAddress indirection | test.cpp:102:18:102:23 | Load | -| test.cpp:105:17:105:19 | Load indirection [string] | test.cpp:105:22:105:27 | FieldAddress indirection | -| test.cpp:105:22:105:27 | FieldAddress indirection | test.cpp:105:22:105:27 | Load | -| test.cpp:109:17:109:19 | Load indirection [string] | test.cpp:109:22:109:27 | FieldAddress indirection | -| test.cpp:109:22:109:27 | FieldAddress indirection | test.cpp:109:22:109:27 | Load | -| test.cpp:113:17:113:19 | Load indirection [string] | test.cpp:113:22:113:27 | FieldAddress indirection | -| test.cpp:113:22:113:27 | FieldAddress indirection | test.cpp:113:22:113:27 | Load | -| test.cpp:117:17:117:19 | Load indirection [string] | test.cpp:117:22:117:27 | FieldAddress indirection | -| test.cpp:117:22:117:27 | FieldAddress indirection | test.cpp:117:22:117:27 | Load | -| test.cpp:121:17:121:19 | Load indirection [string] | test.cpp:121:22:121:27 | FieldAddress indirection | -| test.cpp:121:22:121:27 | FieldAddress indirection | test.cpp:121:22:121:27 | Load | -| test.cpp:125:17:125:19 | Load indirection [string] | test.cpp:125:22:125:27 | FieldAddress indirection | -| test.cpp:125:22:125:27 | FieldAddress indirection | test.cpp:125:22:125:27 | Load | -| test.cpp:129:17:129:19 | Load indirection [string] | test.cpp:129:22:129:27 | FieldAddress indirection | -| test.cpp:129:22:129:27 | FieldAddress indirection | test.cpp:129:22:129:27 | Load | -| test.cpp:133:17:133:19 | Load indirection [string] | test.cpp:133:22:133:27 | FieldAddress indirection | -| test.cpp:133:22:133:27 | FieldAddress indirection | test.cpp:133:22:133:27 | Load | -| test.cpp:137:17:137:19 | Load indirection [string] | test.cpp:137:22:137:27 | FieldAddress indirection | -| test.cpp:137:22:137:27 | FieldAddress indirection | test.cpp:137:22:137:27 | Load | -| test.cpp:141:17:141:19 | Load indirection [string] | test.cpp:141:22:141:27 | FieldAddress indirection | -| test.cpp:141:22:141:27 | FieldAddress indirection | test.cpp:141:22:141:27 | Load | -| test.cpp:147:5:147:34 | Store | test.cpp:147:10:147:15 | Load indirection [post update] [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:150:13:150:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:151:13:151:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:152:13:152:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:154:13:154:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:155:13:155:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:156:13:156:15 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:159:17:159:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:163:17:163:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:167:17:167:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:171:17:171:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:175:17:175:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:179:17:179:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:183:17:183:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:187:17:187:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:191:17:191:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:195:17:195:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:199:17:199:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:203:17:203:19 | Load indirection [string] | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | test.cpp:207:17:207:19 | Load indirection [string] | -| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | Store | -| test.cpp:150:13:150:15 | Load indirection [string] | test.cpp:150:18:150:23 | FieldAddress indirection | -| test.cpp:150:18:150:23 | FieldAddress indirection | test.cpp:150:18:150:23 | Load | -| test.cpp:151:13:151:15 | Load indirection [string] | test.cpp:151:18:151:23 | FieldAddress indirection | -| test.cpp:151:18:151:23 | FieldAddress indirection | test.cpp:151:18:151:23 | Load | -| test.cpp:152:13:152:15 | Load indirection [string] | test.cpp:152:18:152:23 | FieldAddress indirection | -| test.cpp:152:18:152:23 | FieldAddress indirection | test.cpp:152:18:152:23 | Load | -| test.cpp:154:13:154:15 | Load indirection [string] | test.cpp:154:18:154:23 | FieldAddress indirection | -| test.cpp:154:18:154:23 | FieldAddress indirection | test.cpp:154:18:154:23 | Load | -| test.cpp:155:13:155:15 | Load indirection [string] | test.cpp:155:18:155:23 | FieldAddress indirection | -| test.cpp:155:18:155:23 | FieldAddress indirection | test.cpp:155:18:155:23 | Load | -| test.cpp:156:13:156:15 | Load indirection [string] | test.cpp:156:18:156:23 | FieldAddress indirection | -| test.cpp:156:18:156:23 | FieldAddress indirection | test.cpp:156:18:156:23 | Load | -| test.cpp:159:17:159:19 | Load indirection [string] | test.cpp:159:22:159:27 | FieldAddress indirection | -| test.cpp:159:22:159:27 | FieldAddress indirection | test.cpp:159:22:159:27 | Load | -| test.cpp:163:17:163:19 | Load indirection [string] | test.cpp:163:22:163:27 | FieldAddress indirection | -| test.cpp:163:22:163:27 | FieldAddress indirection | test.cpp:163:22:163:27 | Load | -| test.cpp:167:17:167:19 | Load indirection [string] | test.cpp:167:22:167:27 | FieldAddress indirection | -| test.cpp:167:22:167:27 | FieldAddress indirection | test.cpp:167:22:167:27 | Load | -| test.cpp:171:17:171:19 | Load indirection [string] | test.cpp:171:22:171:27 | FieldAddress indirection | -| test.cpp:171:22:171:27 | FieldAddress indirection | test.cpp:171:22:171:27 | Load | -| test.cpp:175:17:175:19 | Load indirection [string] | test.cpp:175:22:175:27 | FieldAddress indirection | -| test.cpp:175:22:175:27 | FieldAddress indirection | test.cpp:175:22:175:27 | Load | -| test.cpp:179:17:179:19 | Load indirection [string] | test.cpp:179:22:179:27 | FieldAddress indirection | -| test.cpp:179:22:179:27 | FieldAddress indirection | test.cpp:179:22:179:27 | Load | -| test.cpp:183:17:183:19 | Load indirection [string] | test.cpp:183:22:183:27 | FieldAddress indirection | -| test.cpp:183:22:183:27 | FieldAddress indirection | test.cpp:183:22:183:27 | Load | -| test.cpp:187:17:187:19 | Load indirection [string] | test.cpp:187:22:187:27 | FieldAddress indirection | -| test.cpp:187:22:187:27 | FieldAddress indirection | test.cpp:187:22:187:27 | Load | -| test.cpp:191:17:191:19 | Load indirection [string] | test.cpp:191:22:191:27 | FieldAddress indirection | -| test.cpp:191:22:191:27 | FieldAddress indirection | test.cpp:191:22:191:27 | Load | -| test.cpp:195:17:195:19 | Load indirection [string] | test.cpp:195:22:195:27 | FieldAddress indirection | -| test.cpp:195:22:195:27 | FieldAddress indirection | test.cpp:195:22:195:27 | Load | -| test.cpp:199:17:199:19 | Load indirection [string] | test.cpp:199:22:199:27 | FieldAddress indirection | -| test.cpp:199:22:199:27 | FieldAddress indirection | test.cpp:199:22:199:27 | Load | -| test.cpp:203:17:203:19 | Load indirection [string] | test.cpp:203:22:203:27 | FieldAddress indirection | -| test.cpp:203:22:203:27 | FieldAddress indirection | test.cpp:203:22:203:27 | Load | -| test.cpp:207:17:207:19 | Load indirection [string] | test.cpp:207:22:207:27 | FieldAddress indirection | -| test.cpp:207:22:207:27 | FieldAddress indirection | test.cpp:207:22:207:27 | Load | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:41:13:41:15 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:42:13:42:15 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:44:13:44:15 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:45:13:45:15 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:48:17:48:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:52:17:52:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:56:17:56:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:60:17:60:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:64:17:64:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:68:17:68:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:72:17:72:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:76:17:76:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:80:17:80:19 | str indirection [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | test.cpp:84:17:84:19 | str indirection [string] | +| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string | +| test.cpp:41:13:41:15 | str indirection [string] | test.cpp:41:18:41:23 | string indirection | +| test.cpp:41:18:41:23 | string indirection | test.cpp:41:18:41:23 | string | +| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string | +| test.cpp:42:13:42:15 | str indirection [string] | test.cpp:42:18:42:23 | string indirection | +| test.cpp:42:18:42:23 | string indirection | test.cpp:42:18:42:23 | string | +| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string | +| test.cpp:44:13:44:15 | str indirection [string] | test.cpp:44:18:44:23 | string indirection | +| test.cpp:44:18:44:23 | string indirection | test.cpp:44:18:44:23 | string | +| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string | +| test.cpp:45:13:45:15 | str indirection [string] | test.cpp:45:18:45:23 | string indirection | +| test.cpp:45:18:45:23 | string indirection | test.cpp:45:18:45:23 | string | +| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string | +| test.cpp:48:17:48:19 | str indirection [string] | test.cpp:48:22:48:27 | string indirection | +| test.cpp:48:22:48:27 | string indirection | test.cpp:48:22:48:27 | string | +| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string | +| test.cpp:52:17:52:19 | str indirection [string] | test.cpp:52:22:52:27 | string indirection | +| test.cpp:52:22:52:27 | string indirection | test.cpp:52:22:52:27 | string | +| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string | +| test.cpp:56:17:56:19 | str indirection [string] | test.cpp:56:22:56:27 | string indirection | +| test.cpp:56:22:56:27 | string indirection | test.cpp:56:22:56:27 | string | +| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string | +| test.cpp:60:17:60:19 | str indirection [string] | test.cpp:60:22:60:27 | string indirection | +| test.cpp:60:22:60:27 | string indirection | test.cpp:60:22:60:27 | string | +| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string | +| test.cpp:64:17:64:19 | str indirection [string] | test.cpp:64:22:64:27 | string indirection | +| test.cpp:64:22:64:27 | string indirection | test.cpp:64:22:64:27 | string | +| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string | +| test.cpp:68:17:68:19 | str indirection [string] | test.cpp:68:22:68:27 | string indirection | +| test.cpp:68:22:68:27 | string indirection | test.cpp:68:22:68:27 | string | +| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string | +| test.cpp:72:17:72:19 | str indirection [string] | test.cpp:72:22:72:27 | string indirection | +| test.cpp:72:22:72:27 | string indirection | test.cpp:72:22:72:27 | string | +| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string | +| test.cpp:76:17:76:19 | str indirection [string] | test.cpp:76:22:76:27 | string indirection | +| test.cpp:76:22:76:27 | string indirection | test.cpp:76:22:76:27 | string | +| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string | +| test.cpp:80:17:80:19 | str indirection [string] | test.cpp:80:22:80:27 | string indirection | +| test.cpp:80:22:80:27 | string indirection | test.cpp:80:22:80:27 | string | +| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string | +| test.cpp:84:17:84:19 | str indirection [string] | test.cpp:84:22:84:27 | string indirection | +| test.cpp:84:22:84:27 | string indirection | test.cpp:84:22:84:27 | string | +| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | +| test.cpp:90:5:90:34 | ... = ... | test.cpp:90:10:90:15 | str indirection [post update] [string] | +| test.cpp:90:10:90:15 | str indirection [post update] [string] | test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | +| test.cpp:90:19:90:24 | call to malloc | test.cpp:90:5:90:34 | ... = ... | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:98:13:98:15 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:99:13:99:15 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:101:13:101:15 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:102:13:102:15 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:105:17:105:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:109:17:109:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:113:17:113:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:117:17:117:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:121:17:121:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:125:17:125:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:129:17:129:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:133:17:133:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:137:17:137:19 | str indirection [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | test.cpp:141:17:141:19 | str indirection [string] | +| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string | +| test.cpp:98:13:98:15 | str indirection [string] | test.cpp:98:18:98:23 | string indirection | +| test.cpp:98:18:98:23 | string indirection | test.cpp:98:18:98:23 | string | +| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string | +| test.cpp:99:13:99:15 | str indirection [string] | test.cpp:99:18:99:23 | string indirection | +| test.cpp:99:18:99:23 | string indirection | test.cpp:99:18:99:23 | string | +| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string | +| test.cpp:101:13:101:15 | str indirection [string] | test.cpp:101:18:101:23 | string indirection | +| test.cpp:101:18:101:23 | string indirection | test.cpp:101:18:101:23 | string | +| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string | +| test.cpp:102:13:102:15 | str indirection [string] | test.cpp:102:18:102:23 | string indirection | +| test.cpp:102:18:102:23 | string indirection | test.cpp:102:18:102:23 | string | +| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string | +| test.cpp:105:17:105:19 | str indirection [string] | test.cpp:105:22:105:27 | string indirection | +| test.cpp:105:22:105:27 | string indirection | test.cpp:105:22:105:27 | string | +| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string | +| test.cpp:109:17:109:19 | str indirection [string] | test.cpp:109:22:109:27 | string indirection | +| test.cpp:109:22:109:27 | string indirection | test.cpp:109:22:109:27 | string | +| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string | +| test.cpp:113:17:113:19 | str indirection [string] | test.cpp:113:22:113:27 | string indirection | +| test.cpp:113:22:113:27 | string indirection | test.cpp:113:22:113:27 | string | +| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string | +| test.cpp:117:17:117:19 | str indirection [string] | test.cpp:117:22:117:27 | string indirection | +| test.cpp:117:22:117:27 | string indirection | test.cpp:117:22:117:27 | string | +| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string | +| test.cpp:121:17:121:19 | str indirection [string] | test.cpp:121:22:121:27 | string indirection | +| test.cpp:121:22:121:27 | string indirection | test.cpp:121:22:121:27 | string | +| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string | +| test.cpp:125:17:125:19 | str indirection [string] | test.cpp:125:22:125:27 | string indirection | +| test.cpp:125:22:125:27 | string indirection | test.cpp:125:22:125:27 | string | +| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string | +| test.cpp:129:17:129:19 | str indirection [string] | test.cpp:129:22:129:27 | string indirection | +| test.cpp:129:22:129:27 | string indirection | test.cpp:129:22:129:27 | string | +| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string | +| test.cpp:133:17:133:19 | str indirection [string] | test.cpp:133:22:133:27 | string indirection | +| test.cpp:133:22:133:27 | string indirection | test.cpp:133:22:133:27 | string | +| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string | +| test.cpp:137:17:137:19 | str indirection [string] | test.cpp:137:22:137:27 | string indirection | +| test.cpp:137:22:137:27 | string indirection | test.cpp:137:22:137:27 | string | +| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string | +| test.cpp:141:17:141:19 | str indirection [string] | test.cpp:141:22:141:27 | string indirection | +| test.cpp:141:22:141:27 | string indirection | test.cpp:141:22:141:27 | string | +| test.cpp:147:5:147:34 | ... = ... | test.cpp:147:10:147:15 | str indirection [post update] [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:150:13:150:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:151:13:151:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:152:13:152:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:154:13:154:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:155:13:155:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:156:13:156:15 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:159:17:159:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:163:17:163:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:167:17:167:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:171:17:171:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:175:17:175:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:179:17:179:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:183:17:183:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:187:17:187:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:191:17:191:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:195:17:195:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:199:17:199:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:203:17:203:19 | str indirection [string] | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | test.cpp:207:17:207:19 | str indirection [string] | +| test.cpp:147:19:147:24 | call to malloc | test.cpp:147:5:147:34 | ... = ... | +| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string | +| test.cpp:150:13:150:15 | str indirection [string] | test.cpp:150:18:150:23 | string indirection | +| test.cpp:150:18:150:23 | string indirection | test.cpp:150:18:150:23 | string | +| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string | +| test.cpp:151:13:151:15 | str indirection [string] | test.cpp:151:18:151:23 | string indirection | +| test.cpp:151:18:151:23 | string indirection | test.cpp:151:18:151:23 | string | +| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string | +| test.cpp:152:13:152:15 | str indirection [string] | test.cpp:152:18:152:23 | string indirection | +| test.cpp:152:18:152:23 | string indirection | test.cpp:152:18:152:23 | string | +| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string | +| test.cpp:154:13:154:15 | str indirection [string] | test.cpp:154:18:154:23 | string indirection | +| test.cpp:154:18:154:23 | string indirection | test.cpp:154:18:154:23 | string | +| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string | +| test.cpp:155:13:155:15 | str indirection [string] | test.cpp:155:18:155:23 | string indirection | +| test.cpp:155:18:155:23 | string indirection | test.cpp:155:18:155:23 | string | +| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string | +| test.cpp:156:13:156:15 | str indirection [string] | test.cpp:156:18:156:23 | string indirection | +| test.cpp:156:18:156:23 | string indirection | test.cpp:156:18:156:23 | string | +| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string | +| test.cpp:159:17:159:19 | str indirection [string] | test.cpp:159:22:159:27 | string indirection | +| test.cpp:159:22:159:27 | string indirection | test.cpp:159:22:159:27 | string | +| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string | +| test.cpp:163:17:163:19 | str indirection [string] | test.cpp:163:22:163:27 | string indirection | +| test.cpp:163:22:163:27 | string indirection | test.cpp:163:22:163:27 | string | +| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string | +| test.cpp:167:17:167:19 | str indirection [string] | test.cpp:167:22:167:27 | string indirection | +| test.cpp:167:22:167:27 | string indirection | test.cpp:167:22:167:27 | string | +| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string | +| test.cpp:171:17:171:19 | str indirection [string] | test.cpp:171:22:171:27 | string indirection | +| test.cpp:171:22:171:27 | string indirection | test.cpp:171:22:171:27 | string | +| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string | +| test.cpp:175:17:175:19 | str indirection [string] | test.cpp:175:22:175:27 | string indirection | +| test.cpp:175:22:175:27 | string indirection | test.cpp:175:22:175:27 | string | +| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string | +| test.cpp:179:17:179:19 | str indirection [string] | test.cpp:179:22:179:27 | string indirection | +| test.cpp:179:22:179:27 | string indirection | test.cpp:179:22:179:27 | string | +| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string | +| test.cpp:183:17:183:19 | str indirection [string] | test.cpp:183:22:183:27 | string indirection | +| test.cpp:183:22:183:27 | string indirection | test.cpp:183:22:183:27 | string | +| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string | +| test.cpp:187:17:187:19 | str indirection [string] | test.cpp:187:22:187:27 | string indirection | +| test.cpp:187:22:187:27 | string indirection | test.cpp:187:22:187:27 | string | +| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string | +| test.cpp:191:17:191:19 | str indirection [string] | test.cpp:191:22:191:27 | string indirection | +| test.cpp:191:22:191:27 | string indirection | test.cpp:191:22:191:27 | string | +| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string | +| test.cpp:195:17:195:19 | str indirection [string] | test.cpp:195:22:195:27 | string indirection | +| test.cpp:195:22:195:27 | string indirection | test.cpp:195:22:195:27 | string | +| test.cpp:199:17:199:19 | str indirection [string] | test.cpp:199:22:199:27 | string | +| test.cpp:199:17:199:19 | str indirection [string] | test.cpp:199:22:199:27 | string indirection | +| test.cpp:199:22:199:27 | string indirection | test.cpp:199:22:199:27 | string | +| test.cpp:203:17:203:19 | str indirection [string] | test.cpp:203:22:203:27 | string | +| test.cpp:203:17:203:19 | str indirection [string] | test.cpp:203:22:203:27 | string indirection | +| test.cpp:203:22:203:27 | string indirection | test.cpp:203:22:203:27 | string | +| test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string | +| test.cpp:207:17:207:19 | str indirection [string] | test.cpp:207:22:207:27 | string indirection | +| test.cpp:207:22:207:27 | string indirection | test.cpp:207:22:207:27 | string | nodes -| test.cpp:16:11:16:21 | VariableAddress indirection [string] | semmle.label | VariableAddress indirection [string] | -| test.cpp:18:5:18:30 | Store | semmle.label | Store | -| test.cpp:18:10:18:15 | Load indirection [post update] [string] | semmle.label | Load indirection [post update] [string] | +| test.cpp:16:11:16:21 | mk_string_t indirection [string] | semmle.label | mk_string_t indirection [string] | +| test.cpp:18:5:18:30 | ... = ... | semmle.label | ... = ... | +| test.cpp:18:10:18:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:18:19:18:24 | call to malloc | semmle.label | call to malloc | -| test.cpp:24:21:24:31 | Call indirection [string] | semmle.label | Call indirection [string] | -| test.cpp:26:13:26:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:26:18:26:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:26:18:26:23 | Load | semmle.label | Load | +| test.cpp:24:21:24:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | +| test.cpp:26:13:26:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:26:18:26:23 | string | semmle.label | string | +| test.cpp:26:18:26:23 | string indirection | semmle.label | string indirection | | test.cpp:29:32:29:34 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:30:13:30:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:30:18:30:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:30:18:30:23 | Load | semmle.label | Load | -| test.cpp:34:21:34:31 | Call indirection [string] | semmle.label | Call indirection [string] | +| test.cpp:30:13:30:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:30:18:30:23 | string | semmle.label | string | +| test.cpp:30:18:30:23 | string indirection | semmle.label | string indirection | +| test.cpp:34:21:34:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | | test.cpp:35:21:35:23 | str indirection [string] | semmle.label | str indirection [string] | -| test.cpp:39:21:39:31 | Call indirection [string] | semmle.label | Call indirection [string] | -| test.cpp:41:13:41:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:41:18:41:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:41:18:41:23 | Load | semmle.label | Load | -| test.cpp:42:13:42:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:42:18:42:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:42:18:42:23 | Load | semmle.label | Load | -| test.cpp:44:13:44:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:44:18:44:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:44:18:44:23 | Load | semmle.label | Load | -| test.cpp:45:13:45:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:45:18:45:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:45:18:45:23 | Load | semmle.label | Load | -| test.cpp:48:17:48:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:48:22:48:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:48:22:48:27 | Load | semmle.label | Load | -| test.cpp:52:17:52:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:52:22:52:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:52:22:52:27 | Load | semmle.label | Load | -| test.cpp:56:17:56:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:56:22:56:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:56:22:56:27 | Load | semmle.label | Load | -| test.cpp:60:17:60:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:60:22:60:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:60:22:60:27 | Load | semmle.label | Load | -| test.cpp:64:17:64:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:64:22:64:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:64:22:64:27 | Load | semmle.label | Load | -| test.cpp:68:17:68:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:68:22:68:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:68:22:68:27 | Load | semmle.label | Load | -| test.cpp:72:17:72:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:72:22:72:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:72:22:72:27 | Load | semmle.label | Load | -| test.cpp:76:17:76:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:76:22:76:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:76:22:76:27 | Load | semmle.label | Load | -| test.cpp:80:17:80:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:80:22:80:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:80:22:80:27 | Load | semmle.label | Load | -| test.cpp:84:17:84:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:84:22:84:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:84:22:84:27 | Load | semmle.label | Load | -| test.cpp:88:11:88:30 | VariableAddress indirection [string] | semmle.label | VariableAddress indirection [string] | -| test.cpp:90:5:90:34 | Store | semmle.label | Store | -| test.cpp:90:10:90:15 | Load indirection [post update] [string] | semmle.label | Load indirection [post update] [string] | +| test.cpp:39:21:39:31 | call to mk_string_t indirection [string] | semmle.label | call to mk_string_t indirection [string] | +| test.cpp:41:13:41:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:41:18:41:23 | string | semmle.label | string | +| test.cpp:41:18:41:23 | string indirection | semmle.label | string indirection | +| test.cpp:42:13:42:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:42:18:42:23 | string | semmle.label | string | +| test.cpp:42:18:42:23 | string indirection | semmle.label | string indirection | +| test.cpp:44:13:44:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:44:18:44:23 | string | semmle.label | string | +| test.cpp:44:18:44:23 | string indirection | semmle.label | string indirection | +| test.cpp:45:13:45:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:45:18:45:23 | string | semmle.label | string | +| test.cpp:45:18:45:23 | string indirection | semmle.label | string indirection | +| test.cpp:48:17:48:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:48:22:48:27 | string | semmle.label | string | +| test.cpp:48:22:48:27 | string indirection | semmle.label | string indirection | +| test.cpp:52:17:52:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:52:22:52:27 | string | semmle.label | string | +| test.cpp:52:22:52:27 | string indirection | semmle.label | string indirection | +| test.cpp:56:17:56:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:56:22:56:27 | string | semmle.label | string | +| test.cpp:56:22:56:27 | string indirection | semmle.label | string indirection | +| test.cpp:60:17:60:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:60:22:60:27 | string | semmle.label | string | +| test.cpp:60:22:60:27 | string indirection | semmle.label | string indirection | +| test.cpp:64:17:64:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:64:22:64:27 | string | semmle.label | string | +| test.cpp:64:22:64:27 | string indirection | semmle.label | string indirection | +| test.cpp:68:17:68:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:68:22:68:27 | string | semmle.label | string | +| test.cpp:68:22:68:27 | string indirection | semmle.label | string indirection | +| test.cpp:72:17:72:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:72:22:72:27 | string | semmle.label | string | +| test.cpp:72:22:72:27 | string indirection | semmle.label | string indirection | +| test.cpp:76:17:76:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:76:22:76:27 | string | semmle.label | string | +| test.cpp:76:22:76:27 | string indirection | semmle.label | string indirection | +| test.cpp:80:17:80:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:80:22:80:27 | string | semmle.label | string | +| test.cpp:80:22:80:27 | string indirection | semmle.label | string indirection | +| test.cpp:84:17:84:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:84:22:84:27 | string | semmle.label | string | +| test.cpp:84:22:84:27 | string indirection | semmle.label | string indirection | +| test.cpp:88:11:88:30 | mk_string_t_plus_one indirection [string] | semmle.label | mk_string_t_plus_one indirection [string] | +| test.cpp:90:5:90:34 | ... = ... | semmle.label | ... = ... | +| test.cpp:90:10:90:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:90:19:90:24 | call to malloc | semmle.label | call to malloc | -| test.cpp:96:21:96:40 | Call indirection [string] | semmle.label | Call indirection [string] | -| test.cpp:98:13:98:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:98:18:98:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:98:18:98:23 | Load | semmle.label | Load | -| test.cpp:99:13:99:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:99:18:99:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:99:18:99:23 | Load | semmle.label | Load | -| test.cpp:101:13:101:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:101:18:101:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:101:18:101:23 | Load | semmle.label | Load | -| test.cpp:102:13:102:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:102:18:102:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:102:18:102:23 | Load | semmle.label | Load | -| test.cpp:105:17:105:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:105:22:105:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:105:22:105:27 | Load | semmle.label | Load | -| test.cpp:109:17:109:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:109:22:109:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:109:22:109:27 | Load | semmle.label | Load | -| test.cpp:113:17:113:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:113:22:113:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:113:22:113:27 | Load | semmle.label | Load | -| test.cpp:117:17:117:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:117:22:117:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:117:22:117:27 | Load | semmle.label | Load | -| test.cpp:121:17:121:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:121:22:121:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:121:22:121:27 | Load | semmle.label | Load | -| test.cpp:125:17:125:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:125:22:125:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:125:22:125:27 | Load | semmle.label | Load | -| test.cpp:129:17:129:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:129:22:129:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:129:22:129:27 | Load | semmle.label | Load | -| test.cpp:133:17:133:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:133:22:133:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:133:22:133:27 | Load | semmle.label | Load | -| test.cpp:137:17:137:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:137:22:137:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:137:22:137:27 | Load | semmle.label | Load | -| test.cpp:141:17:141:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:141:22:141:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:141:22:141:27 | Load | semmle.label | Load | -| test.cpp:147:5:147:34 | Store | semmle.label | Store | -| test.cpp:147:10:147:15 | Load indirection [post update] [string] | semmle.label | Load indirection [post update] [string] | +| test.cpp:96:21:96:40 | call to mk_string_t_plus_one indirection [string] | semmle.label | call to mk_string_t_plus_one indirection [string] | +| test.cpp:98:13:98:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:98:18:98:23 | string | semmle.label | string | +| test.cpp:98:18:98:23 | string indirection | semmle.label | string indirection | +| test.cpp:99:13:99:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:99:18:99:23 | string | semmle.label | string | +| test.cpp:99:18:99:23 | string indirection | semmle.label | string indirection | +| test.cpp:101:13:101:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:101:18:101:23 | string | semmle.label | string | +| test.cpp:101:18:101:23 | string indirection | semmle.label | string indirection | +| test.cpp:102:13:102:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:102:18:102:23 | string | semmle.label | string | +| test.cpp:102:18:102:23 | string indirection | semmle.label | string indirection | +| test.cpp:105:17:105:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:105:22:105:27 | string | semmle.label | string | +| test.cpp:105:22:105:27 | string indirection | semmle.label | string indirection | +| test.cpp:109:17:109:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:109:22:109:27 | string | semmle.label | string | +| test.cpp:109:22:109:27 | string indirection | semmle.label | string indirection | +| test.cpp:113:17:113:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:113:22:113:27 | string | semmle.label | string | +| test.cpp:113:22:113:27 | string indirection | semmle.label | string indirection | +| test.cpp:117:17:117:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:117:22:117:27 | string | semmle.label | string | +| test.cpp:117:22:117:27 | string indirection | semmle.label | string indirection | +| test.cpp:121:17:121:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:121:22:121:27 | string | semmle.label | string | +| test.cpp:121:22:121:27 | string indirection | semmle.label | string indirection | +| test.cpp:125:17:125:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:125:22:125:27 | string | semmle.label | string | +| test.cpp:125:22:125:27 | string indirection | semmle.label | string indirection | +| test.cpp:129:17:129:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:129:22:129:27 | string | semmle.label | string | +| test.cpp:129:22:129:27 | string indirection | semmle.label | string indirection | +| test.cpp:133:17:133:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:133:22:133:27 | string | semmle.label | string | +| test.cpp:133:22:133:27 | string indirection | semmle.label | string indirection | +| test.cpp:137:17:137:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:137:22:137:27 | string | semmle.label | string | +| test.cpp:137:22:137:27 | string indirection | semmle.label | string indirection | +| test.cpp:141:17:141:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:141:22:141:27 | string | semmle.label | string | +| test.cpp:141:22:141:27 | string indirection | semmle.label | string indirection | +| test.cpp:147:5:147:34 | ... = ... | semmle.label | ... = ... | +| test.cpp:147:10:147:15 | str indirection [post update] [string] | semmle.label | str indirection [post update] [string] | | test.cpp:147:19:147:24 | call to malloc | semmle.label | call to malloc | -| test.cpp:150:13:150:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:150:18:150:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:150:18:150:23 | Load | semmle.label | Load | -| test.cpp:151:13:151:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:151:18:151:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:151:18:151:23 | Load | semmle.label | Load | -| test.cpp:152:13:152:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:152:18:152:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:152:18:152:23 | Load | semmle.label | Load | -| test.cpp:154:13:154:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:154:18:154:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:154:18:154:23 | Load | semmle.label | Load | -| test.cpp:155:13:155:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:155:18:155:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:155:18:155:23 | Load | semmle.label | Load | -| test.cpp:156:13:156:15 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:156:18:156:23 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:156:18:156:23 | Load | semmle.label | Load | -| test.cpp:159:17:159:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:159:22:159:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:159:22:159:27 | Load | semmle.label | Load | -| test.cpp:163:17:163:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:163:22:163:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:163:22:163:27 | Load | semmle.label | Load | -| test.cpp:167:17:167:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:167:22:167:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:167:22:167:27 | Load | semmle.label | Load | -| test.cpp:171:17:171:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:171:22:171:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:171:22:171:27 | Load | semmle.label | Load | -| test.cpp:175:17:175:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:175:22:175:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:175:22:175:27 | Load | semmle.label | Load | -| test.cpp:179:17:179:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:179:22:179:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:179:22:179:27 | Load | semmle.label | Load | -| test.cpp:183:17:183:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:183:22:183:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:183:22:183:27 | Load | semmle.label | Load | -| test.cpp:187:17:187:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:187:22:187:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:187:22:187:27 | Load | semmle.label | Load | -| test.cpp:191:17:191:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:191:22:191:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:191:22:191:27 | Load | semmle.label | Load | -| test.cpp:195:17:195:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:195:22:195:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:195:22:195:27 | Load | semmle.label | Load | -| test.cpp:199:17:199:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:199:22:199:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:199:22:199:27 | Load | semmle.label | Load | -| test.cpp:203:17:203:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:203:22:203:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:203:22:203:27 | Load | semmle.label | Load | -| test.cpp:207:17:207:19 | Load indirection [string] | semmle.label | Load indirection [string] | -| test.cpp:207:22:207:27 | FieldAddress indirection | semmle.label | FieldAddress indirection | -| test.cpp:207:22:207:27 | Load | semmle.label | Load | +| test.cpp:150:13:150:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:150:18:150:23 | string | semmle.label | string | +| test.cpp:150:18:150:23 | string indirection | semmle.label | string indirection | +| test.cpp:151:13:151:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:151:18:151:23 | string | semmle.label | string | +| test.cpp:151:18:151:23 | string indirection | semmle.label | string indirection | +| test.cpp:152:13:152:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:152:18:152:23 | string | semmle.label | string | +| test.cpp:152:18:152:23 | string indirection | semmle.label | string indirection | +| test.cpp:154:13:154:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:154:18:154:23 | string | semmle.label | string | +| test.cpp:154:18:154:23 | string indirection | semmle.label | string indirection | +| test.cpp:155:13:155:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:155:18:155:23 | string | semmle.label | string | +| test.cpp:155:18:155:23 | string indirection | semmle.label | string indirection | +| test.cpp:156:13:156:15 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:156:18:156:23 | string | semmle.label | string | +| test.cpp:156:18:156:23 | string indirection | semmle.label | string indirection | +| test.cpp:159:17:159:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:159:22:159:27 | string | semmle.label | string | +| test.cpp:159:22:159:27 | string indirection | semmle.label | string indirection | +| test.cpp:163:17:163:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:163:22:163:27 | string | semmle.label | string | +| test.cpp:163:22:163:27 | string indirection | semmle.label | string indirection | +| test.cpp:167:17:167:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:167:22:167:27 | string | semmle.label | string | +| test.cpp:167:22:167:27 | string indirection | semmle.label | string indirection | +| test.cpp:171:17:171:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:171:22:171:27 | string | semmle.label | string | +| test.cpp:171:22:171:27 | string indirection | semmle.label | string indirection | +| test.cpp:175:17:175:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:175:22:175:27 | string | semmle.label | string | +| test.cpp:175:22:175:27 | string indirection | semmle.label | string indirection | +| test.cpp:179:17:179:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:179:22:179:27 | string | semmle.label | string | +| test.cpp:179:22:179:27 | string indirection | semmle.label | string indirection | +| test.cpp:183:17:183:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:183:22:183:27 | string | semmle.label | string | +| test.cpp:183:22:183:27 | string indirection | semmle.label | string indirection | +| test.cpp:187:17:187:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:187:22:187:27 | string | semmle.label | string | +| test.cpp:187:22:187:27 | string indirection | semmle.label | string indirection | +| test.cpp:191:17:191:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:191:22:191:27 | string | semmle.label | string | +| test.cpp:191:22:191:27 | string indirection | semmle.label | string indirection | +| test.cpp:195:17:195:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:195:22:195:27 | string | semmle.label | string | +| test.cpp:195:22:195:27 | string indirection | semmle.label | string indirection | +| test.cpp:199:17:199:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:199:22:199:27 | string | semmle.label | string | +| test.cpp:199:22:199:27 | string indirection | semmle.label | string indirection | +| test.cpp:203:17:203:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:203:22:203:27 | string | semmle.label | string | +| test.cpp:203:22:203:27 | string indirection | semmle.label | string indirection | +| test.cpp:207:17:207:19 | str indirection [string] | semmle.label | str indirection [string] | +| test.cpp:207:22:207:27 | string | semmle.label | string | +| test.cpp:207:22:207:27 | string indirection | semmle.label | string indirection | subpaths #select -| test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | Load | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string | -| test.cpp:72:9:72:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:72:22:72:27 | Load | This write may overflow $@ by 1 element. | test.cpp:72:22:72:27 | string | string | -| test.cpp:80:9:80:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:80:22:80:27 | Load | This write may overflow $@ by 2 elements. | test.cpp:80:22:80:27 | string | string | -| test.cpp:99:5:99:11 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:99:18:99:23 | Load | This write may overflow $@ by 1 element. | test.cpp:99:18:99:23 | string | string | -| test.cpp:129:9:129:15 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:129:22:129:27 | Load | This write may overflow $@ by 1 element. | test.cpp:129:22:129:27 | string | string | -| test.cpp:137:9:137:15 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:137:22:137:27 | Load | This write may overflow $@ by 2 elements. | test.cpp:137:22:137:27 | string | string | -| test.cpp:152:5:152:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:152:18:152:23 | Load | This write may overflow $@ by 1 element. | test.cpp:152:18:152:23 | string | string | -| test.cpp:154:5:154:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:154:18:154:23 | Load | This write may overflow $@ by 1 element. | test.cpp:154:18:154:23 | string | string | -| test.cpp:156:5:156:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:156:18:156:23 | Load | This write may overflow $@ by 2 elements. | test.cpp:156:18:156:23 | string | string | -| test.cpp:175:9:175:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:175:22:175:27 | Load | This write may overflow $@ by 1 element. | test.cpp:175:22:175:27 | string | string | -| test.cpp:187:9:187:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:187:22:187:27 | Load | This write may overflow $@ by 1 element. | test.cpp:187:22:187:27 | string | string | -| test.cpp:195:9:195:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:195:22:195:27 | Load | This write may overflow $@ by 1 element. | test.cpp:195:22:195:27 | string | string | -| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | Load | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string | -| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | Load | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | -| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | Load | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | +| test.cpp:42:5:42:11 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:42:18:42:23 | string | This write may overflow $@ by 1 element. | test.cpp:42:18:42:23 | string | string | +| test.cpp:72:9:72:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:72:22:72:27 | string | This write may overflow $@ by 1 element. | test.cpp:72:22:72:27 | string | string | +| test.cpp:80:9:80:15 | call to strncpy | test.cpp:18:19:18:24 | call to malloc | test.cpp:80:22:80:27 | string | This write may overflow $@ by 2 elements. | test.cpp:80:22:80:27 | string | string | +| test.cpp:99:5:99:11 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:99:18:99:23 | string | This write may overflow $@ by 1 element. | test.cpp:99:18:99:23 | string | string | +| test.cpp:129:9:129:15 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:129:22:129:27 | string | This write may overflow $@ by 1 element. | test.cpp:129:22:129:27 | string | string | +| test.cpp:137:9:137:15 | call to strncpy | test.cpp:90:19:90:24 | call to malloc | test.cpp:137:22:137:27 | string | This write may overflow $@ by 2 elements. | test.cpp:137:22:137:27 | string | string | +| test.cpp:152:5:152:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:152:18:152:23 | string | This write may overflow $@ by 1 element. | test.cpp:152:18:152:23 | string | string | +| test.cpp:154:5:154:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:154:18:154:23 | string | This write may overflow $@ by 1 element. | test.cpp:154:18:154:23 | string | string | +| test.cpp:156:5:156:11 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:156:18:156:23 | string | This write may overflow $@ by 2 elements. | test.cpp:156:18:156:23 | string | string | +| test.cpp:175:9:175:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:175:22:175:27 | string | This write may overflow $@ by 1 element. | test.cpp:175:22:175:27 | string | string | +| test.cpp:187:9:187:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:187:22:187:27 | string | This write may overflow $@ by 1 element. | test.cpp:187:22:187:27 | string | string | +| test.cpp:195:9:195:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:195:22:195:27 | string | This write may overflow $@ by 1 element. | test.cpp:195:22:195:27 | string | string | +| test.cpp:199:9:199:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:199:22:199:27 | string | This write may overflow $@ by 2 elements. | test.cpp:199:22:199:27 | string | string | +| test.cpp:203:9:203:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:203:22:203:27 | string | This write may overflow $@ by 2 elements. | test.cpp:203:22:203:27 | string | string | +| test.cpp:207:9:207:15 | call to strncpy | test.cpp:147:19:147:24 | call to malloc | test.cpp:207:22:207:27 | string | This write may overflow $@ by 3 elements. | test.cpp:207:22:207:27 | string | string | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected index bb857df2df1..66c633eea49 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-190/AllocMultiplicationOverflow/AllocMultiplicationOverflow.expected @@ -1,11 +1,25 @@ edges +| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | +| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | +| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | +| test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | | test.cpp:37:24:37:27 | size | test.cpp:37:46:37:49 | size | | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:24:37:27 | size | +| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | +| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | +| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | nodes | test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... | +| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... | +| test.cpp:13:33:13:37 | ... * ... | semmle.label | ... * ... | +| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... | +| test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... | | test.cpp:15:31:15:35 | ... * ... | semmle.label | ... * ... | | test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... | +| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... | +| test.cpp:19:34:19:38 | ... * ... | semmle.label | ... * ... | +| test.cpp:22:17:22:21 | ... * ... | semmle.label | ... * ... | | test.cpp:22:17:22:21 | ... * ... | semmle.label | ... * ... | | test.cpp:23:33:23:37 | size1 | semmle.label | size1 | | test.cpp:30:27:30:31 | ... * ... | semmle.label | ... * ... | @@ -14,15 +28,31 @@ nodes | test.cpp:37:46:37:49 | size | semmle.label | size | | test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... | | test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... | +| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... | +| test.cpp:45:36:45:40 | ... * ... | semmle.label | ... * ... | +| test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... | +| test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... | | test.cpp:46:36:46:40 | ... * ... | semmle.label | ... * ... | subpaths #select | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication | +| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication | +| test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | test.cpp:13:33:13:37 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:13:33:13:37 | ... * ... | multiplication | +| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication | +| test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication | | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | test.cpp:15:31:15:35 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:15:31:15:35 | ... * ... | multiplication | | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication | +| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication | +| test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | test.cpp:19:34:19:38 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:19:34:19:38 | ... * ... | multiplication | +| test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:22:17:22:21 | ... * ... | multiplication | | test.cpp:23:33:23:37 | size1 | test.cpp:22:17:22:21 | ... * ... | test.cpp:23:33:23:37 | size1 | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:22:17:22:21 | ... * ... | multiplication | | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | test.cpp:30:27:30:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:30:27:30:31 | ... * ... | multiplication | | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | test.cpp:31:27:31:31 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:31:27:31:31 | ... * ... | multiplication | | test.cpp:37:46:37:49 | size | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:46:37:49 | size | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication | +| test.cpp:37:46:37:49 | size | test.cpp:45:36:45:40 | ... * ... | test.cpp:37:46:37:49 | size | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication | +| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication | +| test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication | | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | test.cpp:45:36:45:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:45:36:45:40 | ... * ... | multiplication | | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication | +| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication | +| test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | test.cpp:46:36:46:40 | ... * ... | Potentially overflowing value from $@ is used in the size of this allocation. | test.cpp:46:36:46:40 | ... * ... | multiplication | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected index 0a8a264fc3d..820c48447ff 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/array-access/ArrayAccessProductFlow.expected @@ -1,112 +1,118 @@ edges -| test.cpp:4:17:4:22 | call to malloc | test.cpp:6:9:6:11 | Load | -| test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | Load | -| test.cpp:19:9:19:16 | VariableAddress indirection [p] | test.cpp:31:9:31:11 | arr indirection [p] | -| test.cpp:19:9:19:16 | VariableAddress indirection [p] | test.cpp:35:9:35:11 | arr indirection [p] | -| test.cpp:19:9:19:16 | VariableAddress indirection [p] | test.cpp:50:18:50:25 | call to mk_array [p] | -| test.cpp:21:5:21:24 | Store | test.cpp:21:9:21:9 | arr indirection [post update] [p] | -| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:19:9:19:16 | VariableAddress indirection [p] | -| test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | Store | -| test.cpp:31:9:31:11 | arr indirection [p] | test.cpp:31:13:31:13 | p | -| test.cpp:31:13:31:13 | p | test.cpp:31:13:31:13 | Load | -| test.cpp:35:9:35:11 | arr indirection [p] | test.cpp:35:13:35:13 | p | -| test.cpp:35:13:35:13 | p | test.cpp:35:13:35:13 | Load | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:6:9:6:11 | arr | +| test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | +| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:28:19:28:26 | call to mk_array [p] | +| test.cpp:19:9:19:16 | mk_array indirection [p] | test.cpp:50:18:50:25 | call to mk_array [p] | +| test.cpp:21:5:21:24 | ... = ... | test.cpp:21:9:21:9 | arr indirection [post update] [p] | +| test.cpp:21:9:21:9 | arr indirection [post update] [p] | test.cpp:19:9:19:16 | mk_array indirection [p] | +| test.cpp:21:13:21:18 | call to malloc | test.cpp:21:5:21:24 | ... = ... | +| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:31:9:31:11 | arr indirection [p] | +| test.cpp:28:19:28:26 | call to mk_array [p] | test.cpp:35:9:35:11 | arr indirection [p] | +| test.cpp:31:9:31:11 | arr indirection [p] | test.cpp:31:13:31:13 | p indirection | +| test.cpp:31:13:31:13 | p indirection | test.cpp:31:13:31:13 | p | +| test.cpp:35:9:35:11 | arr indirection [p] | test.cpp:35:13:35:13 | p indirection | +| test.cpp:35:13:35:13 | p indirection | test.cpp:35:13:35:13 | p | | test.cpp:39:27:39:29 | arr [p] | test.cpp:41:9:41:11 | arr indirection [p] | | test.cpp:39:27:39:29 | arr [p] | test.cpp:45:9:45:11 | arr indirection [p] | -| test.cpp:41:9:41:11 | arr indirection [p] | test.cpp:41:13:41:13 | p | -| test.cpp:41:13:41:13 | p | test.cpp:41:13:41:13 | Load | -| test.cpp:45:9:45:11 | arr indirection [p] | test.cpp:45:13:45:13 | p | -| test.cpp:45:13:45:13 | p | test.cpp:45:13:45:13 | Load | +| test.cpp:41:9:41:11 | arr indirection [p] | test.cpp:41:13:41:13 | p indirection | +| test.cpp:41:13:41:13 | p indirection | test.cpp:41:13:41:13 | p | +| test.cpp:45:9:45:11 | arr indirection [p] | test.cpp:45:13:45:13 | p indirection | +| test.cpp:45:13:45:13 | p indirection | test.cpp:45:13:45:13 | p | | test.cpp:50:18:50:25 | call to mk_array [p] | test.cpp:39:27:39:29 | arr [p] | -| test.cpp:55:5:55:24 | Store | test.cpp:55:9:55:9 | arr indirection [post update] [p] | +| test.cpp:55:5:55:24 | ... = ... | test.cpp:55:9:55:9 | arr indirection [post update] [p] | | test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:59:9:59:11 | arr indirection [p] | | test.cpp:55:9:55:9 | arr indirection [post update] [p] | test.cpp:63:9:63:11 | arr indirection [p] | -| test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | Store | -| test.cpp:59:9:59:11 | arr indirection [p] | test.cpp:59:13:59:13 | p | -| test.cpp:59:13:59:13 | p | test.cpp:59:13:59:13 | Load | -| test.cpp:63:9:63:11 | arr indirection [p] | test.cpp:63:13:63:13 | p | -| test.cpp:63:13:63:13 | p | test.cpp:63:13:63:13 | Load | -| test.cpp:67:10:67:19 | VariableAddress indirection [p] | test.cpp:76:20:76:29 | Call indirection [p] | -| test.cpp:67:10:67:19 | VariableAddress indirection [p] | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] | -| test.cpp:69:5:69:25 | Store | test.cpp:69:10:69:10 | Load indirection [post update] [p] | -| test.cpp:69:10:69:10 | Load indirection [post update] [p] | test.cpp:67:10:67:19 | VariableAddress indirection [p] | -| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | Store | -| test.cpp:76:20:76:29 | Call indirection [p] | test.cpp:79:9:79:11 | Load indirection [p] | -| test.cpp:76:20:76:29 | Call indirection [p] | test.cpp:83:9:83:11 | Load indirection [p] | -| test.cpp:79:9:79:11 | Load indirection [p] | test.cpp:79:14:79:14 | p | -| test.cpp:79:14:79:14 | p | test.cpp:79:14:79:14 | Load | -| test.cpp:83:9:83:11 | Load indirection [p] | test.cpp:83:14:83:14 | p | -| test.cpp:83:14:83:14 | p | test.cpp:83:14:83:14 | Load | -| test.cpp:87:28:87:30 | arr indirection [p] | test.cpp:89:9:89:11 | Load indirection [p] | -| test.cpp:87:28:87:30 | arr indirection [p] | test.cpp:93:9:93:11 | Load indirection [p] | -| test.cpp:89:9:89:11 | Load indirection [p] | test.cpp:89:14:89:14 | p | -| test.cpp:89:14:89:14 | p | test.cpp:89:14:89:14 | Load | -| test.cpp:93:9:93:11 | Load indirection [p] | test.cpp:93:14:93:14 | p | -| test.cpp:93:14:93:14 | p | test.cpp:93:14:93:14 | Load | +| test.cpp:55:13:55:18 | call to malloc | test.cpp:55:5:55:24 | ... = ... | +| test.cpp:59:9:59:11 | arr indirection [p] | test.cpp:59:13:59:13 | p indirection | +| test.cpp:59:13:59:13 | p indirection | test.cpp:59:13:59:13 | p | +| test.cpp:63:9:63:11 | arr indirection [p] | test.cpp:63:13:63:13 | p indirection | +| test.cpp:63:13:63:13 | p indirection | test.cpp:63:13:63:13 | p | +| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | +| test.cpp:67:10:67:19 | mk_array_p indirection [p] | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] | +| test.cpp:69:5:69:25 | ... = ... | test.cpp:69:10:69:10 | arr indirection [post update] [p] | +| test.cpp:69:10:69:10 | arr indirection [post update] [p] | test.cpp:67:10:67:19 | mk_array_p indirection [p] | +| test.cpp:69:14:69:19 | call to malloc | test.cpp:69:5:69:25 | ... = ... | +| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:79:9:79:11 | arr indirection [p] | +| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | test.cpp:83:9:83:11 | arr indirection [p] | +| test.cpp:79:9:79:11 | arr indirection [p] | test.cpp:79:14:79:14 | p indirection | +| test.cpp:79:14:79:14 | p indirection | test.cpp:79:14:79:14 | p | +| test.cpp:83:9:83:11 | arr indirection [p] | test.cpp:83:14:83:14 | p indirection | +| test.cpp:83:14:83:14 | p indirection | test.cpp:83:14:83:14 | p | +| test.cpp:87:28:87:30 | arr indirection [p] | test.cpp:89:9:89:11 | arr indirection [p] | +| test.cpp:87:28:87:30 | arr indirection [p] | test.cpp:93:9:93:11 | arr indirection [p] | +| test.cpp:89:9:89:11 | arr indirection [p] | test.cpp:89:14:89:14 | p indirection | +| test.cpp:89:14:89:14 | p indirection | test.cpp:89:14:89:14 | p | +| test.cpp:93:9:93:11 | arr indirection [p] | test.cpp:93:14:93:14 | p indirection | +| test.cpp:93:14:93:14 | p indirection | test.cpp:93:14:93:14 | p | | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] | test.cpp:87:28:87:30 | arr indirection [p] | nodes | test.cpp:4:17:4:22 | call to malloc | semmle.label | call to malloc | -| test.cpp:6:9:6:11 | Load | semmle.label | Load | -| test.cpp:10:9:10:11 | Load | semmle.label | Load | -| test.cpp:19:9:19:16 | VariableAddress indirection [p] | semmle.label | VariableAddress indirection [p] | -| test.cpp:21:5:21:24 | Store | semmle.label | Store | +| test.cpp:6:9:6:11 | arr | semmle.label | arr | +| test.cpp:10:9:10:11 | arr | semmle.label | arr | +| test.cpp:19:9:19:16 | mk_array indirection [p] | semmle.label | mk_array indirection [p] | +| test.cpp:21:5:21:24 | ... = ... | semmle.label | ... = ... | | test.cpp:21:9:21:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] | | test.cpp:21:13:21:18 | call to malloc | semmle.label | call to malloc | +| test.cpp:28:19:28:26 | call to mk_array [p] | semmle.label | call to mk_array [p] | | test.cpp:31:9:31:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:31:13:31:13 | Load | semmle.label | Load | | test.cpp:31:13:31:13 | p | semmle.label | p | +| test.cpp:31:13:31:13 | p indirection | semmle.label | p indirection | | test.cpp:35:9:35:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:35:13:35:13 | Load | semmle.label | Load | | test.cpp:35:13:35:13 | p | semmle.label | p | +| test.cpp:35:13:35:13 | p indirection | semmle.label | p indirection | | test.cpp:39:27:39:29 | arr [p] | semmle.label | arr [p] | | test.cpp:41:9:41:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:41:13:41:13 | Load | semmle.label | Load | | test.cpp:41:13:41:13 | p | semmle.label | p | +| test.cpp:41:13:41:13 | p indirection | semmle.label | p indirection | | test.cpp:45:9:45:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:45:13:45:13 | Load | semmle.label | Load | | test.cpp:45:13:45:13 | p | semmle.label | p | +| test.cpp:45:13:45:13 | p indirection | semmle.label | p indirection | | test.cpp:50:18:50:25 | call to mk_array [p] | semmle.label | call to mk_array [p] | -| test.cpp:55:5:55:24 | Store | semmle.label | Store | +| test.cpp:55:5:55:24 | ... = ... | semmle.label | ... = ... | | test.cpp:55:9:55:9 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] | | test.cpp:55:13:55:18 | call to malloc | semmle.label | call to malloc | | test.cpp:59:9:59:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:59:13:59:13 | Load | semmle.label | Load | | test.cpp:59:13:59:13 | p | semmle.label | p | +| test.cpp:59:13:59:13 | p indirection | semmle.label | p indirection | | test.cpp:63:9:63:11 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:63:13:63:13 | Load | semmle.label | Load | | test.cpp:63:13:63:13 | p | semmle.label | p | -| test.cpp:67:10:67:19 | VariableAddress indirection [p] | semmle.label | VariableAddress indirection [p] | -| test.cpp:69:5:69:25 | Store | semmle.label | Store | -| test.cpp:69:10:69:10 | Load indirection [post update] [p] | semmle.label | Load indirection [post update] [p] | +| test.cpp:63:13:63:13 | p indirection | semmle.label | p indirection | +| test.cpp:67:10:67:19 | mk_array_p indirection [p] | semmle.label | mk_array_p indirection [p] | +| test.cpp:69:5:69:25 | ... = ... | semmle.label | ... = ... | +| test.cpp:69:10:69:10 | arr indirection [post update] [p] | semmle.label | arr indirection [post update] [p] | | test.cpp:69:14:69:19 | call to malloc | semmle.label | call to malloc | -| test.cpp:76:20:76:29 | Call indirection [p] | semmle.label | Call indirection [p] | -| test.cpp:79:9:79:11 | Load indirection [p] | semmle.label | Load indirection [p] | -| test.cpp:79:14:79:14 | Load | semmle.label | Load | +| test.cpp:76:20:76:29 | call to mk_array_p indirection [p] | semmle.label | call to mk_array_p indirection [p] | +| test.cpp:79:9:79:11 | arr indirection [p] | semmle.label | arr indirection [p] | | test.cpp:79:14:79:14 | p | semmle.label | p | -| test.cpp:83:9:83:11 | Load indirection [p] | semmle.label | Load indirection [p] | -| test.cpp:83:14:83:14 | Load | semmle.label | Load | +| test.cpp:79:14:79:14 | p indirection | semmle.label | p indirection | +| test.cpp:83:9:83:11 | arr indirection [p] | semmle.label | arr indirection [p] | | test.cpp:83:14:83:14 | p | semmle.label | p | +| test.cpp:83:14:83:14 | p indirection | semmle.label | p indirection | | test.cpp:87:28:87:30 | arr indirection [p] | semmle.label | arr indirection [p] | -| test.cpp:89:9:89:11 | Load indirection [p] | semmle.label | Load indirection [p] | -| test.cpp:89:14:89:14 | Load | semmle.label | Load | +| test.cpp:89:9:89:11 | arr indirection [p] | semmle.label | arr indirection [p] | | test.cpp:89:14:89:14 | p | semmle.label | p | -| test.cpp:93:9:93:11 | Load indirection [p] | semmle.label | Load indirection [p] | -| test.cpp:93:14:93:14 | Load | semmle.label | Load | +| test.cpp:89:14:89:14 | p indirection | semmle.label | p indirection | +| test.cpp:93:9:93:11 | arr indirection [p] | semmle.label | arr indirection [p] | | test.cpp:93:14:93:14 | p | semmle.label | p | +| test.cpp:93:14:93:14 | p indirection | semmle.label | p indirection | | test.cpp:98:18:98:27 | call to mk_array_p indirection [p] | semmle.label | call to mk_array_p indirection [p] | subpaths #select -| test.cpp:10:9:10:11 | Load | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:5:25:5:28 | Load | Load | -| test.cpp:10:9:10:11 | Load | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:9:26:9:29 | Load | Load | -| test.cpp:35:13:35:13 | Load | test.cpp:21:13:21:18 | call to malloc | test.cpp:35:13:35:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:30:29:30:32 | Load | Load | -| test.cpp:35:13:35:13 | Load | test.cpp:21:13:21:18 | call to malloc | test.cpp:35:13:35:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:34:30:34:33 | Load | Load | -| test.cpp:45:13:45:13 | Load | test.cpp:21:13:21:18 | call to malloc | test.cpp:45:13:45:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:40:29:40:32 | Load | Load | -| test.cpp:45:13:45:13 | Load | test.cpp:21:13:21:18 | call to malloc | test.cpp:45:13:45:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:44:30:44:33 | Load | Load | -| test.cpp:63:13:63:13 | Load | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:5:56:19 | Store | Store | -| test.cpp:63:13:63:13 | Load | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:5:56:19 | Store | Store | -| test.cpp:63:13:63:13 | Load | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:16:56:19 | Load | Load | -| test.cpp:63:13:63:13 | Load | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:58:29:58:32 | Load | Load | -| test.cpp:63:13:63:13 | Load | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:62:30:62:33 | Load | Load | -| test.cpp:83:14:83:14 | Load | test.cpp:69:14:69:19 | call to malloc | test.cpp:83:14:83:14 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:82:31:82:34 | Load | Load | -| test.cpp:93:14:93:14 | Load | test.cpp:69:14:69:19 | call to malloc | test.cpp:93:14:93:14 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:88:30:88:33 | Load | Load | -| test.cpp:93:14:93:14 | Load | test.cpp:69:14:69:19 | call to malloc | test.cpp:93:14:93:14 | Load | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:92:31:92:34 | Load | Load | +| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:4:24:4:27 | size | size | +| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:4:24:4:27 | size | size | +| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:5:25:5:28 | size | size | +| test.cpp:10:9:10:11 | arr | test.cpp:4:17:4:22 | call to malloc | test.cpp:10:9:10:11 | arr | Off-by one error allocated at $@ bounded by $@. | test.cpp:4:17:4:22 | call to malloc | call to malloc | test.cpp:9:26:9:29 | size | size | +| test.cpp:35:13:35:13 | p | test.cpp:21:13:21:18 | call to malloc | test.cpp:35:13:35:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:30:29:30:32 | size | size | +| test.cpp:35:13:35:13 | p | test.cpp:21:13:21:18 | call to malloc | test.cpp:35:13:35:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:34:30:34:33 | size | size | +| test.cpp:45:13:45:13 | p | test.cpp:21:13:21:18 | call to malloc | test.cpp:45:13:45:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:40:29:40:32 | size | size | +| test.cpp:45:13:45:13 | p | test.cpp:21:13:21:18 | call to malloc | test.cpp:45:13:45:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:21:13:21:18 | call to malloc | call to malloc | test.cpp:44:30:44:33 | size | size | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:55:20:55:23 | size | size | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:55:20:55:23 | size | size | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:5:56:19 | ... = ... | ... = ... | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:5:56:19 | ... = ... | ... = ... | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:56:16:56:19 | size | size | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:58:29:58:32 | size | size | +| test.cpp:63:13:63:13 | p | test.cpp:55:13:55:18 | call to malloc | test.cpp:63:13:63:13 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:55:13:55:18 | call to malloc | call to malloc | test.cpp:62:30:62:33 | size | size | +| test.cpp:83:14:83:14 | p | test.cpp:69:14:69:19 | call to malloc | test.cpp:83:14:83:14 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:82:31:82:34 | size | size | +| test.cpp:93:14:93:14 | p | test.cpp:69:14:69:19 | call to malloc | test.cpp:93:14:93:14 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:88:30:88:33 | size | size | +| test.cpp:93:14:93:14 | p | test.cpp:69:14:69:19 | call to malloc | test.cpp:93:14:93:14 | p | Off-by one error allocated at $@ bounded by $@. | test.cpp:69:14:69:19 | call to malloc | call to malloc | test.cpp:92:31:92:34 | size | size | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected index 9d68450439e..e201ef15af9 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected @@ -1,7 +1,7 @@ edges -| test.cpp:66:32:66:32 | p | test.cpp:66:32:66:32 | Load | +| test.cpp:66:32:66:32 | p | test.cpp:66:32:66:32 | p | | test.cpp:66:32:66:32 | p | test.cpp:67:5:67:6 | * ... | -| test.cpp:66:32:66:32 | p | test.cpp:67:6:67:6 | Load | +| test.cpp:66:32:66:32 | p | test.cpp:67:6:67:6 | p | | test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p | | test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p | | test.cpp:77:27:77:44 | access to array | test.cpp:77:26:77:44 | & ... | @@ -13,11 +13,11 @@ nodes | test.cpp:50:5:50:24 | access to array | semmle.label | access to array | | test.cpp:57:9:57:19 | access to array | semmle.label | access to array | | test.cpp:61:9:61:19 | access to array | semmle.label | access to array | -| test.cpp:66:32:66:32 | Load | semmle.label | Load | +| test.cpp:66:32:66:32 | p | semmle.label | p | | test.cpp:66:32:66:32 | p | semmle.label | p | | test.cpp:66:32:66:32 | p | semmle.label | p | | test.cpp:67:5:67:6 | * ... | semmle.label | * ... | -| test.cpp:67:6:67:6 | Load | semmle.label | Load | +| test.cpp:67:6:67:6 | p | semmle.label | p | | test.cpp:72:5:72:15 | access to array | semmle.label | access to array | | test.cpp:77:26:77:44 | & ... | semmle.label | & ... | | test.cpp:77:27:77:44 | access to array | semmle.label | access to array | @@ -31,7 +31,7 @@ subpaths | test.cpp:57:9:57:19 | access to array | test.cpp:57:9:57:19 | access to array | test.cpp:57:9:57:19 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:19:9:19:11 | buf | buf | test.cpp:57:9:57:23 | Store: ... = ... | write | | test.cpp:61:9:61:19 | access to array | test.cpp:61:9:61:19 | access to array | test.cpp:61:9:61:19 | access to array | This pointer arithmetic may have an off-by-2 error allowing it to overrun $@ at this $@. | test.cpp:19:9:19:11 | buf | buf | test.cpp:61:9:61:23 | Store: ... = ... | write | | test.cpp:72:5:72:15 | access to array | test.cpp:72:5:72:15 | access to array | test.cpp:72:5:72:15 | access to array | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:72:5:72:19 | Store: ... = ... | write | -| test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:66:32:66:32 | Load | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | +| test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:66:32:66:32 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | | test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:66:32:66:32 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | | test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:67:5:67:6 | * ... | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | -| test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:67:6:67:6 | Load | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | +| test.cpp:77:27:77:44 | access to array | test.cpp:77:27:77:44 | access to array | test.cpp:67:6:67:6 | p | This pointer arithmetic may have an off-by-1 error allowing it to overrun $@ at this $@. | test.cpp:15:9:15:11 | buf | buf | test.cpp:67:5:67:10 | Store: ... = ... | write | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected index 05069444c19..1b6be088de2 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected @@ -1,416 +1,425 @@ edges -| test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | -| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | +| test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | p | +| test.cpp:5:15:5:15 | p | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | p | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | p | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | p | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:15 | p | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:15 | p | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:15 | p | test.cpp:7:16:7:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:7:16:7:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:8:16:8:20 | ... + ... | +| test.cpp:5:15:5:15 | p | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:15 | p | test.cpp:12:16:12:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | ... + ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | ... + ... | | test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | | test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:6:15:6:15 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:7:16:7:16 | q | | test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | | test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:22 | ... + ... | test.cpp:12:16:12:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:5:15:5:22 | Store | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:5:15:5:22 | Store | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:22 | Store | test.cpp:12:16:12:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:6:15:6:15 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:7:16:7:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:6:15:6:15 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:6:15:6:15 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:7:16:7:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:7:16:7:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:7:16:7:16 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:8:16:8:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:8:16:8:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:8:16:8:16 | Load | test.cpp:12:16:12:16 | Load | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:8:16:8:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:9:16:9:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:10:16:10:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:11:16:11:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:12:16:12:16 | q | +| test.cpp:5:15:5:22 | ... + ... | test.cpp:12:16:12:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:6:15:6:15 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:6:15:6:15 | q | test.cpp:7:16:7:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:7:16:7:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:6:15:6:15 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:6:15:6:15 | q | test.cpp:8:16:8:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:8:16:8:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:9:16:9:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:9:16:9:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:10:16:10:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:10:16:10:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:11:16:11:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:11:16:11:16 | q | +| test.cpp:6:15:6:15 | q | test.cpp:12:16:12:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:7:16:7:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:7:16:7:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:7:16:7:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:7:16:7:16 | q | test.cpp:8:16:8:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:8:16:8:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:9:16:9:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:9:16:9:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:7:16:7:16 | q | test.cpp:12:16:12:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:8:16:8:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:8:16:8:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:8:16:8:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:8:16:8:16 | q | test.cpp:9:16:9:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:9:16:9:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:8:16:8:16 | q | test.cpp:12:16:12:16 | q | | test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:9:16:9:16 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:9:16:9:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:9:16:9:16 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:10:16:10:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:10:16:10:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:10:16:10:16 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:10:16:10:16 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:11:16:11:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:11:16:11:16 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | Load | -| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | +| test.cpp:9:16:9:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:9:16:9:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:9:16:9:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:9:16:9:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:9:16:9:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:9:16:9:16 | q | test.cpp:10:16:10:16 | q | +| test.cpp:9:16:9:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:9:16:9:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:9:16:9:16 | q | test.cpp:12:16:12:16 | q | +| test.cpp:10:16:10:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:10:16:10:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:10:16:10:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:10:16:10:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:10:16:10:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:10:16:10:16 | q | test.cpp:11:16:11:16 | q | +| test.cpp:10:16:10:16 | q | test.cpp:12:16:12:16 | q | +| test.cpp:11:16:11:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:11:16:11:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:11:16:11:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:11:16:11:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:11:16:11:16 | q | test.cpp:12:16:12:16 | q | +| test.cpp:12:16:12:16 | q | test.cpp:6:14:6:15 | Load: * ... | +| test.cpp:12:16:12:16 | q | test.cpp:8:14:8:21 | Load: * ... | +| test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | p | +| test.cpp:17:15:17:15 | p | test.cpp:17:15:17:22 | ... + ... | +| test.cpp:17:15:17:15 | p | test.cpp:20:16:20:20 | ... + ... | | test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | | test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | -| test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | -| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | +| test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | p | +| test.cpp:29:15:29:15 | p | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | p | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | p | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | p | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:15 | p | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:15 | p | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:15 | p | test.cpp:31:16:31:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:31:16:31:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:32:16:32:20 | ... + ... | +| test.cpp:29:15:29:15 | p | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:15 | p | test.cpp:36:16:36:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | ... + ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | ... + ... | | test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | | test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:30:15:30:15 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:31:16:31:16 | q | | test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | | test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:28 | ... + ... | test.cpp:36:16:36:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:29:15:29:28 | Store | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:29:15:29:28 | Store | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:28 | Store | test.cpp:36:16:36:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:30:15:30:15 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:30:15:30:15 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:30:15:30:15 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:31:16:31:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:31:16:31:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:31:16:31:16 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:32:16:32:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:32:16:32:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:32:16:32:16 | Load | test.cpp:36:16:36:16 | Load | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:32:16:32:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:33:16:33:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:34:16:34:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:35:16:35:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:36:16:36:16 | q | +| test.cpp:29:15:29:28 | ... + ... | test.cpp:36:16:36:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:30:15:30:15 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:30:15:30:15 | q | test.cpp:31:16:31:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:31:16:31:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:30:15:30:15 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:30:15:30:15 | q | test.cpp:32:16:32:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:32:16:32:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:33:16:33:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:33:16:33:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:34:16:34:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:34:16:34:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:35:16:35:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:35:16:35:16 | q | +| test.cpp:30:15:30:15 | q | test.cpp:36:16:36:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:31:16:31:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:31:16:31:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:31:16:31:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:31:16:31:16 | q | test.cpp:32:16:32:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:32:16:32:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:33:16:33:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:33:16:33:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:31:16:31:16 | q | test.cpp:36:16:36:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:32:16:32:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:32:16:32:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:32:16:32:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:32:16:32:16 | q | test.cpp:33:16:33:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:33:16:33:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:32:16:32:16 | q | test.cpp:36:16:36:16 | q | | test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:33:16:33:16 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:33:16:33:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:33:16:33:16 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:34:16:34:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:34:16:34:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:34:16:34:16 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:34:16:34:16 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:35:16:35:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:35:16:35:16 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | +| test.cpp:33:16:33:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:33:16:33:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:33:16:33:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:33:16:33:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:33:16:33:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:33:16:33:16 | q | test.cpp:34:16:34:16 | q | +| test.cpp:33:16:33:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:33:16:33:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:33:16:33:16 | q | test.cpp:36:16:36:16 | q | +| test.cpp:34:16:34:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:34:16:34:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:34:16:34:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:34:16:34:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:34:16:34:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:34:16:34:16 | q | test.cpp:35:16:35:16 | q | +| test.cpp:34:16:34:16 | q | test.cpp:36:16:36:16 | q | +| test.cpp:35:16:35:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:35:16:35:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:35:16:35:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:35:16:35:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:35:16:35:16 | q | test.cpp:36:16:36:16 | q | +| test.cpp:36:16:36:16 | q | test.cpp:30:14:30:15 | Load: * ... | +| test.cpp:36:16:36:16 | q | test.cpp:32:14:32:21 | Load: * ... | +| test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | p | +| test.cpp:41:15:41:15 | p | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | p | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | p | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | p | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:15 | p | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:15 | p | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:15 | p | test.cpp:43:16:43:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:43:16:43:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:44:16:44:20 | ... + ... | +| test.cpp:41:15:41:15 | p | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:15 | p | test.cpp:48:16:48:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | ... + ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | ... + ... | | test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | | test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:42:15:42:15 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:43:16:43:16 | q | | test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | | test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:28 | ... + ... | test.cpp:48:16:48:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:41:15:41:28 | Store | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:41:15:41:28 | Store | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:28 | Store | test.cpp:48:16:48:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:42:15:42:15 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:42:15:42:15 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:42:15:42:15 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:43:16:43:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:43:16:43:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:43:16:43:16 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:44:16:44:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:44:16:44:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:44:16:44:16 | Load | test.cpp:48:16:48:16 | Load | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:44:16:44:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:45:16:45:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:46:16:46:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:47:16:47:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:48:16:48:16 | q | +| test.cpp:41:15:41:28 | ... + ... | test.cpp:48:16:48:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:42:15:42:15 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:42:15:42:15 | q | test.cpp:43:16:43:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:43:16:43:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:42:15:42:15 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:42:15:42:15 | q | test.cpp:44:16:44:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:44:16:44:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:45:16:45:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:45:16:45:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:46:16:46:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:46:16:46:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:47:16:47:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:47:16:47:16 | q | +| test.cpp:42:15:42:15 | q | test.cpp:48:16:48:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:43:16:43:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:43:16:43:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:43:16:43:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:43:16:43:16 | q | test.cpp:44:16:44:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:44:16:44:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:45:16:45:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:45:16:45:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:43:16:43:16 | q | test.cpp:48:16:48:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:44:16:44:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:44:16:44:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:44:16:44:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:44:16:44:16 | q | test.cpp:45:16:45:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:45:16:45:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:44:16:44:16 | q | test.cpp:48:16:48:16 | q | | test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:45:16:45:16 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:45:16:45:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:45:16:45:16 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:46:16:46:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:46:16:46:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:46:16:46:16 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:46:16:46:16 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:47:16:47:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:47:16:47:16 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:62:39:62:39 | Load | -| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:66:39:66:39 | Load | -| test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:70:38:70:38 | Load | -| test.cpp:51:33:51:35 | Load indirection | test.cpp:60:34:60:37 | mk_array output argument | -| test.cpp:52:19:52:24 | call to malloc | test.cpp:51:7:51:14 | VariableAddress indirection | -| test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | Load | -| test.cpp:53:5:53:23 | Store | test.cpp:51:33:51:35 | Load indirection | -| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store | -| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... | -| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | Load indirection | -| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | Load | -| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | Load | -| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | Load | -| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:91:20:91:22 | arr indirection [begin] | -| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:95:20:95:22 | arr indirection [begin] | -| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:99:20:99:22 | arr indirection [begin] | -| test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:119:18:119:25 | call to mk_array [begin] | -| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:91:36:91:38 | arr indirection [end] | -| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:95:36:95:38 | arr indirection [end] | -| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:99:35:99:37 | arr indirection [end] | -| test.cpp:80:9:80:16 | VariableAddress indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] | -| test.cpp:82:5:82:28 | Store | test.cpp:82:9:82:13 | arr indirection [post update] [begin] | -| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | VariableAddress indirection [begin] | +| test.cpp:45:16:45:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:45:16:45:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:45:16:45:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:45:16:45:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:45:16:45:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:45:16:45:16 | q | test.cpp:46:16:46:16 | q | +| test.cpp:45:16:45:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:45:16:45:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:45:16:45:16 | q | test.cpp:48:16:48:16 | q | +| test.cpp:46:16:46:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:46:16:46:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:46:16:46:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:46:16:46:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:46:16:46:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:46:16:46:16 | q | test.cpp:47:16:47:16 | q | +| test.cpp:46:16:46:16 | q | test.cpp:48:16:48:16 | q | +| test.cpp:47:16:47:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:47:16:47:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:47:16:47:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:47:16:47:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:47:16:47:16 | q | test.cpp:48:16:48:16 | q | +| test.cpp:48:16:48:16 | q | test.cpp:42:14:42:15 | Load: * ... | +| test.cpp:48:16:48:16 | q | test.cpp:44:14:44:21 | Load: * ... | +| test.cpp:51:7:51:14 | mk_array indirection | test.cpp:60:19:60:26 | call to mk_array | +| test.cpp:51:33:51:35 | end | test.cpp:60:34:60:37 | mk_array output argument | +| test.cpp:52:19:52:24 | call to malloc | test.cpp:51:7:51:14 | mk_array indirection | +| test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | begin | +| test.cpp:53:5:53:23 | ... = ... | test.cpp:51:33:51:35 | end | +| test.cpp:53:12:53:16 | begin | test.cpp:53:5:53:23 | ... = ... | +| test.cpp:53:12:53:16 | begin | test.cpp:53:12:53:23 | ... + ... | +| test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | end | +| test.cpp:60:19:60:26 | call to mk_array | test.cpp:62:39:62:39 | p | +| test.cpp:60:19:60:26 | call to mk_array | test.cpp:66:39:66:39 | p | +| test.cpp:60:19:60:26 | call to mk_array | test.cpp:70:38:70:38 | p | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | end | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | end | +| test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | end | +| test.cpp:62:32:62:34 | end | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:66:32:66:34 | end | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:70:31:70:33 | end | test.cpp:67:9:67:14 | Store: ... = ... | +| test.cpp:80:9:80:16 | mk_array indirection [begin] | test.cpp:89:19:89:26 | call to mk_array [begin] | +| test.cpp:80:9:80:16 | mk_array indirection [begin] | test.cpp:119:18:119:25 | call to mk_array [begin] | +| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:89:19:89:26 | call to mk_array [end] | +| test.cpp:80:9:80:16 | mk_array indirection [end] | test.cpp:119:18:119:25 | call to mk_array [end] | +| test.cpp:82:5:82:28 | ... = ... | test.cpp:82:9:82:13 | arr indirection [post update] [begin] | +| test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:80:9:80:16 | mk_array indirection [begin] | | test.cpp:82:9:82:13 | arr indirection [post update] [begin] | test.cpp:83:15:83:17 | arr indirection [begin] | -| test.cpp:82:17:82:22 | call to malloc | test.cpp:82:5:82:28 | Store | -| test.cpp:83:5:83:30 | Store | test.cpp:83:9:83:11 | arr indirection [post update] [end] | -| test.cpp:83:9:83:11 | arr indirection [post update] [end] | test.cpp:80:9:80:16 | VariableAddress indirection [end] | -| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin | -| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | Store | -| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store | -| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... | -| test.cpp:83:19:83:23 | begin | test.cpp:83:19:83:23 | Load | +| test.cpp:82:17:82:22 | call to malloc | test.cpp:82:5:82:28 | ... = ... | +| test.cpp:83:5:83:30 | ... = ... | test.cpp:83:9:83:11 | arr indirection [post update] [end] | +| test.cpp:83:9:83:11 | arr indirection [post update] [end] | test.cpp:80:9:80:16 | mk_array indirection [end] | +| test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin indirection | +| test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | ... = ... | +| test.cpp:83:19:83:23 | begin | test.cpp:83:5:83:30 | ... = ... | +| test.cpp:83:19:83:23 | begin | test.cpp:83:15:83:30 | ... + ... | +| test.cpp:83:19:83:23 | begin indirection | test.cpp:83:19:83:23 | begin | +| test.cpp:89:19:89:26 | call to mk_array [begin] | test.cpp:91:20:91:22 | arr indirection [begin] | +| test.cpp:89:19:89:26 | call to mk_array [begin] | test.cpp:95:20:95:22 | arr indirection [begin] | +| test.cpp:89:19:89:26 | call to mk_array [begin] | test.cpp:99:20:99:22 | arr indirection [begin] | +| test.cpp:89:19:89:26 | call to mk_array [end] | test.cpp:91:36:91:38 | arr indirection [end] | +| test.cpp:89:19:89:26 | call to mk_array [end] | test.cpp:95:36:95:38 | arr indirection [end] | +| test.cpp:89:19:89:26 | call to mk_array [end] | test.cpp:99:35:99:37 | arr indirection [end] | | test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin | -| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:47:91:47 | Load | -| test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | Load | +| test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin indirection | +| test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | p | +| test.cpp:91:24:91:28 | begin indirection | test.cpp:91:47:91:47 | p | | test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end | -| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:91:40:91:42 | end | test.cpp:91:40:91:42 | Load | +| test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end indirection | +| test.cpp:91:40:91:42 | end | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:91:40:91:42 | end indirection | test.cpp:91:40:91:42 | end | | test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin | -| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:47:95:47 | Load | -| test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | Load | +| test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin indirection | +| test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | p | +| test.cpp:95:24:95:28 | begin indirection | test.cpp:95:47:95:47 | p | | test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end | -| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:95:40:95:42 | end | test.cpp:95:40:95:42 | Load | +| test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end indirection | +| test.cpp:95:40:95:42 | end | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:95:40:95:42 | end indirection | test.cpp:95:40:95:42 | end | | test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin | -| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:46:99:46 | Load | -| test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | Load | +| test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin indirection | +| test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | p | +| test.cpp:99:24:99:28 | begin indirection | test.cpp:99:46:99:46 | p | | test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end | -| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:99:39:99:41 | end | test.cpp:99:39:99:41 | Load | +| test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end indirection | +| test.cpp:99:39:99:41 | end | test.cpp:96:9:96:14 | Store: ... = ... | +| test.cpp:99:39:99:41 | end indirection | test.cpp:99:39:99:41 | end | | test.cpp:104:27:104:29 | arr [begin] | test.cpp:105:20:105:22 | arr indirection [begin] | | test.cpp:104:27:104:29 | arr [begin] | test.cpp:109:20:109:22 | arr indirection [begin] | | test.cpp:104:27:104:29 | arr [begin] | test.cpp:113:20:113:22 | arr indirection [begin] | @@ -418,138 +427,154 @@ edges | test.cpp:104:27:104:29 | arr [end] | test.cpp:109:36:109:38 | arr indirection [end] | | test.cpp:104:27:104:29 | arr [end] | test.cpp:113:35:113:37 | arr indirection [end] | | test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:24:105:28 | begin | -| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:47:105:47 | Load | -| test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | Load | +| test.cpp:105:20:105:22 | arr indirection [begin] | test.cpp:105:24:105:28 | begin indirection | +| test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | p | +| test.cpp:105:24:105:28 | begin indirection | test.cpp:105:47:105:47 | p | | test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end | -| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:105:40:105:42 | end | test.cpp:105:40:105:42 | Load | +| test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end indirection | +| test.cpp:105:40:105:42 | end | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:105:40:105:42 | end indirection | test.cpp:105:40:105:42 | end | | test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin | -| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:47:109:47 | Load | -| test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | Load | +| test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin indirection | +| test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | p | +| test.cpp:109:24:109:28 | begin indirection | test.cpp:109:47:109:47 | p | | test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end | -| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:109:40:109:42 | end | test.cpp:109:40:109:42 | Load | +| test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end indirection | +| test.cpp:109:40:109:42 | end | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:109:40:109:42 | end indirection | test.cpp:109:40:109:42 | end | | test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin | -| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:46:113:46 | Load | -| test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | Load | +| test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin indirection | +| test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | p | +| test.cpp:113:24:113:28 | begin indirection | test.cpp:113:46:113:46 | p | | test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end | -| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:113:39:113:41 | end | test.cpp:113:39:113:41 | Load | +| test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end indirection | +| test.cpp:113:39:113:41 | end | test.cpp:110:9:110:14 | Store: ... = ... | +| test.cpp:113:39:113:41 | end indirection | test.cpp:113:39:113:41 | end | | test.cpp:119:18:119:25 | call to mk_array [begin] | test.cpp:104:27:104:29 | arr [begin] | | test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] | -| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | Store | -| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | Load | -| test.cpp:125:5:125:17 | Store | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | +| test.cpp:124:15:124:20 | call to malloc | test.cpp:125:5:125:17 | ... = ... | +| test.cpp:124:15:124:20 | call to malloc | test.cpp:126:15:126:15 | p | +| test.cpp:125:5:125:17 | ... = ... | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:129:11:129:13 | arr indirection [begin] | | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:133:11:133:13 | arr indirection [begin] | | test.cpp:125:9:125:13 | arr indirection [post update] [begin] | test.cpp:137:11:137:13 | arr indirection [begin] | -| test.cpp:129:11:129:13 | arr indirection [begin] | test.cpp:129:15:129:19 | begin | -| test.cpp:129:15:129:19 | begin | test.cpp:129:15:129:19 | Load | -| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin | -| test.cpp:133:15:133:19 | begin | test.cpp:133:15:133:19 | Load | -| test.cpp:137:11:137:13 | arr indirection [begin] | test.cpp:137:15:137:19 | begin | -| test.cpp:137:15:137:19 | begin | test.cpp:137:15:137:19 | Load | -| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:150:20:150:29 | Call indirection [begin] | -| test.cpp:141:10:141:19 | VariableAddress indirection [begin] | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | -| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:150:20:150:29 | Call indirection [end] | -| test.cpp:141:10:141:19 | VariableAddress indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | -| test.cpp:143:5:143:29 | Store | test.cpp:143:10:143:14 | Load indirection [post update] [begin] | -| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:141:10:141:19 | VariableAddress indirection [begin] | -| test.cpp:143:10:143:14 | Load indirection [post update] [begin] | test.cpp:144:16:144:18 | Load indirection [begin] | -| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | Store | -| test.cpp:144:5:144:32 | Store | test.cpp:144:10:144:12 | Load indirection [post update] [end] | -| test.cpp:144:10:144:12 | Load indirection [post update] [end] | test.cpp:141:10:141:19 | VariableAddress indirection [end] | -| test.cpp:144:16:144:18 | Load indirection [begin] | test.cpp:144:21:144:25 | begin | -| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | Store | -| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store | -| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... | -| test.cpp:144:21:144:25 | begin | test.cpp:144:21:144:25 | Load | -| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:152:20:152:22 | Load indirection [begin] | -| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:156:20:156:22 | Load indirection [begin] | -| test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:160:20:160:22 | Load indirection [begin] | -| test.cpp:150:20:150:29 | Call indirection [end] | test.cpp:156:37:156:39 | Load indirection [end] | -| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:25:152:29 | begin | -| test.cpp:152:20:152:22 | Load indirection [begin] | test.cpp:152:49:152:49 | Load | -| test.cpp:152:25:152:29 | begin | test.cpp:152:49:152:49 | Load | -| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:25:156:29 | begin | -| test.cpp:156:20:156:22 | Load indirection [begin] | test.cpp:156:49:156:49 | Load | -| test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | Load | -| test.cpp:156:37:156:39 | Load indirection [end] | test.cpp:156:42:156:44 | end | -| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... | -| test.cpp:156:42:156:44 | end | test.cpp:156:42:156:44 | Load | -| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:25:160:29 | begin | -| test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:48:160:48 | Load | -| test.cpp:160:25:160:29 | begin | test.cpp:160:48:160:48 | Load | -| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:166:20:166:22 | Load indirection [begin] | -| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:170:20:170:22 | Load indirection [begin] | -| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:174:20:174:22 | Load indirection [begin] | -| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:166:37:166:39 | Load indirection [end] | -| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:170:37:170:39 | Load indirection [end] | -| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:174:36:174:38 | Load indirection [end] | -| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:25:166:29 | begin | -| test.cpp:166:20:166:22 | Load indirection [begin] | test.cpp:166:49:166:49 | Load | -| test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | Load | -| test.cpp:166:37:166:39 | Load indirection [end] | test.cpp:166:42:166:44 | end | -| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:166:42:166:44 | end | test.cpp:166:42:166:44 | Load | -| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:25:170:29 | begin | -| test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:49:170:49 | Load | -| test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | Load | -| test.cpp:170:37:170:39 | Load indirection [end] | test.cpp:170:42:170:44 | end | -| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:170:42:170:44 | end | test.cpp:170:42:170:44 | Load | -| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:25:174:29 | begin | -| test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:48:174:48 | Load | -| test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | Load | -| test.cpp:174:36:174:38 | Load indirection [end] | test.cpp:174:41:174:43 | end | -| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:174:41:174:43 | end | test.cpp:174:41:174:43 | Load | +| test.cpp:129:11:129:13 | arr indirection [begin] | test.cpp:129:15:129:19 | begin indirection | +| test.cpp:129:15:129:19 | begin indirection | test.cpp:129:15:129:19 | begin | +| test.cpp:133:11:133:13 | arr indirection [begin] | test.cpp:133:15:133:19 | begin indirection | +| test.cpp:133:15:133:19 | begin indirection | test.cpp:133:15:133:19 | begin | +| test.cpp:137:11:137:13 | arr indirection [begin] | test.cpp:137:15:137:19 | begin indirection | +| test.cpp:137:15:137:19 | begin indirection | test.cpp:137:15:137:19 | begin | +| test.cpp:141:10:141:19 | mk_array_p indirection [begin] | test.cpp:150:20:150:29 | call to mk_array_p indirection [begin] | +| test.cpp:141:10:141:19 | mk_array_p indirection [begin] | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | +| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:150:20:150:29 | call to mk_array_p indirection [end] | +| test.cpp:141:10:141:19 | mk_array_p indirection [end] | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | +| test.cpp:143:5:143:29 | ... = ... | test.cpp:143:10:143:14 | arr indirection [post update] [begin] | +| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:141:10:141:19 | mk_array_p indirection [begin] | +| test.cpp:143:10:143:14 | arr indirection [post update] [begin] | test.cpp:144:16:144:18 | arr indirection [begin] | +| test.cpp:143:18:143:23 | call to malloc | test.cpp:143:5:143:29 | ... = ... | +| test.cpp:144:5:144:32 | ... = ... | test.cpp:144:10:144:12 | arr indirection [post update] [end] | +| test.cpp:144:10:144:12 | arr indirection [post update] [end] | test.cpp:141:10:141:19 | mk_array_p indirection [end] | +| test.cpp:144:16:144:18 | arr indirection [begin] | test.cpp:144:21:144:25 | begin indirection | +| test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | ... = ... | +| test.cpp:144:21:144:25 | begin | test.cpp:144:5:144:32 | ... = ... | +| test.cpp:144:21:144:25 | begin | test.cpp:144:16:144:32 | ... + ... | +| test.cpp:144:21:144:25 | begin indirection | test.cpp:144:21:144:25 | begin | +| test.cpp:150:20:150:29 | call to mk_array_p indirection [begin] | test.cpp:152:20:152:22 | arr indirection [begin] | +| test.cpp:150:20:150:29 | call to mk_array_p indirection [begin] | test.cpp:156:20:156:22 | arr indirection [begin] | +| test.cpp:150:20:150:29 | call to mk_array_p indirection [begin] | test.cpp:160:20:160:22 | arr indirection [begin] | +| test.cpp:150:20:150:29 | call to mk_array_p indirection [end] | test.cpp:156:37:156:39 | arr indirection [end] | +| test.cpp:152:20:152:22 | arr indirection [begin] | test.cpp:152:25:152:29 | begin | +| test.cpp:152:20:152:22 | arr indirection [begin] | test.cpp:152:25:152:29 | begin indirection | +| test.cpp:152:25:152:29 | begin | test.cpp:152:49:152:49 | p | +| test.cpp:152:25:152:29 | begin indirection | test.cpp:152:49:152:49 | p | +| test.cpp:156:20:156:22 | arr indirection [begin] | test.cpp:156:25:156:29 | begin | +| test.cpp:156:20:156:22 | arr indirection [begin] | test.cpp:156:25:156:29 | begin indirection | +| test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | p | +| test.cpp:156:25:156:29 | begin indirection | test.cpp:156:49:156:49 | p | +| test.cpp:156:37:156:39 | arr indirection [end] | test.cpp:156:42:156:44 | end | +| test.cpp:156:37:156:39 | arr indirection [end] | test.cpp:156:42:156:44 | end indirection | +| test.cpp:156:42:156:44 | end | test.cpp:157:9:157:14 | Store: ... = ... | +| test.cpp:156:42:156:44 | end indirection | test.cpp:156:42:156:44 | end | +| test.cpp:160:20:160:22 | arr indirection [begin] | test.cpp:160:25:160:29 | begin | +| test.cpp:160:20:160:22 | arr indirection [begin] | test.cpp:160:25:160:29 | begin indirection | +| test.cpp:160:25:160:29 | begin | test.cpp:160:48:160:48 | p | +| test.cpp:160:25:160:29 | begin indirection | test.cpp:160:48:160:48 | p | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:166:20:166:22 | arr indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:170:20:170:22 | arr indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [begin] | test.cpp:174:20:174:22 | arr indirection [begin] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:166:37:166:39 | arr indirection [end] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:170:37:170:39 | arr indirection [end] | +| test.cpp:165:29:165:31 | arr indirection [end] | test.cpp:174:36:174:38 | arr indirection [end] | +| test.cpp:166:20:166:22 | arr indirection [begin] | test.cpp:166:25:166:29 | begin | +| test.cpp:166:20:166:22 | arr indirection [begin] | test.cpp:166:25:166:29 | begin indirection | +| test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | p | +| test.cpp:166:25:166:29 | begin indirection | test.cpp:166:49:166:49 | p | +| test.cpp:166:37:166:39 | arr indirection [end] | test.cpp:166:42:166:44 | end | +| test.cpp:166:37:166:39 | arr indirection [end] | test.cpp:166:42:166:44 | end indirection | +| test.cpp:166:42:166:44 | end | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:166:42:166:44 | end indirection | test.cpp:166:42:166:44 | end | +| test.cpp:170:20:170:22 | arr indirection [begin] | test.cpp:170:25:170:29 | begin | +| test.cpp:170:20:170:22 | arr indirection [begin] | test.cpp:170:25:170:29 | begin indirection | +| test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | p | +| test.cpp:170:25:170:29 | begin indirection | test.cpp:170:49:170:49 | p | +| test.cpp:170:37:170:39 | arr indirection [end] | test.cpp:170:42:170:44 | end | +| test.cpp:170:37:170:39 | arr indirection [end] | test.cpp:170:42:170:44 | end indirection | +| test.cpp:170:42:170:44 | end | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:170:42:170:44 | end indirection | test.cpp:170:42:170:44 | end | +| test.cpp:174:20:174:22 | arr indirection [begin] | test.cpp:174:25:174:29 | begin | +| test.cpp:174:20:174:22 | arr indirection [begin] | test.cpp:174:25:174:29 | begin indirection | +| test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | p | +| test.cpp:174:25:174:29 | begin indirection | test.cpp:174:48:174:48 | p | +| test.cpp:174:36:174:38 | arr indirection [end] | test.cpp:174:41:174:43 | end | +| test.cpp:174:36:174:38 | arr indirection [end] | test.cpp:174:41:174:43 | end indirection | +| test.cpp:174:41:174:43 | end | test.cpp:171:9:171:14 | Store: ... = ... | +| test.cpp:174:41:174:43 | end indirection | test.cpp:174:41:174:43 | end | | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | test.cpp:165:29:165:31 | arr indirection [begin] | | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] | -| test.cpp:188:15:188:20 | call to malloc | test.cpp:189:15:189:15 | Load | -| test.cpp:194:23:194:28 | call to malloc | test.cpp:195:17:195:17 | Load | -| test.cpp:194:23:194:28 | call to malloc | test.cpp:197:8:197:8 | Load | -| test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:5 | Load | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load | -| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array | -| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:23 | ... + ... | test.cpp:197:20:197:22 | Load | +| test.cpp:188:15:188:20 | call to malloc | test.cpp:189:15:189:15 | p | +| test.cpp:194:23:194:28 | call to malloc | test.cpp:195:17:195:17 | p | +| test.cpp:194:23:194:28 | call to malloc | test.cpp:197:8:197:8 | p | +| test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:5 | p | +| test.cpp:195:17:195:17 | p | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:17 | p | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:17 | p | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:17 | p | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:17 | p | test.cpp:197:20:197:22 | end | +| test.cpp:195:17:195:17 | p | test.cpp:201:5:201:12 | access to array | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | ... + ... | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:197:20:197:22 | end | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:197:20:197:22 | end | | test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:195:17:195:23 | Store | test.cpp:197:20:197:22 | Load | -| test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:197:20:197:22 | Load | test.cpp:201:5:201:19 | Store: ... = ... | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | Store: ... = ... | +| test.cpp:195:17:195:23 | ... + ... | test.cpp:201:5:201:19 | Store: ... = ... | +| test.cpp:197:20:197:22 | end | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:201:5:201:12 | access to array | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:205:23:205:28 | call to malloc | test.cpp:206:17:206:17 | Load | -| test.cpp:205:23:205:28 | call to malloc | test.cpp:208:15:208:15 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... | -| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | -| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:23 | ... + ... | test.cpp:209:12:209:14 | Load | +| test.cpp:205:23:205:28 | call to malloc | test.cpp:206:17:206:17 | p | +| test.cpp:205:23:205:28 | call to malloc | test.cpp:208:15:208:15 | p | +| test.cpp:206:17:206:17 | p | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:17 | p | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:17 | p | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:17 | p | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:17 | p | test.cpp:209:12:209:14 | end | +| test.cpp:206:17:206:17 | p | test.cpp:213:5:213:6 | * ... | +| test.cpp:206:17:206:17 | p | test.cpp:213:6:213:6 | q | +| test.cpp:206:17:206:17 | p | test.cpp:213:6:213:6 | q | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | ... + ... | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:209:12:209:14 | end | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:209:12:209:14 | end | | test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:206:17:206:23 | Store | test.cpp:209:12:209:14 | Load | -| test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:209:12:209:14 | Load | test.cpp:213:5:213:13 | Store: ... = ... | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | Store: ... = ... | +| test.cpp:206:17:206:23 | ... + ... | test.cpp:213:5:213:13 | Store: ... = ... | +| test.cpp:209:12:209:14 | end | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:213:5:213:6 | * ... | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:6 | * ... | -| test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:221:17:221:22 | call to malloc | test.cpp:222:5:222:5 | Load | +| test.cpp:213:6:213:6 | q | test.cpp:213:5:213:6 | * ... | +| test.cpp:213:6:213:6 | q | test.cpp:213:5:213:13 | Store: ... = ... | +| test.cpp:213:6:213:6 | q | test.cpp:213:5:213:13 | Store: ... = ... | +| test.cpp:221:17:221:22 | call to malloc | test.cpp:222:5:222:5 | p | #select | test.cpp:6:14:6:15 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:6:14:6:15 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | | test.cpp:8:14:8:21 | Load: * ... | test.cpp:4:15:4:20 | call to malloc | test.cpp:8:14:8:21 | Load: * ... | This read might be out of bounds, as the pointer might be equal to $@ + $@ + 1. | test.cpp:4:15:4:20 | call to malloc | call to malloc | test.cpp:5:19:5:22 | size | size | diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected index b5b943e5415..d2d00140255 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-359/semmle/tests/PrivateCleartextWrite.expected @@ -1,13 +1,31 @@ edges -| test.cpp:45:18:45:23 | buffer | test.cpp:47:10:47:15 | buffer | +| test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | func indirection | +| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | +| test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | +| test.cpp:74:24:74:30 | medical | test.cpp:81:22:81:28 | medical | | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | +| test.cpp:77:16:77:22 | medical | test.cpp:81:22:81:28 | medical | | test.cpp:81:17:81:20 | call to func | test.cpp:82:24:82:28 | buff5 | | test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | | test.cpp:81:22:81:28 | medical | test.cpp:81:17:81:20 | call to func | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | +| test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | nodes +| test.cpp:45:7:45:10 | func indirection | semmle.label | func indirection | | test.cpp:45:18:45:23 | buffer | semmle.label | buffer | -| test.cpp:47:10:47:15 | buffer | semmle.label | buffer | | test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode | +| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode | +| test.cpp:57:9:57:18 | theZipcode | semmle.label | theZipcode | +| test.cpp:74:24:74:30 | medical | semmle.label | medical | | test.cpp:74:24:74:30 | medical | semmle.label | medical | | test.cpp:77:16:77:22 | medical | semmle.label | medical | | test.cpp:78:24:78:27 | temp | semmle.label | temp | @@ -15,13 +33,35 @@ nodes | test.cpp:81:22:81:28 | medical | semmle.label | medical | | test.cpp:82:24:82:28 | buff5 | semmle.label | buff5 | | test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode | +| test.cpp:96:37:96:46 | theZipcode | semmle.label | theZipcode | | test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode | +| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode | +| test.cpp:99:42:99:51 | theZipcode | semmle.label | theZipcode | +| test.cpp:99:61:99:70 | theZipcode | semmle.label | theZipcode | +| test.cpp:99:61:99:70 | theZipcode | semmle.label | theZipcode | subpaths -| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | test.cpp:47:10:47:15 | buffer | test.cpp:81:17:81:20 | call to func | +| test.cpp:81:22:81:28 | medical | test.cpp:45:18:45:23 | buffer | test.cpp:45:7:45:10 | func indirection | test.cpp:81:17:81:20 | call to func | #select | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. | +| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. | +| test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | test.cpp:57:9:57:18 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:57:9:57:18 | theZipcode | this source of private data. | | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | test.cpp:74:24:74:30 | medical | This write into the external location 'medical' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. | +| test.cpp:78:24:78:27 | temp | test.cpp:74:24:74:30 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. | | test.cpp:78:24:78:27 | temp | test.cpp:77:16:77:22 | medical | test.cpp:78:24:78:27 | temp | This write into the external location 'temp' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. | +| test.cpp:82:24:82:28 | buff5 | test.cpp:74:24:74:30 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:74:24:74:30 | medical | this source of private data. | +| test.cpp:82:24:82:28 | buff5 | test.cpp:77:16:77:22 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:77:16:77:22 | medical | this source of private data. | | test.cpp:82:24:82:28 | buff5 | test.cpp:81:22:81:28 | medical | test.cpp:82:24:82:28 | buff5 | This write into the external location 'buff5' may contain unencrypted data from $@. | test.cpp:81:22:81:28 | medical | this source of private data. | | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:96:37:96:46 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:96:37:96:46 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:96:37:96:46 | theZipcode | this source of private data. | | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:42:99:51 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:61:99:70 | theZipcode | this source of private data. | +| test.cpp:99:42:99:51 | theZipcode | test.cpp:99:61:99:70 | theZipcode | test.cpp:99:42:99:51 | theZipcode | This write into the external location 'theZipcode' may contain unencrypted data from $@. | test.cpp:99:61:99:70 | theZipcode | this source of private data. | diff --git a/cpp/ql/test/library-tests/CPP-205/elements.expected b/cpp/ql/test/library-tests/CPP-205/elements.expected index 8fbe5a0734f..f64b9d4e08b 100644 --- a/cpp/ql/test/library-tests/CPP-205/elements.expected +++ b/cpp/ql/test/library-tests/CPP-205/elements.expected @@ -1,14 +1,14 @@ | CPP-205.cpp:0:0:0:0 | CPP-205.cpp | | | CPP-205.cpp:1:20:1:20 | T | | | CPP-205.cpp:1:20:1:20 | definition of T | | -| CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for fn(int) -> int | -| CPP-205.cpp:2:5:2:5 | fn | function fn(int) -> int | -| CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for fn(T) -> int | -| CPP-205.cpp:2:5:2:6 | fn | function fn(T) -> int | -| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for fn(T) -> int | -| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for fn(int) -> int | -| CPP-205.cpp:2:10:2:12 | out | parameter for fn(T) -> int | -| CPP-205.cpp:2:10:2:12 | out | parameter for fn(int) -> int | +| CPP-205.cpp:2:5:2:5 | definition of fn | function declaration entry for int fn(int) | +| CPP-205.cpp:2:5:2:5 | fn | function int fn(int) | +| CPP-205.cpp:2:5:2:6 | definition of fn | function declaration entry for int fn(T) | +| CPP-205.cpp:2:5:2:6 | fn | function int fn(T) | +| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn(T) | +| CPP-205.cpp:2:10:2:12 | definition of out | parameter declaration entry for int fn(int) | +| CPP-205.cpp:2:10:2:12 | out | parameter for int fn(T) | +| CPP-205.cpp:2:10:2:12 | out | parameter for int fn(int) | | CPP-205.cpp:2:15:5:1 | { ... } | | | CPP-205.cpp:2:15:5:1 | { ... } | | | CPP-205.cpp:3:3:3:33 | declaration | | @@ -20,16 +20,16 @@ | CPP-205.cpp:4:3:4:11 | return ... | | | CPP-205.cpp:4:10:4:10 | 0 | | | CPP-205.cpp:4:10:4:10 | 0 | | -| CPP-205.cpp:7:5:7:8 | definition of main | function declaration entry for main() -> int | -| CPP-205.cpp:7:5:7:8 | main | function main() -> int | +| CPP-205.cpp:7:5:7:8 | definition of main | function declaration entry for int main() | +| CPP-205.cpp:7:5:7:8 | main | function int main() | | CPP-205.cpp:7:12:9:1 | { ... } | | | CPP-205.cpp:8:3:8:15 | return ... | | | CPP-205.cpp:8:10:8:11 | call to fn | | | CPP-205.cpp:8:13:8:13 | 0 | | -| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | -| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | +| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | +| file://:0:0:0:0 | (unnamed parameter 0) | parameter for __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | | file://:0:0:0:0 | __super | | | file://:0:0:0:0 | __va_list_tag | | -| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | -| file://:0:0:0:0 | operator= | function __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | +| file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | +| file://:0:0:0:0 | operator= | function __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | | file://:0:0:0:0 | y | | diff --git a/cpp/ql/test/library-tests/CPP-205/elements.ql b/cpp/ql/test/library-tests/CPP-205/elements.ql index 0b75bca9bb2..9388a799dbc 100644 --- a/cpp/ql/test/library-tests/CPP-205/elements.ql +++ b/cpp/ql/test/library-tests/CPP-205/elements.ql @@ -1,17 +1,19 @@ import cpp +import semmle.code.cpp.Print string describe(Element e) { - result = "function " + e.(Function).getFullSignature() + e instanceof Function and + result = "function " + getIdentityString(e) or result = "function declaration entry for " + - e.(FunctionDeclarationEntry).getFunction().getFullSignature() + getIdentityString(e.(FunctionDeclarationEntry).getFunction()) or - result = "parameter for " + e.(Parameter).getFunction().getFullSignature() + result = "parameter for " + getIdentityString(e.(Parameter).getFunction()) or result = "parameter declaration entry for " + - e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction().getFullSignature() + getIdentityString(e.(ParameterDeclarationEntry).getFunctionDeclarationEntry().getFunction()) } from Element e diff --git a/cpp/ql/test/library-tests/allocators/allocators.expected b/cpp/ql/test/library-tests/allocators/allocators.expected index 5fdf7e50b90..5e7d573c83e 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.expected +++ b/cpp/ql/test/library-tests/allocators/allocators.expected @@ -1,51 +1,51 @@ newExprs -| allocators.cpp:49:3:49:9 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | -| allocators.cpp:50:3:50:15 | new | int | operator new(size_t, float) -> void * | 4 | 4 | | | -| allocators.cpp:51:3:51:11 | new | int | operator new(unsigned long) -> void * | 4 | 4 | | | -| allocators.cpp:52:3:52:14 | new | String | operator new(unsigned long) -> void * | 8 | 8 | | | -| allocators.cpp:53:3:53:27 | new | String | operator new(size_t, float) -> void * | 8 | 8 | | | -| allocators.cpp:54:3:54:17 | new | Overaligned | operator new(unsigned long, align_val_t) -> void * | 256 | 128 | aligned | | -| allocators.cpp:55:3:55:25 | new | Overaligned | operator new(size_t, align_val_t, float) -> void * | 256 | 128 | aligned | | -| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator new(size_t) -> void * | 1 | 1 | | | -| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator new(size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | -| allocators.cpp:129:3:129:21 | new | int | operator new(size_t, void *) -> void * | 4 | 4 | | & ... | -| allocators.cpp:135:3:135:26 | new | int | operator new(size_t, const nothrow_t &) -> void * | 4 | 4 | | | +| allocators.cpp:49:3:49:9 | new | int | void* operator new(unsigned long) | 4 | 4 | | | +| allocators.cpp:50:3:50:15 | new | int | void* operator new(size_t, float) | 4 | 4 | | | +| allocators.cpp:51:3:51:11 | new | int | void* operator new(unsigned long) | 4 | 4 | | | +| allocators.cpp:52:3:52:14 | new | String | void* operator new(unsigned long) | 8 | 8 | | | +| allocators.cpp:53:3:53:27 | new | String | void* operator new(size_t, float) | 8 | 8 | | | +| allocators.cpp:54:3:54:17 | new | Overaligned | void* operator new(unsigned long, std::align_val_t) | 256 | 128 | aligned | | +| allocators.cpp:55:3:55:25 | new | Overaligned | void* operator new(size_t, std::align_val_t, float) | 256 | 128 | aligned | | +| allocators.cpp:107:3:107:18 | new | FailedInit | void* FailedInit::operator new(size_t) | 1 | 1 | | | +| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void* FailedInitOveraligned::operator new(size_t, std::align_val_t, float) | 128 | 128 | aligned | | +| allocators.cpp:129:3:129:21 | new | int | void* operator new(std::size_t, void*) | 4 | 4 | | & ... | +| allocators.cpp:135:3:135:26 | new | int | void* operator new(std::size_t, std::nothrow_t const&) | 4 | 4 | | | newArrayExprs -| allocators.cpp:68:3:68:12 | new[] | int[] | int | operator new[](unsigned long) -> void * | 4 | 4 | | n | | -| allocators.cpp:69:3:69:18 | new[] | int[] | int | operator new[](size_t, float) -> void * | 4 | 4 | | n | | -| allocators.cpp:70:3:70:15 | new[] | String[] | String | operator new[](unsigned long) -> void * | 8 | 8 | | n | | -| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | operator new[](unsigned long, align_val_t) -> void * | 256 | 128 | aligned | n | | -| allocators.cpp:72:3:72:16 | new[] | String[10] | String | operator new[](unsigned long) -> void * | 8 | 8 | | | | -| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | FailedInit::operator new[](size_t) -> void * | 1 | 1 | | n | | -| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | FailedInitOveraligned::operator new[](size_t, align_val_t, float) -> void * | 128 | 128 | aligned | | | -| allocators.cpp:132:3:132:17 | new[] | int[1] | int | operator new[](size_t, void *) -> void * | 4 | 4 | | | buf | -| allocators.cpp:136:3:136:26 | new[] | int[2] | int | operator new[](size_t, const nothrow_t &) -> void * | 4 | 4 | | | | -| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | operator new[](unsigned long) -> void * | 10 | 1 | | x | | -| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | operator new[](unsigned long) -> void * | 20 | 1 | | | | -| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | operator new[](unsigned long) -> void * | 900 | 1 | | x | | +| allocators.cpp:68:3:68:12 | new[] | int[] | int | void* operator new[](unsigned long) | 4 | 4 | | n | | +| allocators.cpp:69:3:69:18 | new[] | int[] | int | void* operator new[](size_t, float) | 4 | 4 | | n | | +| allocators.cpp:70:3:70:15 | new[] | String[] | String | void* operator new[](unsigned long) | 8 | 8 | | n | | +| allocators.cpp:71:3:71:20 | new[] | Overaligned[] | Overaligned | void* operator new[](unsigned long, std::align_val_t) | 256 | 128 | aligned | n | | +| allocators.cpp:72:3:72:16 | new[] | String[10] | String | void* operator new[](unsigned long) | 8 | 8 | | | | +| allocators.cpp:108:3:108:19 | new[] | FailedInit[] | FailedInit | void* FailedInit::operator new[](size_t) | 1 | 1 | | n | | +| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned[10] | FailedInitOveraligned | void* FailedInitOveraligned::operator new[](size_t, std::align_val_t, float) | 128 | 128 | aligned | | | +| allocators.cpp:132:3:132:17 | new[] | int[1] | int | void* operator new[](std::size_t, void*) | 4 | 4 | | | buf | +| allocators.cpp:136:3:136:26 | new[] | int[2] | int | void* operator new[](std::size_t, std::nothrow_t const&) | 4 | 4 | | | | +| allocators.cpp:142:13:142:27 | new[] | char[][10] | char[10] | void* operator new[](unsigned long) | 10 | 1 | | x | | +| allocators.cpp:143:13:143:28 | new[] | char[20][20] | char[20] | void* operator new[](unsigned long) | 20 | 1 | | | | +| allocators.cpp:144:13:144:31 | new[] | char[][30][30] | char[30][30] | void* operator new[](unsigned long) | 900 | 1 | | x | | newExprDeallocators -| allocators.cpp:52:3:52:14 | new | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:53:3:53:27 | new | String | operator delete(void *, float) -> void | 8 | 8 | | -| allocators.cpp:107:3:107:18 | new | FailedInit | FailedInit::operator delete(void *, size_t) -> void | 1 | 1 | sized | -| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | FailedInitOveraligned::operator delete(void *, align_val_t, float) -> void | 128 | 128 | aligned | +| allocators.cpp:52:3:52:14 | new | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:53:3:53:27 | new | String | void operator delete(void*, float) | 8 | 8 | | +| allocators.cpp:107:3:107:18 | new | FailedInit | void FailedInit::operator delete(void*, size_t) | 1 | 1 | sized | +| allocators.cpp:109:3:109:35 | new | FailedInitOveraligned | void FailedInitOveraligned::operator delete(void*, std::align_val_t, float) | 128 | 128 | aligned | newArrayExprDeallocators -| allocators.cpp:70:3:70:15 | new[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:72:3:72:16 | new[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:108:3:108:19 | new[] | FailedInit | FailedInit::operator delete[](void *, size_t) -> void | 1 | 1 | sized | -| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | FailedInitOveraligned::operator delete[](void *, align_val_t, float) -> void | 128 | 128 | aligned | +| allocators.cpp:70:3:70:15 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:72:3:72:16 | new[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:108:3:108:19 | new[] | FailedInit | void FailedInit::operator delete[](void*, size_t) | 1 | 1 | sized | +| allocators.cpp:110:3:110:37 | new[] | FailedInitOveraligned | void FailedInitOveraligned::operator delete[](void*, std::align_val_t, float) | 128 | 128 | aligned | deleteExprs -| allocators.cpp:59:3:59:35 | delete | int | operator delete(void *, unsigned long) -> void | 4 | 4 | sized | -| allocators.cpp:60:3:60:38 | delete | String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:61:3:61:44 | delete | SizedDealloc | SizedDealloc::operator delete(void *, size_t) -> void | 32 | 1 | sized | -| allocators.cpp:62:3:62:43 | delete | Overaligned | operator delete(void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | -| allocators.cpp:64:3:64:44 | delete | const String | operator delete(void *, unsigned long) -> void | 8 | 8 | sized | +| allocators.cpp:59:3:59:35 | delete | int | void operator delete(void*, unsigned long) | 4 | 4 | sized | +| allocators.cpp:60:3:60:38 | delete | String | void operator delete(void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:61:3:61:44 | delete | SizedDealloc | void SizedDealloc::operator delete(void*, size_t) | 32 | 1 | sized | +| allocators.cpp:62:3:62:43 | delete | Overaligned | void operator delete(void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | +| allocators.cpp:64:3:64:44 | delete | const String | void operator delete(void*, unsigned long) | 8 | 8 | sized | deleteArrayExprs -| allocators.cpp:78:3:78:37 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | -| allocators.cpp:79:3:79:40 | delete[] | String | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | SizedDealloc::operator delete[](void *, size_t) -> void | 32 | 1 | sized | -| allocators.cpp:81:3:81:45 | delete[] | Overaligned | operator delete[](void *, unsigned long, align_val_t) -> void | 256 | 128 | sized aligned | -| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | operator delete[](void *, unsigned long) -> void | 8 | 8 | sized | -| allocators.cpp:83:3:83:23 | delete[] | int | operator delete[](void *, unsigned long) -> void | 4 | 4 | sized | +| allocators.cpp:78:3:78:37 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized | +| allocators.cpp:79:3:79:40 | delete[] | String | void operator delete[](void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:80:3:80:46 | delete[] | SizedDealloc | void SizedDealloc::operator delete[](void*, size_t) | 32 | 1 | sized | +| allocators.cpp:81:3:81:45 | delete[] | Overaligned | void operator delete[](void*, unsigned long, std::align_val_t) | 256 | 128 | sized aligned | +| allocators.cpp:82:3:82:49 | delete[] | PolymorphicBase | void operator delete[](void*, unsigned long) | 8 | 8 | sized | +| allocators.cpp:83:3:83:23 | delete[] | int | void operator delete[](void*, unsigned long) | 4 | 4 | sized | allocationFunctions | allocators.cpp:7:7:7:18 | operator new | getSizeArg = 0, requiresDealloc | | allocators.cpp:8:7:8:20 | operator new[] | getSizeArg = 0, requiresDealloc | diff --git a/cpp/ql/test/library-tests/allocators/allocators.ql b/cpp/ql/test/library-tests/allocators/allocators.ql index a2126cdfbce..2d70f2f5083 100644 --- a/cpp/ql/test/library-tests/allocators/allocators.ql +++ b/cpp/ql/test/library-tests/allocators/allocators.ql @@ -1,12 +1,13 @@ import cpp import semmle.code.cpp.models.implementations.Allocation +import semmle.code.cpp.Print query predicate newExprs( NewExpr expr, string type, string sig, int size, int alignment, string form, string placement ) { exists(Function allocator, Type allocatedType | expr.getAllocator() = allocator and - sig = allocator.getFullSignature() and + sig = getIdentityString(allocator) and allocatedType = expr.getAllocatedType() and type = allocatedType.toString() and size = allocatedType.getSize() and @@ -24,7 +25,7 @@ query predicate newArrayExprs( ) { exists(Function allocator, Type arrayType, Type elementType | expr.getAllocator() = allocator and - sig = allocator.getFullSignature() and + sig = getIdentityString(allocator) and arrayType = expr.getAllocatedType() and t1 = arrayType.toString() and elementType = expr.getAllocatedElementType() and @@ -44,7 +45,7 @@ query predicate newExprDeallocators( ) { exists(Function deallocator, Type allocatedType | expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and + sig = getIdentityString(deallocator) and allocatedType = expr.getAllocatedType() and type = allocatedType.toString() and size = allocatedType.getSize() and @@ -62,7 +63,7 @@ query predicate newArrayExprDeallocators( ) { exists(Function deallocator, Type elementType | expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and + sig = getIdentityString(deallocator) and elementType = expr.getAllocatedElementType() and type = elementType.toString() and size = elementType.getSize() and @@ -80,7 +81,7 @@ query predicate deleteExprs( ) { exists(Function deallocator, Type deletedType | expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and + sig = getIdentityString(deallocator) and deletedType = expr.getDeletedObjectType() and type = deletedType.toString() and size = deletedType.getSize() and @@ -98,7 +99,7 @@ query predicate deleteArrayExprs( ) { exists(Function deallocator, Type elementType | expr.getDeallocator() = deallocator and - sig = deallocator.getFullSignature() and + sig = getIdentityString(deallocator) and elementType = expr.getDeletedElementType() and type = elementType.toString() and size = elementType.getSize() and diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp index e80991d4fb3..231b7dfddc1 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/annotate_sinks_only/defaulttainttracking.cpp @@ -7,7 +7,7 @@ int main() { char untainted_buf[100] = ""; char buf[100] = "VAR = "; - sink(strcat(buf, getenv("VAR"))); // $ ast MISSING: ir + sink(strcat(buf, getenv("VAR"))); // $ ast,ir sink(buf); // $ ast,ir sink(untainted_buf); // the two buffers would be conflated if we added flow through all partial chi inputs diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql index 58bbec1c780..1497702db76 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/standardFlow.ql @@ -1,14 +1,12 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow -class TestConfig extends DataFlow::Configuration { - TestConfig() { this = "TestConfig" } - - override predicate isSource(DataFlow::Node source) { +module TestConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(FunctionCall call | call.getTarget().getName() = "sink" and sink.asExpr() = call.getAnArgument() @@ -16,6 +14,8 @@ class TestConfig extends DataFlow::Configuration { } } -from DataFlow::Node sink, DataFlow::Node source, TestConfig cfg -where cfg.hasFlow(source, sink) +module TestFlow = DataFlow::Make; + +from DataFlow::Node sink, DataFlow::Node source +where TestFlow::hasFlow(source, sink) select sink, source diff --git a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql index a1ad99aeef0..c46d2cddf88 100644 --- a/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql +++ b/cpp/ql/test/library-tests/dataflow/additional-flow-to-parameter/withAdditionalFlow.ql @@ -1,21 +1,19 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow -class TestConfig extends DataFlow::Configuration { - TestConfig() { this = "TestConfig" } - - override predicate isSource(DataFlow::Node source) { +module TestConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(FunctionCall call | call.getTarget().getName() = "sink" and sink.asExpr() = call.getAnArgument() ) } - override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { // Send all arguments of function-pointer-calls to a function with a // special name exists(Call call, Function target, int i | @@ -27,6 +25,8 @@ class TestConfig extends DataFlow::Configuration { } } -from DataFlow::Node sink, DataFlow::Node source, TestConfig cfg -where cfg.hasFlow(source, sink) +module TestFlow = DataFlow::Make; + +from DataFlow::Node sink, DataFlow::Node source +where TestFlow::hasFlow(source, sink) select sink, source diff --git a/cpp/ql/test/library-tests/dataflow/crement/from0.ql b/cpp/ql/test/library-tests/dataflow/crement/from0.ql index e5f293a0bcb..90bf8401fba 100644 --- a/cpp/ql/test/library-tests/dataflow/crement/from0.ql +++ b/cpp/ql/test/library-tests/dataflow/crement/from0.ql @@ -1,14 +1,14 @@ import cpp import semmle.code.cpp.ir.dataflow.DataFlow -class Cfg extends DataFlow::Configuration { - Cfg() { this = "from0::Cfg" } +module Cfg implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr().getValue() = "0" } - override predicate isSource(DataFlow::Node source) { source.asExpr().getValue() = "0" } - - override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof VariableAccess } + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof VariableAccess } } -from Cfg cfg, Expr sink -where cfg.hasFlowToExpr(sink) +module Flow = DataFlow::Make; + +from Expr sink +where Flow::hasFlowToExpr(sink) select sink diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/BarrierGuard.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/BarrierGuard.cpp index 34a27db9656..05e45ad52d6 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/BarrierGuard.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/BarrierGuard.cpp @@ -4,7 +4,7 @@ bool guarded(int); void bg_basic(int source) { if (guarded(source)) { - sink(source); // no flow + sink(source); } else { sink(source); // $ ast,ir } @@ -14,13 +14,13 @@ void bg_not(int source) { if (!guarded(source)) { sink(source); // $ ast,ir } else { - sink(source); // no flow + sink(source); } } void bg_and(int source, bool arbitrary) { if (guarded(source) && arbitrary) { - sink(source); // no flow + sink(source); } else { sink(source); // $ ast,ir } @@ -38,7 +38,7 @@ void bg_return(int source) { if (!guarded(source)) { return; } - sink(source); // no flow + sink(source); } struct XY { @@ -56,7 +56,7 @@ void bg_stackstruct(XY s1, XY s2) { } } -void bg_structptr(XY *p1, XY *p2) { +void bg_structptr(XY *p1, XY *p2) { // $ ast-def=p1 ast-def=p2 p1->x = source(); if (guarded(p1->x)) { sink(p1->x); // $ SPURIOUS: ast diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp index 1e9fb56d619..71e752720de 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/clang.cpp @@ -8,7 +8,7 @@ struct twoIntFields { int getFirst() { return m1; } }; -void following_pointers( +void following_pointers( // $ ast-def=sourceStruct1_ptr int sourceArray1[], int cleanArray1[], twoIntFields sourceStruct1, @@ -19,7 +19,7 @@ void following_pointers( sink(sourceArray1[0]); // no flow sink(*sourceArray1); // no flow - sink(&sourceArray1); // $ ast // [should probably be taint only] + sink(&sourceArray1); // $ ast,ir // [should probably be taint only] sink(sourceStruct1.m1); // no flow sink(sourceStruct1_ptr->m1); // no flow @@ -48,5 +48,5 @@ void following_pointers( int stackArray[2] = { source(), source() }; stackArray[0] = source(); - sink(stackArray); // $ ast MISSING: ir + sink(stackArray); // $ ast ir ir=49:25 ir=49:35 ir=50:19 } diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index 23cdbc6779c..0750c1af392 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -1,4 +1,5 @@ uniqueEnclosingCallable +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation missingLocation @@ -85,19 +86,35 @@ postWithInFlow | test.cpp:407:10:407:13 | ref arg & ... | PostUpdateNode should not be the target of local flow. | | test.cpp:407:11:407:13 | tmp [inner post update] | PostUpdateNode should not be the target of local flow. | | test.cpp:423:21:423:25 | local [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:436:19:436:23 | local [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:3:465:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:4:465:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:470:22:470:22 | x [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:499:3:499:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:499:4:499:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:505:35:505:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:511:5:511:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:511:6:511:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:516:5:516:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:516:6:516:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:522:25:522:25 | x [inner post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:526:25:526:25 | y [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:441:19:441:23 | local [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:472:3:472:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:472:4:472:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:477:22:477:22 | x [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:506:3:506:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:506:4:506:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:512:35:512:35 | x [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:519:3:519:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:519:3:519:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:520:3:520:12 | stackArray [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:520:3:520:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:526:3:526:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:526:4:526:4 | e [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:531:40:531:40 | e [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:537:5:537:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:537:6:537:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:542:5:542:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:542:6:542:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:548:25:548:25 | x [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:552:25:552:25 | y [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:562:5:562:13 | globalInt [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:576:5:576:13 | globalInt [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:589:19:589:19 | x [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:596:3:596:4 | xs [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:596:3:596:7 | access to array [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:602:3:602:3 | p [inner post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:602:3:602:7 | access to array [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:608:3:608:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:608:4:608:4 | p [inner post update] | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition uniqueParameterNodePosition diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 57eb909fe2b..aac44e507c1 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -1,22 +1,8 @@ uniqueEnclosingCallable +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation -| BarrierGuard.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| acrossLinkTargets.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| clang.cpp:4:11:4:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| clang.cpp:4:27:4:35 | (unnamed parameter 0) | Node should have one location but has 2. | -| clang.cpp:4:51:4:53 | (unnamed parameter 0) | Node should have one location but has 2. | -| dispatch.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| globals.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| test.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 6. | -| test.cpp:2:27:2:35 | (unnamed parameter 0) | Node should have one location but has 2. | -| test.cpp:2:51:2:53 | (unnamed parameter 0) | Node should have one location but has 2. | missingLocation -| Nodes without location: 4 | uniqueNodeToString missingToString parameterCallable @@ -33,621 +19,14 @@ postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| BarrierGuard.cpp:49:6:49:6 | x [post update] | PostUpdateNode should not be the target of local flow. | -| BarrierGuard.cpp:60:3:60:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| BarrierGuard.cpp:60:7:60:7 | x [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:8:20:8:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:22:8:22:20 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:22:9:22:20 | sourceArray1 [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:26:8:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:26:8:26:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:28:3:28:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:28:22:28:23 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:30:8:30:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:30:8:30:24 | sourceStruct1_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:34:19:34:41 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:39:16:39:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:39:30:39:51 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:39:30:39:51 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:43:26:43:53 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:43:26:43:53 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:49:7:49:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:49:22:49:44 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:49:22:49:44 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:50:3:50:12 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:50:3:50:12 | stackArray [post update] | PostUpdateNode should not be the target of local flow. | -| clang.cpp:50:3:50:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:6:29:6:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:7:29:7:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:9:30:9:45 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:10:30:10:45 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:15:8:15:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:15:8:15:8 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:15:8:15:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:16:30:16:45 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:17:31:17:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:21:8:21:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:21:8:21:8 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:21:8:21:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:22:30:22:45 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:24:31:24:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:29:8:29:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:29:29:29:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:31:8:31:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:31:8:31:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:32:8:32:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:32:8:32:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:33:3:33:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:33:3:33:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:35:8:35:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:35:8:35:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:36:8:36:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:36:8:36:13 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:37:3:37:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:37:3:37:8 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:39:8:39:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:39:8:39:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:39:8:39:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:40:8:40:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:40:8:40:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:40:8:40:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:41:3:41:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:41:3:41:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:41:3:41:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:43:8:43:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:43:8:43:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:43:8:43:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:44:8:44:13 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:44:8:44:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:44:8:44:13 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:45:3:45:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:45:3:45:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:45:3:45:8 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:51:3:51:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:55:8:55:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:55:8:55:19 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:56:8:56:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:56:8:56:19 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:58:8:58:23 | call to readGlobalBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:60:3:60:14 | globalBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:60:18:60:29 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:60:18:60:29 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:60:18:60:29 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:61:3:61:14 | globalMiddle [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:61:18:61:29 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:61:18:61:29 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:61:18:61:29 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:65:3:65:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:65:10:65:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:65:10:65:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:65:10:65:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:69:3:69:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:69:3:69:5 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:73:3:73:5 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:73:3:73:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:73:3:73:5 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:77:21:77:34 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:78:23:78:39 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:78:23:78:39 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:78:24:78:37 | call to allocateBottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:80:8:80:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:81:3:81:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:81:3:81:3 | x [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:85:3:85:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:3:89:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:12:89:17 | (Middle *)... [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:12:89:17 | (Top *)... [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:12:89:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:89:12:89:17 | bottom [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:90:3:90:10 | call to identity [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:90:12:90:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:90:12:90:14 | top [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:100:3:100:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:105:5:105:17 | maybeCallSink [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:113:30:113:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:117:31:117:46 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:127:10:127:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:127:31:127:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:129:10:129:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:129:10:129:15 | topPtr [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:130:10:130:15 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:130:10:130:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:130:10:130:15 | topRef [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:148:3:148:3 | u [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:148:5:148:5 | f [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:168:3:168:4 | u2 [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:168:6:168:6 | u [post update] | PostUpdateNode should not be the target of local flow. | -| dispatch.cpp:168:8:168:8 | f [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:17:19:17:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:17:19:17:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:24:9:24:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:24:20:24:20 | y [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:26:9:26:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:26:18:26:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:26:19:26:24 | coords [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:28:14:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:28:14:28:25 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:28:22:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| example.c:28:23:28:25 | pos [post update] | PostUpdateNode should not be the target of local flow. | -| globals.cpp:5:9:5:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| globals.cpp:9:5:9:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| globals.cpp:13:5:13:19 | flowTestGlobal1 [post update] | PostUpdateNode should not be the target of local flow. | -| globals.cpp:16:12:16:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| globals.cpp:23:5:23:19 | flowTestGlobal2 [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:8:6:8:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:9:6:9:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:10:6:10:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:11:6:11:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:7:13:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:10:17:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:13:11:13:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:16:3:16:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:7:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:10:24:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:20:11:20:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:23:3:23:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:23:3:23:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:23:3:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:7:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:10:31:2 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:28:11:28:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:34:7:34:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:34:13:34:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:40:7:40:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:40:13:40:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:43:3:43:3 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:43:3:43:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:43:3:43:3 | c [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:4:45:4 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:4:45:4 | t [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:7:45:7 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:7:45:7 | u [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:10:45:10 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. | -| lambdas.cpp:45:10:45:10 | w [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:11:5:11:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:11:5:11:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:11:5:11:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:16:12:16:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:16:12:16:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:16:12:16:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:16:12:16:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:20:5:20:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:20:5:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:20:5:20:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:22:7:22:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:22:7:22:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:22:7:22:9 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:24:7:24:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:24:7:24:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:24:7:24:9 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:29:5:29:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:29:5:29:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:29:5:29:7 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:31:7:31:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:31:7:31:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:31:7:31:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:37:21:37:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:37:21:37:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:37:21:37:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:37:21:37:23 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:39:7:39:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:39:7:39:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:39:7:39:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:44:5:44:7 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:44:5:44:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:44:5:44:7 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:46:7:46:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:46:7:46:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:46:7:46:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:48:7:48:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:48:7:48:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:48:7:48:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:55:19:55:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:55:19:55:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:58:15:58:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:58:15:58:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:61:26:61:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:61:26:61:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:64:15:64:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:64:15:64:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:75:5:75:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:75:5:75:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:75:9:75:11 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:79:12:79:14 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:79:12:79:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:79:12:79:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:79:12:79:14 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:83:5:83:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:83:5:83:7 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:83:9:83:11 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:87:7:87:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:87:7:87:9 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:87:11:87:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:89:7:89:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:89:7:89:9 | lhs [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:89:11:89:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:94:5:94:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:94:5:94:7 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:94:9:94:11 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:96:7:96:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:96:7:96:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:96:11:96:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:102:21:102:23 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:102:21:102:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:102:21:102:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:102:21:102:23 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:104:7:104:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:104:7:104:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:104:11:104:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:109:5:109:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:109:5:109:7 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:109:9:109:11 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:113:7:113:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:113:7:113:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:113:11:113:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:115:7:115:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:115:7:115:9 | out [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:115:11:115:13 | val [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:122:19:122:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:122:19:122:20 | x1 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:125:15:125:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:125:15:125:16 | x2 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:128:26:128:27 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:128:26:128:27 | x3 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:131:15:131:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. | -| ref.cpp:131:15:131:16 | x4 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:6:7:6:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:8:3:8:4 | t2 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:12:5:12:6 | t2 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:17:3:17:4 | t1 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:23:12:23:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:23:27:23:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:24:5:24:6 | t1 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:41:9:41:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:41:17:41:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:42:9:42:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:43:10:43:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:43:10:43:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:45:5:45:5 | t [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:45:9:45:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:45:9:45:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:50:9:50:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:50:24:50:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:52:7:52:7 | t [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:54:7:54:7 | t [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:67:14:67:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:68:8:68:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:69:8:69:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:70:14:70:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:77:3:77:4 | u1 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:80:7:80:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:84:8:84:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:85:3:85:4 | i1 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:91:3:91:9 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:91:3:91:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:91:3:91:9 | source1 [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:100:9:100:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:101:10:101:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:102:5:102:5 | t [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:107:9:107:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:108:10:108:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:109:5:109:5 | t [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:115:3:115:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:115:4:115:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:115:4:115:6 | out [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:116:3:116:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:120:3:120:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:120:4:120:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:120:4:120:6 | out [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:121:3:121:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:125:3:125:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:125:4:125:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:125:4:125:6 | out [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:126:3:126:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:134:3:134:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:138:7:138:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:139:7:139:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:145:3:145:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:149:7:149:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:151:7:151:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:156:7:156:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:158:3:158:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:162:7:162:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:164:7:164:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:171:7:171:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:172:3:172:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:176:7:176:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:177:7:177:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:190:5:190:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:194:9:194:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:194:13:194:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:194:13:194:27 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:194:13:194:27 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:195:9:195:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:196:9:196:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:201:9:201:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:203:5:203:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:207:9:207:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:207:13:207:33 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:207:13:207:33 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:207:13:207:33 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:209:9:209:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:209:13:209:33 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:209:13:209:33 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:209:13:209:33 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:214:9:214:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:215:9:215:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:217:5:217:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:221:9:221:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:221:13:221:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:221:13:221:34 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:221:13:221:34 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:223:9:223:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:223:13:223:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:223:13:223:34 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:223:13:223:34 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:230:9:230:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:231:9:231:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:232:5:232:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:236:9:236:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:236:13:236:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:236:13:236:24 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:236:13:236:24 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:237:9:237:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:245:7:245:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:245:7:245:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:245:7:245:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:246:7:246:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:246:7:246:16 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:246:7:246:16 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:250:11:250:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:251:7:251:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:251:7:251:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:251:7:251:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:255:11:255:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:256:7:256:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:256:7:256:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:256:7:256:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:265:11:265:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:265:15:265:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:265:15:265:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:265:15:265:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:267:7:267:7 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:267:11:267:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:267:11:267:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:267:11:267:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:272:11:272:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:273:7:273:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:273:14:273:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:273:14:273:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:273:14:273:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:277:11:277:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:278:7:278:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:278:14:278:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:278:14:278:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:278:14:278:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:282:11:282:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:283:7:283:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:288:13:288:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:288:17:288:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:288:17:288:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:288:17:288:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:290:9:290:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:290:13:290:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:290:13:290:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:290:13:290:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:295:13:295:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:295:17:295:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:295:17:295:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:295:17:295:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:296:9:296:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:300:13:300:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:300:23:300:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:300:23:300:28 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:300:23:300:28 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:301:9:301:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:305:13:305:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:306:9:306:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:314:2:314:2 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:314:2:314:2 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:314:2:314:2 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:317:6:317:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:317:10:317:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:317:10:317:10 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:317:10:317:10 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:319:6:319:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:319:10:319:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:319:10:319:10 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:319:10:319:10 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:321:2:321:2 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:321:2:321:2 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:321:2:321:2 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:324:2:324:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:333:5:333:13 | globalVar [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:347:5:347:13 | globalVar [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:359:5:359:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:359:5:359:9 | field [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:364:5:364:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:364:5:364:14 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:364:5:364:14 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:373:5:373:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:373:5:373:9 | field [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:374:5:374:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:374:5:374:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:383:7:383:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:384:10:384:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:384:10:384:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:384:11:384:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:389:7:389:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:390:8:390:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:391:10:391:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:391:10:391:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:391:11:391:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:400:10:400:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:400:10:400:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:400:11:400:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:406:8:406:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:407:10:407:13 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:407:10:407:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:407:11:407:13 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:417:16:417:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:417:16:417:20 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:423:20:423:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:423:21:423:25 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:429:20:429:24 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:429:20:429:24 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:436:18:436:23 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:436:19:436:23 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:442:18:442:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:442:18:442:22 | local [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:453:7:453:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:456:7:456:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:458:7:458:9 | tmp [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:3:465:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:4:465:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:465:4:465:4 | p [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:469:7:469:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:470:21:470:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:470:22:470:22 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:481:21:481:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:481:21:481:30 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:481:21:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:481:24:481:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:481:24:481:30 | content [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:482:8:482:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:489:7:489:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:491:5:491:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:494:5:494:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:499:3:499:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:499:4:499:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:499:4:499:4 | p [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:504:7:504:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:505:34:505:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:505:35:505:35 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:511:5:511:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:511:6:511:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:511:6:511:6 | p [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:516:5:516:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:516:6:516:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:516:6:516:6 | p [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:522:24:522:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:522:24:522:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:522:25:522:25 | x [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:526:24:526:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:526:24:526:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| test.cpp:526:25:526:25 | y [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:9:7:9:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:10:12:10:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:10:27:10:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:11:5:11:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:17:7:17:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:18:12:18:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:18:35:18:35 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:19:5:19:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:25:7:25:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:26:12:26:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:26:27:26:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:27:5:27:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:33:7:33:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:34:12:34:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:34:27:34:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:37:5:37:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:43:7:43:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:44:12:44:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:44:27:44:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:47:5:47:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:54:7:54:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:55:12:55:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:55:30:55:30 | y [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:55:38:55:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:62:7:62:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:63:12:63:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:63:30:63:30 | y [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:63:38:63:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:64:5:64:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:70:7:70:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:76:12:76:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:76:30:76:30 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:76:38:76:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:83:7:83:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:84:12:84:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:84:20:84:20 | y [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:84:38:84:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:90:7:90:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:91:12:91:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:91:20:91:20 | x [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:91:38:91:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:97:7:97:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:98:7:98:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:101:18:101:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| true_upon_entry.cpp:102:5:102:5 | x [post update] | PostUpdateNode should not be the target of local flow. | +| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:384:10:384:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:391:10:391:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:400:10:400:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| test.cpp:407:10:407:13 | memcpy output argument | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition uniqueParameterNodePosition diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp index f9df8c9497c..ff22b0d12b7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -25,7 +25,7 @@ struct Bottom : Middle { void notSink(int x) override { } }; -void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { +void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef Top *topPtr = bottomPtr, &topRef = bottomRef; sink(topPtr->isSource1()); // $ ir MISSING: ast @@ -65,11 +65,11 @@ Top *allocateBottom() { return new Bottom(); } -void callSinkByPointer(Top *top) { +void callSinkByPointer(Top *top) { // $ ast-def=top top->isSink(source()); // leads to MISSING from ast } -void callSinkByReference(Top &top) { +void callSinkByReference(Top &top) { // $ ast-def=top top.isSink(source()); // leads to MISSING from ast } @@ -81,11 +81,11 @@ void globalVirtualDispatch() { x->isSink(source()); // $ MISSING: ast,ir } -Top *identity(Top *top) { +Top *identity(Top *top) { // $ ast-def=top return top; } -void callIdentityFunctions(Top *top, Bottom *bottom) { +void callIdentityFunctions(Top *top, Bottom *bottom) { // $ ast-def=bottom ast-def=top identity(bottom)->isSink(source()); // $ MISSING: ast,ir identity(top)->isSink(source()); // no flow } @@ -120,7 +120,7 @@ namespace virtual_inheritance { struct Bottom : Middle { }; - void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { + void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { // $ ast-def=bottomPtr ast-def=bottomRef // Because the inheritance from `Top` is virtual, the following casts go // directly from `Bottom` to `Top`, skipping `Middle`. That means we don't // get flow from a `Middle` value to the call qualifier. diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/example.c b/cpp/ql/test/library-tests/dataflow/dataflow-tests/example.c index 40f62783ea9..ad01145cde7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/example.c +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/example.c @@ -12,7 +12,7 @@ typedef struct char isTrue; } MyBool; -void myTest_with_local_flow(MyBool *b, int pos) +void myTest_with_local_flow(MyBool *b, int pos) // $ ast-def=b { MyCoords coords = {0}; diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql new file mode 100644 index 00000000000..bdeeccbc211 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/has-parameter-flow-out.ql @@ -0,0 +1,53 @@ +import TestUtilities.InlineExpectationsTest +import cpp + +module AstTest { + private import semmle.code.cpp.dataflow.DataFlow::DataFlow + private import semmle.code.cpp.dataflow.internal.DataFlowPrivate + + class AstParameterDefTest extends InlineExpectationsTest { + AstParameterDefTest() { this = "AstParameterDefTest" } + + override string getARelevantTag() { result = "ast-def" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(Function f, Parameter p, RefParameterFinalValueNode n | + p.isNamed() and + n.getParameter() = p and + n.getFunction() = f and + location = f.getLocation() and + element = p.toString() and + tag = "ast-def" and + value = p.getName() + ) + } + } +} + +module IRTest { + private import semmle.code.cpp.ir.dataflow.DataFlow + private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil + + private string stars(int k) { + k = [0 .. max(FinalParameterNode n | | n.getIndirectionIndex())] and + (if k = 0 then result = "" else result = "*" + stars(k - 1)) + } + + class IRParameterDefTest extends InlineExpectationsTest { + IRParameterDefTest() { this = "IRParameterDefTest" } + + override string getARelevantTag() { result = "ir-def" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(Function f, Parameter p, FinalParameterNode n | + p.isNamed() and + n.getParameter() = p and + n.getFunction() = f and + location = f.getLocation() and + element = p.toString() and + tag = "ir-def" and + value = stars(n.getIndirectionIndex()) + p.getName() + ) + } + } +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp index f48b50d705b..645c41896c4 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/lambdas.cpp @@ -37,7 +37,7 @@ void test_lambdas() }; d(t, u); - auto e = [](int &a, int &b, int &c) { + auto e = [](int &a, int &b, int &c) { // $ ast-def=a ast-def=b ast-def=c ir-def=*c sink(a); // $ ast,ir sink(b); c = source(); diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected index d57335c1e7b..b62fad5bd9a 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/localFlow.expected @@ -71,10 +71,10 @@ | test.cpp:391:11:391:13 | tmp | test.cpp:391:10:391:13 | & ... | | test.cpp:391:17:391:23 | source1 | test.cpp:391:10:391:13 | ref arg & ... | | test.cpp:391:17:391:23 | source1 | test.cpp:391:16:391:23 | & ... | -| test.cpp:480:67:480:67 | s | test.cpp:480:67:480:67 | s | -| test.cpp:480:67:480:67 | s | test.cpp:481:21:481:21 | s | -| test.cpp:480:67:480:67 | s | test.cpp:482:20:482:20 | s | -| test.cpp:481:21:481:21 | s [post update] | test.cpp:480:67:480:67 | s | -| test.cpp:481:21:481:21 | s [post update] | test.cpp:482:20:482:20 | s | -| test.cpp:481:24:481:30 | ref arg content | test.cpp:482:23:482:29 | content | -| test.cpp:482:23:482:29 | content | test.cpp:483:9:483:17 | p_content | +| test.cpp:487:67:487:67 | s | test.cpp:487:67:487:67 | s | +| test.cpp:487:67:487:67 | s | test.cpp:488:21:488:21 | s | +| test.cpp:487:67:487:67 | s | test.cpp:489:20:489:20 | s | +| test.cpp:488:21:488:21 | s [post update] | test.cpp:487:67:487:67 | s | +| test.cpp:488:21:488:21 | s [post update] | test.cpp:489:20:489:20 | s | +| test.cpp:488:24:488:30 | ref arg content | test.cpp:489:23:489:29 | content | +| test.cpp:489:23:489:29 | content | test.cpp:490:9:490:17 | p_content | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/ref.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/ref.cpp index c0aa967c5f7..1fda792dd26 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/ref.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/ref.cpp @@ -7,16 +7,16 @@ extern int arbitrary; namespace withoutFields { template - void assign(T &lhs, T rhs) { + void assign(T &lhs, T rhs) { // $ ast-def=lhs ir-def=*lhs ast-def=lhs lhs = rhs; } template - void assignWrapper(T &lhs, T rhs) { + void assignWrapper(T &lhs, T rhs) { // $ ast-def=lhs ast-def=lhs assign(lhs, rhs); } - void notAssign(int &lhs, int rhs) { + void notAssign(int &lhs, int rhs) { // $ ast-def=lhs ir-def=*lhs lhs = rhs; if (arbitrary) { lhs = 1; @@ -25,14 +25,14 @@ namespace withoutFields { } } - void sourceToParam(int &out) { + void sourceToParam(int &out) { // $ ast-def=out ir-def=*out out = source(); if (arbitrary) { out = 1; } } - void sourceToParamWrapper(int &out) { + void sourceToParamWrapper(int &out) { // $ ast-def=out ir-def=*out if (arbitrary) { sourceToParam(out); } else { @@ -40,7 +40,7 @@ namespace withoutFields { } } - void notSource(int &out) { + void notSource(int &out) { // $ ast-def=out ir-def=*out out = source(); if (arbitrary) { out = 1; @@ -53,16 +53,16 @@ namespace withoutFields { int x1, x2, x3, x4; assignWrapper(x1, source()); - sink(x1); // $ ast=55:23 ir SPURIOUS: ast=53:9 + sink(x1); // $ ast,ir=55:23 SPURIOUS: ast,ir=53:9 notAssign(x2, source()); - sink(x2); // $ SPURIOUS: ast,ir + sink(x2); // $ SPURIOUS: ast ir sourceToParamWrapper(x3); - sink(x3); // $ ast=29:11 ir SPURIOUS: ast=53:17 + sink(x3); // $ ast,ir=29:11 SPURIOUS: ast,ir=53:17 notSource(x4); - sink(x4); // $ SPURIOUS: ast,ir + sink(x4); // $ SPURIOUS: ast ir } } @@ -71,15 +71,15 @@ namespace withFields { int val; }; - void assign(Int &lhs, int rhs) { + void assign(Int &lhs, int rhs) { // $ ast-def=lhs lhs.val = rhs; } - void assignWrapper(Int &lhs, int rhs) { + void assignWrapper(Int &lhs, int rhs) { // $ ast-def=lhs assign(lhs, rhs); } - void notAssign(Int &lhs, int rhs) { + void notAssign(Int &lhs, int rhs) { // $ ast-def=lhs lhs.val = rhs; // Field flow ignores that the field is subsequently overwritten, leading // to false flow here. @@ -90,14 +90,14 @@ namespace withFields { } } - void sourceToParam(Int &out) { + void sourceToParam(Int &out) { // $ ast-def=out out.val = source(); if (arbitrary) { out.val = 1; } } - void sourceToParamWrapper(Int &out) { + void sourceToParamWrapper(Int &out) { // $ ast-def=out if (arbitrary) { sourceToParam(out); } else { @@ -105,7 +105,7 @@ namespace withFields { } } - void notSource(Int &out) { + void notSource(Int &out) { // $ ast-def=out out.val = source(); // Field flow ignores that the field is subsequently overwritten, leading // to false flow here. diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-number-of-outnodes.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-number-of-outnodes.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-number-of-outnodes.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-number-of-outnodes.ql new file mode 100644 index 00000000000..f5fcd216882 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-number-of-outnodes.ql @@ -0,0 +1,46 @@ +import TestUtilities.InlineExpectationsTest +import cpp + +module AstTest { + private import semmle.code.cpp.dataflow.DataFlow::DataFlow + private import semmle.code.cpp.dataflow.internal.DataFlowPrivate + + class AstMultipleOutNodesTest extends InlineExpectationsTest { + AstMultipleOutNodesTest() { this = "AstMultipleOutNodesTest" } + + override string getARelevantTag() { result = "ast-count(" + any(ReturnKind k).toString() + ")" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlowCall call, int n, ReturnKind kind | + call.getLocation() = location and + n = strictcount(getAnOutNode(call, kind)) and + n > 1 and + element = call.toString() and + tag = "ast-count(" + kind.toString() + ")" and + value = n.toString() + ) + } + } +} + +module IRTest { + private import semmle.code.cpp.ir.dataflow.DataFlow + private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate + + class IRMultipleOutNodesTest extends InlineExpectationsTest { + IRMultipleOutNodesTest() { this = "IRMultipleOutNodesTest" } + + override string getARelevantTag() { result = "ir-count(" + any(ReturnKind k).toString() + ")" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + exists(DataFlowCall call, int n, ReturnKind kind | + call.getLocation() = location and + n = strictcount(getAnOutNode(call, kind)) and + n > 1 and + element = call.toString() and + tag = "ir-count(" + kind.toString() + ")" and + value = n.toString() + ) + } + } +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index dc1f78c1a69..36b78896179 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -63,7 +63,7 @@ namespace std { template T&& move(T& t) noexcept; // simplified signature } -void identityOperations(int* source1) { +void identityOperations(int* source1) { // $ ast-def=source1 const int *x1 = std::move(source1); int* x2 = const_cast(x1); int* x3 = (x2); @@ -71,9 +71,9 @@ void identityOperations(int* source1) { sink(x4); // $ ast,ir } -void trackUninitialized() { // NOTE: uninitialized tracking for IR dataflow is deprecated +void trackUninitialized() { int u1; - sink(u1); // $ ast + sink(u1); // $ ast,ir u1 = 2; sink(u1); // clean @@ -81,15 +81,15 @@ void trackUninitialized() { // NOTE: uninitialized tracking for IR dataflow is d sink(i1); // clean int u2; - sink(i1 ? u2 : 1); // $ ast + sink(i1 ? u2 : 1); // $ ast,ir i1 = u2; - sink(i1); // $ ast + sink(i1); // $ ast,ir } -void local_references(int &source1, int clean1) { +void local_references(int &source1, int clean1) { // $ ast-def=source1 ir-def=*source1 sink(source1); // $ ast,ir source1 = clean1; - sink(source1); // $ SPURIOUS: ir + sink(source1); // clean // The next two test cases show that the analysis does not understand the "&" // on the type at all. It does not understand that the initialization creates @@ -111,17 +111,17 @@ void local_references(int &source1, int clean1) { } } -int alwaysAssignSource(int *out) { +int alwaysAssignSource(int *out) { // $ ast-def=out ir-def=*out *out = source(); return 0; } -int alwaysAssign0(int *out) { +int alwaysAssign0(int *out) { // $ ast-def=out ir-def=*out *out = 0; return 0; } -int alwaysAssignInput(int *out, int in) { +int alwaysAssignInput(int *out, int in) { // $ ast-def=out ir-def=*out *out = in; return 0; } @@ -398,14 +398,14 @@ void flowThroughMemcpy_blockvar_with_local_flow(int source1, int b) { void cleanedByMemcpy_ssa(int clean1) { // currently modeled with BlockVar, not SSA int tmp; memcpy(&tmp, &clean1, sizeof tmp); - sink(tmp); // $ SPURIOUS: ast + sink(tmp); // $ SPURIOUS: ast,ir } void cleanedByMemcpy_blockvar(int clean1) { int tmp; int *capture = &tmp; memcpy(&tmp, &clean1, sizeof tmp); - sink(tmp); // $ SPURIOUS: ast + sink(tmp); // $ SPURIOUS: ast,ir } void intRefSource(int &ref_source); @@ -415,33 +415,40 @@ void intArraySource(int ref_source[], size_t len); void intRefSourceCaller() { int local; intRefSource(local); - sink(local); // $ ast=416:7 ast=417:16 MISSING: ir + sink(local); // $ ast,ir=416:7 ast,ir=417:16 } void intPointerSourceCaller() { int local; intPointerSource(&local); - sink(local); // $ ast=422:7 ast=423:20 MISSING: ir + sink(local); // $ ast,ir=422:7 ast,ir=423:20 } + + + + + void intPointerSourceCaller2() { int local[1]; intPointerSource(local); - sink(local); // $ ast=428:7 ast=429:20 MISSING: ir - sink(*local); // $ ast=428:7 ast=429:20 MISSING: ir + sink(local); // $ ast=434:20 ir SPURIOUS: ast=433:7 + sink(*local); // $ ast=434:20 ir SPURIOUS: ast=433:7 } void intArraySourceCaller() { int local; intArraySource(&local, 1); - sink(local); // $ ast=435:7 ast=436:18 MISSING: ir + sink(local); // $ ast,ir=440:7 ast,ir=441:18 } +// The IR results for this test _are_ equivalent to the AST ones. +// See the comment on `intPointerSourceCaller2` for an explanation. void intArraySourceCaller2() { int local[2]; intArraySource(local, 2); - sink(local); // $ ast=441:7 ast=442:18 MISSING: ir - sink(*local); // $ ast=441:7 ast=442:18 MISSING: ir + sink(local); // $ ast=449:18 ir SPURIOUS: ast=448:7 + sink(*local); // $ ast=449:18 ir SPURIOUS: ast=448:7 } /////////////////////////////////////////////////////////////////////////////// @@ -461,7 +468,7 @@ void throughStmtExpr(int source1, int clean1) { sink(local); // $ ast,ir } -void intOutparamSource(int *p) { +void intOutparamSource(int *p) { // $ ast-def=p ir-def=*p *p = source(); } @@ -477,7 +484,7 @@ struct MyStruct { int* content; }; -void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) { +void local_field_flow_def_by_ref_steps_with_local_flow(MyStruct * s) { // $ ast-def=s writes_to_content(s->content); int* p_content = s->content; sink(*p_content); @@ -495,7 +502,7 @@ void regression_with_phi_flow(int clean1) { } } -int intOutparamSourceMissingReturn(int *p) { +int intOutparamSourceMissingReturn(int *p) { // $ ast-def=p ir-def=*p *p = source(); // return deliberately omitted to test IR dataflow behavior } @@ -506,13 +513,32 @@ void viaOutparamMissingReturn() { sink(x); // $ ast,ir } -void sink_then_source_1(int* p) { - sink(*p); // clean +void uncertain_definition() { + int stackArray[2]; + int clean = 0; + stackArray[0] = source(); + stackArray[1] = clean; + sink(stackArray[0]); // $ ast=519:19 ir SPURIOUS: ast=517:7 +} + +void set_through_const_pointer(int x, const int **e) // $ ast-def=e ir-def=**e ir-def=*e +{ + *e = &x; +} + +void test_set_through_const_pointer(int *e) // $ ast-def=e +{ + set_through_const_pointer(source(), &e); + sink(*e); // $ ir MISSING: ast +} + +void sink_then_source_1(int* p) { // $ ast-def=p ir-def=*p + sink(*p); // $ ir // Flow from the unitialized x to the dereference. *p = source(); } -void sink_then_source_2(int* p, int y) { - sink(y); // $ SPURIOUS: ast +void sink_then_source_2(int* p, int y) { // $ ast-def=p ir-def=*p + sink(y); // $ SPURIOUS: ast ir *p = source(); } @@ -526,3 +552,79 @@ void test_sink_then_source() { sink_then_source_2(&y, y); } } + +int* indirect_source(); + +namespace IndirectFlowThroughGlobals { + int* globalInt; + + void taintGlobal() { + globalInt = indirect_source(); + } + + void f() { + sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17 + taintGlobal(); + sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17 + } + + void calledAfterTaint() { + sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17 + } + + void taintAndCall() { + globalInt = indirect_source(); + calledAfterTaint(); + sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17 + } +} + +void write_to_param(int* x) { // $ ast-def=x + int s = source(); + x = &s; +} + +void test_write_to_param() { + int x = 0; + write_to_param(&x); + sink(x); // $ SPURIOUS: ast +} + +void test_indirect_flow_to_array() { + int* p = indirect_source(); + int* xs[2]; + xs[0] = p; + sink(*xs[0]); // $ ir MISSING: ast // the IR source is the indirection of `indirect_source()`. +} + +void test_def_by_ref_followed_by_uncertain_write_array(int* p) { // $ ast-def=p ir-def=*p + intPointerSource(p); + p[10] = 0; + sink(*p); // $ ir MISSING: ast +} + +void test_def_by_ref_followed_by_uncertain_write_pointer(int* p) { // $ ast-def=p ir-def=*p + intPointerSource(p); + *p = 0; + sink(*p); // $ ir MISSING: ast +} + +void test_flow_through_void_double_pointer(int *p) // $ ast-def=p +{ + intPointerSource(p); + void* q = (void*)&p; + sink(**(int**)q); // $ ir MISSING: ast +} + +void use(int *); + +void test_def_via_phi_read(bool b) +{ + static int buffer[10]; // This is missing an initialisation in IR dataflow + if (b) + { + use(buffer); + } + intPointerSource(buffer); + sink(buffer); // $ ast,ir +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql index 25e88c878bb..8c3e0f53e41 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql @@ -24,6 +24,8 @@ module AstTest { or source.asParameter().getName().matches("source%") or + source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source" + or source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%") or // Track uninitialized variables @@ -67,18 +69,27 @@ module IRTest { override predicate isSource(DataFlow::Node source) { source.asExpr().(FunctionCall).getTarget().getName() = "source" or + source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source" + or source.asParameter().getName().matches("source%") + or + source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%") + or + exists(source.asUninitialized()) } override predicate isSink(DataFlow::Node sink) { exists(FunctionCall call | call.getTarget().getName() = "sink" and - sink.asExpr() = call.getAnArgument() + call.getAnArgument() in [sink.asExpr(), sink.asIndirectExpr()] ) } override predicate isBarrier(DataFlow::Node barrier) { - barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or + exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] | + barrierExpr.(VariableAccess).getTarget().hasName("barrier") + ) + or barrier = DataFlow::InstructionBarrierGuard::getABarrierNode() } } diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected new file mode 100644 index 00000000000..a77f3044647 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected @@ -0,0 +1,3 @@ +failures +astTypeBugs +irTypeBugs diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql new file mode 100644 index 00000000000..5ff9204f305 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.ql @@ -0,0 +1,30 @@ +import TestUtilities.InlineExpectationsTest +import cpp + +module AstTest { + private import semmle.code.cpp.dataflow.internal.DataFlowUtil + + query predicate astTypeBugs(Location location, Node node) { + exists(int n | + n = count(node.getType()) and + location = node.getLocation() and + n != 1 + ) + } +} + +import AstTest + +module IrTest { + private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil + + query predicate irTypeBugs(Location location, Node node) { + exists(int n | + n = count(node.getType()) and + location = node.getLocation() and + n != 1 + ) + } +} + +import IrTest diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected index 6f9f89945d2..0a52d928028 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/uninitialized.expected @@ -26,14 +26,19 @@ | test.cpp:416:7:416:11 | local | test.cpp:418:8:418:12 | local | | test.cpp:422:7:422:11 | local | test.cpp:423:21:423:25 | local | | test.cpp:422:7:422:11 | local | test.cpp:424:8:424:12 | local | -| test.cpp:428:7:428:11 | local | test.cpp:429:20:429:24 | local | -| test.cpp:428:7:428:11 | local | test.cpp:430:8:430:12 | local | -| test.cpp:428:7:428:11 | local | test.cpp:431:9:431:13 | local | -| test.cpp:435:7:435:11 | local | test.cpp:436:19:436:23 | local | -| test.cpp:435:7:435:11 | local | test.cpp:437:8:437:12 | local | -| test.cpp:441:7:441:11 | local | test.cpp:442:18:442:22 | local | -| test.cpp:441:7:441:11 | local | test.cpp:443:8:443:12 | local | -| test.cpp:441:7:441:11 | local | test.cpp:444:9:444:13 | local | -| test.cpp:521:9:521:9 | x | test.cpp:522:25:522:25 | x | -| test.cpp:525:9:525:9 | y | test.cpp:526:25:526:25 | y | -| test.cpp:525:9:525:9 | y | test.cpp:526:28:526:28 | y | +| test.cpp:433:7:433:11 | local | test.cpp:434:20:434:24 | local | +| test.cpp:433:7:433:11 | local | test.cpp:435:8:435:12 | local | +| test.cpp:433:7:433:11 | local | test.cpp:436:9:436:13 | local | +| test.cpp:440:7:440:11 | local | test.cpp:441:19:441:23 | local | +| test.cpp:440:7:440:11 | local | test.cpp:442:8:442:12 | local | +| test.cpp:448:7:448:11 | local | test.cpp:449:18:449:22 | local | +| test.cpp:448:7:448:11 | local | test.cpp:450:8:450:12 | local | +| test.cpp:448:7:448:11 | local | test.cpp:451:9:451:13 | local | +| test.cpp:517:7:517:16 | stackArray | test.cpp:519:3:519:12 | stackArray | +| test.cpp:517:7:517:16 | stackArray | test.cpp:520:3:520:12 | stackArray | +| test.cpp:517:7:517:16 | stackArray | test.cpp:521:8:521:17 | stackArray | +| test.cpp:547:9:547:9 | x | test.cpp:548:25:548:25 | x | +| test.cpp:551:9:551:9 | y | test.cpp:552:25:552:25 | y | +| test.cpp:551:9:551:9 | y | test.cpp:552:28:552:28 | y | +| test.cpp:595:8:595:9 | xs | test.cpp:596:3:596:4 | xs | +| test.cpp:595:8:595:9 | xs | test.cpp:597:9:597:10 | xs | diff --git a/cpp/ql/test/library-tests/dataflow/fields/A.cpp b/cpp/ql/test/library-tests/dataflow/fields/A.cpp index 3c8cfb3551b..a3a151576e5 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/A.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/A.cpp @@ -40,7 +40,7 @@ public: cc.insert(nullptr); ct.insert(new C()); sink(&cc); // no flow - sink(&ct); // $ ast MISSING: ir + sink(&ct); // $ ast ir } void f1() { @@ -53,8 +53,8 @@ public: { B *b = new B(); b->set(new C1()); - sink(b->get()); // $ ast ir=55:12 - sink((new B(new C()))->get()); // $ ast,ir + sink(b->get()); // $ ast ir + sink((new B(new C()))->get()); // $ ast ir } void f3() @@ -63,7 +63,7 @@ public: B *b2; b2 = setOnB(b1, new C2()); sink(b1->c); // no flow - sink(b2->c); // $ ast ir=64:21 + sink(b2->c); // $ ast ir } void f4() @@ -72,7 +72,7 @@ public: B *b2; b2 = setOnBWrap(b1, new C2()); sink(b1->c); // no flow - sink(b2->c); // $ ast ir=73:25 + sink(b2->c); // $ ast ir } B *setOnBWrap(B *b1, C *c) @@ -129,7 +129,7 @@ public: { B *b = new B(); f7(b); - sink(b->c); // $ ast,ir + sink(b->c); // $ ast ir } class D diff --git a/cpp/ql/test/library-tests/dataflow/fields/C.cpp b/cpp/ql/test/library-tests/dataflow/fields/C.cpp index 98121af7055..96bbb25a3b6 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/C.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/C.cpp @@ -28,7 +28,7 @@ public: { sink(s1); // $ast,ir sink(s2); // $ MISSING: ast,ir - sink(s3); // $ast MISSING: ir + sink(s3); // $ast,ir sink(s4); // $ MISSING: ast,ir } }; diff --git a/cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll b/cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll index 652147c328b..dac495f132b 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll +++ b/cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll @@ -18,7 +18,7 @@ class IRConf extends Configuration { override predicate isSink(Node sink) { exists(Call c | c.getTarget().hasName("sink") and - c.getAnArgument() = [sink.asExpr(), sink.asConvertedExpr()] + c.getAnArgument() = [sink.asExpr(), sink.asIndirectExpr(), sink.asConvertedExpr()] ) } diff --git a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp index 16ff8546b15..71bfc62b3ba 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp +++ b/cpp/ql/test/library-tests/dataflow/fields/aliasing.cpp @@ -99,7 +99,7 @@ void addressOfField() { S s_copy = s; int* px = &s_copy.m1; - sink(*px); // $ MISSING: ast,ir + sink(*px); // $ ir MISSING: ast } void taint_a_ptr(int* pa) { @@ -119,22 +119,22 @@ struct S_with_pointer { void pointer_deref(int* xs) { taint_a_ptr(xs); - sink(xs[0]); // $ MISSING: ast,ir + sink(xs[0]); // $ ir MISSING: ast } void pointer_deref_sub(int* xs) { taint_a_ptr(xs - 2); - sink(*(xs - 2)); // $ MISSING: ast,ir + sink(*(xs - 2)); // $ ir MISSING: ast } void pointer_many_addrof_and_deref(int* xs) { taint_a_ptr(xs); - sink(*&*&*xs); // $ MISSING: ast,ir + sink(*&*&*xs); // $ ir MISSING: ast } void pointer_unary_plus(int* xs) { taint_a_ptr(+xs); - sink(*+xs); // $ MISSING: ast,ir + sink(*+xs); // $ ir MISSING: ast } void pointer_member_index(S_with_pointer s) { diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected index e0470aac85d..71936f331b6 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-consistency.expected @@ -5,6 +5,7 @@ uniqueEnclosingCallable | C.cpp:10:20:10:29 | new | Node should have one enclosing callable but has 0. | | C.cpp:35:24:35:33 | 0 | Node should have one enclosing callable but has 0. | | C.cpp:35:24:35:33 | new | Node should have one enclosing callable but has 0. | +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation missingLocation diff --git a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected index dd2d9f54f35..954454ac7c0 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected @@ -1,16 +1,8 @@ uniqueEnclosingCallable +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation -| E.cpp:15:31:15:33 | buf | Node should have one location but has 2. | -| aliasing.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 2. | -| conflated.cpp:2:11:2:13 | (unnamed parameter 0) | Node should have one location but has 2. | -| conflated.cpp:14:22:14:25 | buf | Node should have one location but has 2. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | missingLocation -| Nodes without location: 4 | uniqueNodeToString missingToString parameterCallable @@ -23,1308 +15,28 @@ localCallNodes postIsNotPre postHasUniquePre uniquePostUpdate +| aliasing.cpp:70:11:70:11 | definition of w indirection | Node has multiple PostUpdateNodes. | +| aliasing.cpp:77:11:77:11 | definition of w indirection | Node has multiple PostUpdateNodes. | +| aliasing.cpp:84:11:84:11 | definition of w indirection | Node has multiple PostUpdateNodes. | +| aliasing.cpp:91:11:91:11 | definition of w indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:22:3:22:5 | this indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:25:7:25:7 | this indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:42:10:42:14 | inner indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:43:10:43:14 | inner indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:53:6:53:10 | inner indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:54:6:54:10 | inner indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:55:6:55:10 | inner indirection | Node has multiple PostUpdateNodes. | +| complex.cpp:56:6:56:10 | inner indirection | Node has multiple PostUpdateNodes. | +| struct_init.c:26:16:26:20 | definition of outer indirection | Node has multiple PostUpdateNodes. | +| struct_init.c:41:16:41:20 | definition of outer indirection | Node has multiple PostUpdateNodes. | postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| A.cpp:9:9:9:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:9:9:9:9 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:9:9:9:9 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:14:9:14:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:14:9:14:9 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:14:9:14:9 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:25:7:25:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:25:13:25:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:27:22:27:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:27:28:27:28 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:28:16:28:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:7:31:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:14:31:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:14:31:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:14:31:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:20:31:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:20:31:20 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:31:20:31:20 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:38:7:38:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:38:7:38:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:39:7:39:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:39:7:39:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:40:5:40:6 | cc [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:40:5:40:6 | cc [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:40:15:40:21 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:40:15:40:21 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:5:41:6 | ct [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:5:41:6 | ct [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:15:41:21 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:15:41:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:15:41:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:15:41:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:41:15:41:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:42:10:42:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:42:10:42:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:42:10:42:12 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:42:11:42:12 | cc [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:43:10:43:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:43:10:43:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:43:10:43:12 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:43:11:43:12 | ct [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:47:8:47:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:47:12:47:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:47:12:47:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:47:12:47:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:48:8:48:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:48:20:48:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:48:20:48:20 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:48:20:48:20 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:49:10:49:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:49:10:49:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:49:10:49:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:49:13:49:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:49:13:49:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:54:8:54:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:54:12:54:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:54:12:54:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:54:12:54:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:5:55:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:5:55:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:5:55:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:12:55:19 | (C *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:12:55:19 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:12:55:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:12:55:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:55:12:55:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:10:56:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:10:56:10 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:10:56:10 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:10:56:17 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:10:56:17 | call to get [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:56:13:56:15 | call to get [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:10:57:32 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:10:57:32 | call to get [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:11:57:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:11:57:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:11:57:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:11:57:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:17:57:23 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:17:57:23 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:17:57:23 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:17:57:23 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:57:28:57:30 | call to get [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:62:8:62:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:62:13:62:19 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:62:13:62:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:62:13:62:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:5:64:6 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:10:64:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:10:64:15 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:10:64:15 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:17:64:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:17:64:18 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:17:64:18 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:21:64:28 | (C *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:21:64:28 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:21:64:28 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:21:64:28 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:64:21:64:28 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:65:10:65:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:65:10:65:14 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:65:10:65:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:65:14:65:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:65:14:65:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:66:10:66:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:66:10:66:14 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:66:10:66:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:66:14:66:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:66:14:66:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:71:8:71:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:71:13:71:19 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:71:13:71:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:71:13:71:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:5:73:6 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:10:73:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:10:73:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:10:73:19 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:21:73:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:21:73:22 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:21:73:22 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:25:73:32 | (C *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:25:73:32 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:25:73:32 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:25:73:32 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:73:25:73:32 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:74:10:74:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:74:10:74:14 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:74:10:74:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:74:14:74:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:74:14:74:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:75:10:75:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:75:10:75:14 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:75:10:75:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:75:14:75:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:75:14:75:14 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:5:81:6 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:10:81:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:10:81:15 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:10:81:15 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:17:81:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:17:81:18 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:17:81:18 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:21:81:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:21:81:21 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:81:21:81:21 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:5:82:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:12:82:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:12:82:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:12:82:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:12:82:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:82:12:82:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:87:9:87:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:87:9:87:9 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:87:9:87:9 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:89:10:89:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:89:15:89:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:89:15:89:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:89:15:89:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:7:90:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:7:90:8 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:7:90:8 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:15:90:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:15:90:15 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:90:15:90:15 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:91:7:91:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:93:5:93:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:98:8:98:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:98:12:98:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:98:12:98:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:99:9:99:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:99:14:99:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:99:14:99:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:99:14:99:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:100:5:100:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:100:9:100:9 | a [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:5:101:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:5:101:6 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:5:101:6 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:8:101:9 | (C *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:8:101:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:8:101:9 | c1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:101:8:101:9 | c1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:105:9:105:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:107:12:107:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:107:12:107:16 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:107:12:107:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:107:16:107:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:107:16:107:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:110:9:110:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:112:7:112:8 | cc [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:116:7:116:8 | cc [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:116:12:116:19 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:116:12:116:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:116:12:116:19 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:118:9:118:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:120:12:120:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:120:12:120:16 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:120:12:120:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:120:16:120:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:120:16:120:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:5:126:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:5:126:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:5:126:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:12:126:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:12:126:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:12:126:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:126:12:126:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:130:8:130:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:130:12:130:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:130:12:130:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:130:12:130:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:5:131:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:5:131:6 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:5:131:6 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:8:131:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:8:131:8 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:131:8:131:8 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:132:10:132:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:132:10:132:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:132:10:132:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:132:13:132:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:132:13:132:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:7:142:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:10:142:10 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:14:142:20 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:14:142:20 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:142:14:142:20 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:7:143:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:13:143:13 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:17:143:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:17:143:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:25:143:31 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:25:143:31 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:143:25:143:31 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:150:8:150:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:150:12:150:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:150:12:150:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:150:12:150:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:8:151:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:12:151:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:12:151:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:12:151:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:18:151:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:18:151:18 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:18:151:18 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:21:151:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:21:151:21 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:151:21:151:21 | this [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:152:10:152:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:152:10:152:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:152:10:152:13 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:152:13:152:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:152:13:152:13 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:10:153:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:10:153:16 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:10:153:16 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:13:153:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:16:153:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:153:16:153:16 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:154:10:154:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:154:10:154:13 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:154:10:154:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:154:13:154:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:154:13:154:13 | c [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:159:8:159:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:159:12:159:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:159:12:159:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:159:12:159:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:13:160:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:18:160:60 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:18:160:60 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:18:160:60 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:29:160:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:29:160:29 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:29:160:29 | b [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:32:160:59 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:32:160:59 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:32:160:59 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:32:160:59 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:43:160:49 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:43:160:49 | (B *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:52:160:58 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:160:52:160:58 | (MyList *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:13:161:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:18:161:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:18:161:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:18:161:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:29:161:35 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:29:161:35 | (B *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:38:161:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:38:161:39 | l1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:161:38:161:39 | l1 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:13:162:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:18:162:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:18:162:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:18:162:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:29:162:35 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:29:162:35 | (B *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:38:162:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:38:162:39 | l2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:162:38:162:39 | l2 [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:163:10:163:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:163:10:163:17 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:163:10:163:17 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:163:14:163:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:163:14:163:17 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:10:164:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:10:164:23 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:10:164:23 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:14:164:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:20:164:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:164:20:164:23 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:10:165:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:10:165:29 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:10:165:29 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:14:165:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:20:165:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:26:165:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:165:26:165:29 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:10:166:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:10:166:35 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:10:166:35 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:14:166:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:20:166:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:26:166:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:32:166:35 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:166:32:166:35 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:167:18:167:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:167:40:167:40 | l [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:169:12:169:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:169:12:169:18 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:169:12:169:18 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:169:15:169:18 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:169:15:169:18 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:174:14:174:63 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:183:7:183:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:183:7:183:10 | head [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:184:7:184:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| A.cpp:184:13:184:16 | next [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:6:11:6:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:6:15:6:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:6:15:6:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:11:7:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:16:7:35 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:16:7:35 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:16:7:35 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:25:7:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:25:7:25 | e [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:25:7:25 | e [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:28:7:34 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:7:28:7:34 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:11:8:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:16:8:27 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:16:8:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:16:8:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:25:8:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:25:8:26 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:8:25:8:26 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:10:9:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:10:9:24 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:10:9:24 | elem1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:14:9:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:20:9:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:9:20:9:24 | elem1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:10:10:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:10:10:24 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:10:10:24 | elem2 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:14:10:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:20:10:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:10:20:10:24 | elem2 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:15:11:15:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:15:15:15:27 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:15:15:15:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:11:16:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:16:16:38 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:16:16:38 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:16:16:38 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:28:16:34 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:28:16:34 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:37:16:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:37:16:37 | e [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:16:37:16:37 | e [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:11:17:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:16:17:27 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:16:17:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:16:17:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:25:17:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:25:17:26 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:17:25:17:26 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:10:18:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:10:18:24 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:10:18:24 | elem1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:14:18:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:20:18:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:18:20:18:24 | elem1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:10:19:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:10:19:24 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:10:19:24 | elem2 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:14:19:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:20:19:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:19:20:19:24 | elem2 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:35:7:35:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:35:13:35:17 | elem1 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:36:7:36:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:36:13:36:17 | elem2 [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:46:7:46:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| B.cpp:46:13:46:16 | box1 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:18:8:18:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:18:12:18:18 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:18:12:18:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:18:12:18:18 | new [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:19:5:19:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:19:5:19:5 | c [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:19:5:19:5 | c [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:22:9:22:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:22:12:22:21 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:22:12:22:21 | new [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:5:24:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:11:24:12 | s3 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:16:24:25 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:24:16:24:25 | new [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:29:10:29:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:29:10:29:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:29:10:29:11 | s1 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:29:10:29:11 | s1 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:30:10:30:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:30:10:30:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:30:10:30:11 | s2 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:30:10:30:11 | s2 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:31:10:31:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:31:10:31:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:31:10:31:11 | s3 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:31:10:31:11 | s3 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:32:10:32:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:32:10:32:11 | s4 [post update] | PostUpdateNode should not be the target of local flow. | -| C.cpp:32:10:32:11 | s4 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:9:21:9:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:9:21:9:24 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:10:23:10:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:11:29:11:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:11:29:11:32 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:16:21:16:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:16:21:16:23 | box [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:17:23:17:33 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:18:29:18:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:18:29:18:31 | box [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:10:22:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:10:22:11 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:10:22:11 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:10:22:33 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:10:22:33 | call to getElem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:14:22:20 | call to getBox1 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:14:22:20 | call to getBox1 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:22:25:22:31 | call to getElem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:28:11:28:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:28:15:28:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:28:15:28:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:11:29:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:15:29:41 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:15:29:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:15:29:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:24:29:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:24:29:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:24:29:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:24:29:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:33:29:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:29:33:29:39 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:30:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:30:8:30:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:30:13:30:16 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:31:14:31:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:31:14:31:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:31:14:31:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:35:11:35:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:35:15:35:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:35:15:35:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:11:36:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:15:36:41 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:15:36:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:15:36:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:24:36:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:24:36:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:24:36:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:24:36:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:33:36:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:36:33:36:39 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:5:37:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:8:37:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:8:37:10 | box [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:8:37:10 | box [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:21:37:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:21:37:21 | e [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:37:21:37:21 | e [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:38:14:38:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:38:14:38:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:38:14:38:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:42:11:42:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:42:15:42:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:42:15:42:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:11:43:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:15:43:41 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:15:43:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:15:43:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:24:43:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:24:43:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:24:43:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:24:43:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:33:43:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:43:33:43:39 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:44:5:44:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:44:5:44:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:44:5:44:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:44:19:44:22 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:45:14:45:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:45:14:45:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:45:14:45:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:49:11:49:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:49:15:49:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:49:15:49:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:11:50:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:15:50:41 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:15:50:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:15:50:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:24:50:40 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:24:50:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:24:50:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:24:50:40 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:33:50:39 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:50:33:50:39 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:5:51:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:5:51:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:5:51:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:8:51:14 | call to getBox1 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:8:51:14 | call to getBox1 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:27:51:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:27:51:27 | e [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:51:27:51:27 | e [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:52:14:52:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:52:14:52:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:52:14:52:14 | b [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:56:11:56:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:56:15:56:24 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:56:15:56:24 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:5:57:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:5:57:12 | boxfield [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:16:57:42 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:16:57:42 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:16:57:42 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:25:57:41 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:25:57:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:25:57:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:25:57:41 | new [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:34:57:40 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:57:34:57:40 | (Elem *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:58:5:58:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:58:5:58:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:58:15:58:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:58:20:58:23 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:59:5:59:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:59:5:59:7 | this [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:59:5:59:7 | this [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:10:64:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:10:64:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:10:64:28 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:10:64:28 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:20:64:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:25:64:28 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| D.cpp:64:25:64:28 | elem [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:21:10:21:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:21:18:21:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:21:18:21:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:21:18:21:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:28:21:28:23 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:28:21:28:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:28:21:28:23 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:28:21:28:23 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:29:21:29:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:29:21:29:29 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:29:21:29:29 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:29:24:29:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:29:24:29:29 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:30:21:30:33 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:30:21:30:33 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:30:28:30:33 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:30:28:30:33 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:31:10:31:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:31:10:31:12 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:31:10:31:12 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:32:10:32:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:32:13:32:18 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:32:13:32:18 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:32:13:32:18 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:33:18:33:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:33:18:33:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| E.cpp:33:19:33:19 | p [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:9:3:9:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:9:6:9:7 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:13:3:13:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:13:3:13:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:13:5:13:6 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:17:5:17:6 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:21:9:21:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:21:9:21:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:22:9:22:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:22:9:22:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:23:9:23:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:23:9:23:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:25:17:25:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:25:17:25:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:25:18:25:19 | s1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:26:19:26:20 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:26:19:26:20 | s2 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:26:19:26:20 | s2 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:35:9:35:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:35:9:35:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:36:6:36:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:37:3:37:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:37:3:37:6 | ref1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:37:8:37:9 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:40:9:40:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:40:9:40:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:41:6:41:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:42:6:42:7 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:47:9:47:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:47:9:47:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:48:5:48:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:49:9:49:10 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:52:9:52:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:52:9:52:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:53:5:53:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:54:6:54:7 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:59:9:59:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:59:9:59:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:60:6:60:7 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:61:5:61:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:70:17:70:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:70:17:70:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:71:5:71:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:72:5:72:6 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:77:17:77:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:77:17:77:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:78:6:78:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:79:3:79:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:79:6:79:7 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:84:17:84:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:84:17:84:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:85:6:85:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:86:3:86:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:86:3:86:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:86:5:86:6 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:91:17:91:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:91:17:91:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:92:7:92:8 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:98:5:98:6 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:100:5:100:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:101:8:101:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:106:3:106:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:106:4:106:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:106:4:106:5 | pa [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:111:15:111:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:111:15:111:19 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:111:18:111:19 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:121:15:121:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:121:15:121:16 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:121:15:121:16 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:126:15:126:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:126:15:126:16 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:126:15:126:20 | ... - ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:126:15:126:20 | ... - ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:131:15:131:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:131:15:131:16 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:131:15:131:16 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:136:15:136:17 | + ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:136:15:136:17 | + ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:136:16:136:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:136:16:136:17 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:141:17:141:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:141:17:141:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:141:17:141:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:15:147:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:15:147:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:16:147:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:16:147:16 | s [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:147:21:147:22 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:158:15:158:20 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:158:15:158:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:158:17:158:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:164:15:164:20 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:164:15:164:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:164:17:164:20 | data [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:175:15:175:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:175:15:175:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:175:21:175:22 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:181:15:181:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:181:15:181:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:181:21:181:22 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:187:15:187:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:187:15:187:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:187:21:187:22 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:188:6:188:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:194:15:194:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:194:15:194:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:194:21:194:22 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:195:6:195:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:200:15:200:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:200:15:200:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:200:16:200:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:200:23:200:24 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:205:15:205:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:205:15:205:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:205:16:205:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aliasing.cpp:205:23:205:24 | m1 [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:5:9:5:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:5:18:5:23 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:5:18:5:23 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:6:3:6:5 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:6:3:6:5 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:6:3:6:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:7:8:7:10 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:7:8:7:10 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:7:8:7:13 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:7:8:7:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:7:8:7:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:8:8:8:10 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:8:8:8:10 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:8:8:8:13 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:8:8:8:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:8:8:8:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:9:8:9:11 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:9:8:9:11 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:9:9:9:11 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:9:9:9:11 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:8:10:15 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:8:10:15 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:9:10:15 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:10:10:12 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:10:10:12 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:10:10:10:15 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:14:9:14:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:14:18:14:23 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:14:18:14:23 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:3:15:10 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:4:15:10 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:5:15:7 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:5:15:7 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:15:5:15:10 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:16:8:16:10 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:16:8:16:10 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:16:8:16:13 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:16:8:16:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:16:8:16:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:17:8:17:10 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:17:8:17:10 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:17:8:17:13 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:17:8:17:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:17:8:17:13 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:36:3:36:14 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:36:12:36:14 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:36:19:36:22 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:37:8:37:19 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:37:17:37:19 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:37:24:37:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:37:24:37:27 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:37:24:37:27 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:38:8:38:19 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:38:17:38:19 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:38:24:38:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:38:24:38:27 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:38:24:38:27 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:42:3:42:17 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:42:5:42:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:42:15:42:17 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:42:22:42:25 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:8:43:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:10:43:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:20:43:22 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:27:43:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:27:43:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:43:27:43:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:8:44:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:10:44:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:20:44:22 | arr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:27:44:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:27:44:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:44:27:44:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:48:5:48:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:48:15:48:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:48:15:48:17 | ptr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:48:22:48:25 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:10:49:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:20:49:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:20:49:22 | ptr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:27:49:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:27:49:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:49:27:49:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:10:50:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:20:50:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:20:50:22 | ptr [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:27:50:30 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:27:50:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| arrays.cpp:50:27:50:30 | data [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:12:5:12:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:12:8:12:8 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:16:5:16:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:16:11:16:11 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:5:20:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:5:20:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:5:20:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:23:20:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:23:20:27 | value [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:20:23:20:27 | value [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:19:24:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:19:24:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:19:24:22 | this [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:25:24:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:25:24:29 | value [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:24:25:24:29 | value [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:32:5:32:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:36:5:36:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:40:5:40:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:44:5:44:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:50:3:50:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:50:3:50:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:50:17:50:26 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:50:17:50:26 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:51:10:51:20 | call to getDirectly [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:51:10:51:20 | call to getDirectly [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:56:3:56:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:56:3:56:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:56:19:56:28 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:56:19:56:28 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:57:10:57:22 | call to getIndirectly [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:57:10:57:22 | call to getIndirectly [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:62:3:62:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:62:3:62:3 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:62:25:62:34 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:62:25:62:34 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:63:10:63:28 | call to getThroughNonMember [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:63:10:63:28 | call to getThroughNonMember [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:68:17:68:18 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:68:17:68:18 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:68:18:68:18 | s [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:68:21:68:30 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:68:21:68:30 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:69:8:69:20 | call to nonMemberGetA [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:69:8:69:20 | call to nonMemberGetA [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:84:3:84:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:84:10:84:10 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:88:3:88:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:88:3:88:7 | inner [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:88:9:88:9 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:92:3:92:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:92:4:92:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:92:4:92:5 | pa [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:96:3:96:4 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:96:3:96:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:96:3:96:4 | pa [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:102:21:102:39 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:102:21:102:39 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:102:28:102:39 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:103:27:103:35 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:103:27:103:35 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:103:27:103:35 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:104:15:104:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:104:15:104:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:104:22:104:22 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:106:21:106:41 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:106:21:106:41 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:106:22:106:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:106:30:106:41 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:107:21:107:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:107:29:107:37 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:107:29:107:37 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:107:29:107:37 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:108:15:108:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:108:15:108:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:108:16:108:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:108:24:108:24 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:110:27:110:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:110:27:110:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:110:27:110:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:111:14:111:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:111:25:111:25 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:111:25:111:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:111:25:111:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:112:14:112:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:112:14:112:14 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:112:14:112:14 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:114:8:114:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:114:29:114:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:114:29:114:29 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:114:29:114:29 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:115:8:115:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:115:16:115:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:115:27:115:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:115:27:115:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:115:27:115:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:116:8:116:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:116:16:116:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:116:16:116:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:116:16:116:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:122:21:122:38 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:122:21:122:38 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:122:27:122:38 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:123:21:123:36 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:123:21:123:36 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:123:21:123:36 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:123:28:123:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:123:28:123:36 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:124:15:124:21 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:124:15:124:21 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:124:21:124:21 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:126:21:126:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:126:21:126:40 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:126:21:126:40 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:126:29:126:40 | inner_nested [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:21:127:38 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:21:127:38 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:21:127:38 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:22:127:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:30:127:38 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:127:30:127:38 | inner_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:128:15:128:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:128:15:128:23 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:128:15:128:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:128:23:128:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:130:27:130:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:130:27:130:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:130:27:130:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:131:14:131:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:131:25:131:25 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:131:25:131:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:131:25:131:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:132:14:132:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:132:14:132:14 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:132:14:132:14 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:134:8:134:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:134:29:134:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:134:29:134:29 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:134:29:134:29 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:135:8:135:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:135:16:135:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:135:27:135:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:135:27:135:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:135:27:135:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:136:8:136:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:136:16:136:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:136:16:136:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| by_reference.cpp:136:16:136:16 | a [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:9:13:9:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:10:13:10:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:11:22:11:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:11:22:11:23 | a_ [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:12:22:12:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:12:22:12:23 | b_ [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:14:23:14:27 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:14:30:14:34 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:22:11:22:17 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:22:11:22:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:25:7:25:7 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:25:7:25:7 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:33:3:33:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:42:8:42:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:42:8:42:8 | b [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:42:16:42:16 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:42:16:42:16 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:43:8:43:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:43:8:43:8 | b [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:43:16:43:16 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:43:16:43:16 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:48:9:48:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:48:9:48:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:49:9:49:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:49:9:49:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:50:9:50:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:50:9:50:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:51:9:51:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:51:9:51:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:53:12:53:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:53:12:53:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:54:12:54:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:54:12:54:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:55:12:55:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:55:12:55:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:56:12:56:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:56:12:56:12 | f [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:59:7:59:8 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:59:7:59:8 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:59:7:59:8 | b1 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:62:7:62:8 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:62:7:62:8 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:62:7:62:8 | b2 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:65:7:65:8 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:65:7:65:8 | b3 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:65:7:65:8 | b3 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:68:7:68:8 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:68:7:68:8 | b4 [post update] | PostUpdateNode should not be the target of local flow. | -| complex.cpp:68:7:68:8 | b4 [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:10:3:10:7 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:10:4:10:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:10:4:10:5 | ra [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:10:7:10:7 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:10:7:10:7 | p [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:19:19:19:21 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:19:19:19:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:19:19:19:21 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:19:19:19:21 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:20:8:20:10 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:20:8:20:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:20:8:20:10 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:20:8:20:10 | raw [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:24:3:24:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:28:6:28:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:29:3:29:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:29:7:29:7 | x [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:35:3:35:4 | pa [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:35:8:35:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:35:8:35:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:36:3:36:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:36:7:36:7 | x [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:45:34:45:43 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:52:15:52:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:53:3:53:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:53:7:53:10 | next [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:54:3:54:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:54:7:54:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:54:13:54:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:15:59:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:20:59:39 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:20:59:39 | new [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:20:59:39 | new [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:35:59:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:35:59:38 | next [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:59:35:59:38 | next [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:60:3:60:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:60:7:60:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conflated.cpp:60:13:60:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:5:5:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:18:15:18:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:19:15:19:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:20:24:20:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:20:24:20:25 | a_ [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:21:24:21:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:21:24:21:25 | b_ [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:23:25:23:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:23:32:23:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:28:10:28:10 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:28:10:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:28:10:28:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:28:10:28:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:29:10:29:10 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:29:10:29:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:29:10:29:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:29:10:29:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:34:9:34:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:34:9:34:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:35:9:35:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:35:9:35:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:36:9:36:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:36:9:36:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:37:9:37:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:37:9:37:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:40:9:40:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:40:9:40:9 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:40:9:40:9 | f [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:43:9:43:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:43:9:43:9 | g [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:43:9:43:9 | g [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:46:9:46:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:46:9:46:9 | h [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:46:9:46:9 | h [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:49:9:49:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:49:9:49:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| constructors.cpp:49:9:49:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:9:30:9:33 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:9:36:9:36 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:12:49:12:53 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:12:56:12:56 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:13:51:13:55 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:13:51:13:55 | inner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:13:57:13:57 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:18:25:18:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:22:5:22:9 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:22:5:22:9 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:22:23:22:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:23:16:23:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:23:23:23:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:23:23:23:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:23:23:23:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:5:27:9 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:5:27:9 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:28:27:37 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:27:28:27:37 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:28:16:28:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:28:23:28:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:28:23:28:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:28:23:28:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:17:32:21 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:17:32:21 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:35:32:44 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:32:35:32:44 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:33:16:33:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:33:23:33:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:33:23:33:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:33:23:33:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:19:37:35 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:19:37:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:19:37:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:20:37:24 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:20:37:24 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:26:37:33 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:38:37:47 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:37:38:37:47 | call to user_input [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:38:16:38:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:38:23:38:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:38:23:38:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:38:23:38:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:42:7:42:11 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:42:7:42:11 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:42:13:42:20 | call to getInner [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:42:25:42:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:43:16:43:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:43:23:43:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:43:23:43:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:43:23:43:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:47:6:47:11 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:47:6:47:11 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:47:7:47:11 | outer [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:47:27:47:27 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:48:16:48:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:48:23:48:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:48:23:48:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| qualifiers.cpp:48:23:48:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:24:42:24:56 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:25:11:25:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:26:5:26:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:27:5:27:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:30:9:30:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:31:9:31:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:32:9:32:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:34:9:34:12 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:34:10:34:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:34:10:34:10 | d [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:34:10:34:12 | ... ++ [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:34:17:34:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:36:5:36:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:39:5:39:96 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:42:20:42:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:42:20:42:20 | o [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:42:20:42:20 | o [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:48:14:48:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:48:34:48:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:49:9:49:15 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:49:13:49:15 | bar [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:49:20:49:22 | baz [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:51:9:51:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:53:9:53:15 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:53:13:53:15 | bar [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:53:20:53:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:53:35:53:43 | bufferLen [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:16:54:22 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:16:54:47 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:16:54:47 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:16:54:47 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:20:54:22 | bar [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:27:54:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:54:42:54:47 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:58:13:58:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:60:16:60:18 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:60:16:60:18 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:60:16:60:18 | dst [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:60:16:60:18 | dst [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:14:61:55 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:14:61:55 | bufferLen [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:21:61:27 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:25:61:27 | bar [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:32:61:34 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:47:61:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:61:47:61:55 | bufferLen [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:14:65:52 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:14:65:52 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:21:65:27 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:21:65:52 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:25:65:27 | bar [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:32:65:34 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:65:47:65:52 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:66:14:66:23 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:66:14:66:23 | dst [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:66:21:66:23 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:66:21:66:23 | dst [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:67:9:67:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| realistic.cpp:69:5:69:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:5:5:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:18:15:18:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:19:15:19:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:20:24:20:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:20:24:20:25 | a_ [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:21:24:21:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:21:24:21:25 | b_ [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:23:25:23:29 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:23:32:23:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:28:10:28:10 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:28:10:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:28:10:28:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:28:10:28:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:29:10:29:10 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:29:10:29:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:29:10:29:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:29:10:29:10 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:34:9:34:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:34:9:34:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:35:9:35:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:35:9:35:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:36:9:36:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:36:9:36:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:37:9:37:9 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:37:9:37:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:39:5:39:5 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:39:5:39:5 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:40:5:40:5 | g [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:40:5:40:5 | g [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:41:5:41:5 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:41:5:41:5 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:42:5:42:5 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:42:5:42:5 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:45:9:45:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:45:9:45:9 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:45:9:45:9 | f [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:48:9:48:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:48:9:48:9 | g [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:48:9:48:9 | g [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:51:9:51:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:51:9:51:9 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:51:9:51:9 | h [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:54:9:54:9 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:54:9:54:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:54:9:54:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:65:7:65:7 | i [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:66:7:66:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:79:9:79:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:83:9:83:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:83:12:83:13 | f1 [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:84:14:84:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:84:14:84:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:84:14:84:20 | this [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:92:7:92:7 | i [post update] | PostUpdateNode should not be the target of local flow. | -| simple.cpp:93:15:93:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:15:8:15:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:15:12:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:15:12:15:12 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:15:12:15:12 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:16:8:16:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:16:12:16:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:16:12:16:12 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:16:12:16:12 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:20:17:20:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:20:17:20:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:22:11:22:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:22:11:22:11 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:22:11:22:11 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:23:11:23:11 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:23:11:23:11 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:23:11:23:11 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:24:10:24:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:24:10:24:12 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:24:11:24:12 | ab [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:26:23:29:3 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:27:5:27:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:27:5:27:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:31:23:31:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:31:23:31:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:31:23:31:23 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:32:23:32:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:32:23:32:23 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:32:23:32:23 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:33:14:33:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:33:25:33:25 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:33:25:33:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:33:25:33:25 | a [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:34:14:34:22 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:34:25:34:25 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:34:25:34:25 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:34:25:34:25 | b [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:36:10:36:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:36:10:36:24 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:36:17:36:24 | nestedAB [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:40:17:40:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:40:17:40:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:41:23:44:3 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:42:5:42:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:42:5:42:23 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:46:16:46:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:46:16:46:24 | pointerAB [post update] | PostUpdateNode should not be the target of local flow. | -| struct_init.c:46:16:46:24 | pointerAB [post update] | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. | +| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition uniqueParameterNodePosition diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected index 2b2618a8c87..ec21a37dd3f 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected @@ -1,958 +1,1251 @@ edges -| A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | c [post update] | -| A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | c [post update] | -| A.cpp:28:8:28:10 | this [c] | A.cpp:28:23:28:26 | this [read] [c] | -| A.cpp:28:23:28:26 | this [read] [c] | A.cpp:28:29:28:29 | FieldAddress [read] | -| A.cpp:28:29:28:29 | FieldAddress [read] | A.cpp:28:8:28:10 | ReturnValue | +| A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | ... = ... | +| A.cpp:25:7:25:17 | ... = ... | A.cpp:25:13:25:13 | this indirection [post update] [c] | +| A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | ... = ... | +| A.cpp:27:22:27:32 | ... = ... | A.cpp:27:28:27:28 | this indirection [post update] [c] | +| A.cpp:28:8:28:10 | this indirection [c] | A.cpp:28:23:28:26 | this indirection [c] | +| A.cpp:28:23:28:26 | this indirection [c] | A.cpp:28:29:28:29 | c | +| A.cpp:28:23:28:26 | this indirection [c] | A.cpp:28:29:28:29 | c indirection | +| A.cpp:28:29:28:29 | c | A.cpp:28:8:28:10 | get indirection | +| A.cpp:28:29:28:29 | c indirection | A.cpp:28:8:28:10 | get indirection | | A.cpp:29:23:29:23 | c | A.cpp:31:20:31:20 | c | -| A.cpp:31:14:31:21 | new [post update] [c] | A.cpp:29:15:29:18 | ReturnValue [c] | +| A.cpp:31:14:31:21 | call to B [c] | A.cpp:29:15:29:18 | make indirection [c] | | A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | -| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | new [post update] [c] | +| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] | +| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | +| A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | | A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c | -| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [read] [c] | +| A.cpp:48:12:48:18 | call to make indirection [c] | A.cpp:49:10:49:10 | b indirection [c] | | A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | -| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make [c] | -| A.cpp:49:10:49:10 | b [read] [c] | A.cpp:49:10:49:13 | (void *)... | -| A.cpp:55:5:55:5 | b [post update] [c] | A.cpp:56:10:56:10 | b [c] | -| A.cpp:55:12:55:19 | (C *)... | A.cpp:55:12:55:19 | new | +| A.cpp:48:20:48:20 | c | A.cpp:48:12:48:18 | call to make indirection [c] | +| A.cpp:49:10:49:10 | b indirection [c] | A.cpp:49:10:49:13 | c | +| A.cpp:49:10:49:10 | b indirection [c] | A.cpp:49:13:49:13 | c indirection | +| A.cpp:49:13:49:13 | c indirection | A.cpp:49:10:49:13 | c | +| A.cpp:49:13:49:13 | c indirection | A.cpp:49:13:49:13 | c | +| A.cpp:55:5:55:5 | set output argument [c] | A.cpp:56:10:56:10 | b indirection [c] | | A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | -| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | b [post update] [c] | +| A.cpp:55:12:55:19 | new | A.cpp:55:5:55:5 | set output argument [c] | | A.cpp:55:12:55:19 | new | A.cpp:55:12:55:19 | new | -| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | -| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get | -| A.cpp:56:10:56:10 | b [c] | A.cpp:56:13:56:15 | call to get | -| A.cpp:56:13:56:15 | call to get | A.cpp:56:10:56:17 | (void *)... | -| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | -| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get | -| A.cpp:57:11:57:24 | new [c] | A.cpp:57:28:57:30 | call to get | -| A.cpp:57:11:57:24 | new [post update] [c] | A.cpp:57:11:57:24 | new [c] | +| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:28:8:28:10 | this indirection [c] | +| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:56:10:56:17 | call to get | +| A.cpp:57:11:57:24 | call to B [c] | A.cpp:57:11:57:24 | new indirection [c] | +| A.cpp:57:11:57:24 | new indirection [c] | A.cpp:28:8:28:10 | this indirection [c] | +| A.cpp:57:11:57:24 | new indirection [c] | A.cpp:57:10:57:32 | call to get | | A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | -| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | new [post update] [c] | +| A.cpp:57:17:57:23 | new | A.cpp:57:11:57:24 | call to B [c] | | A.cpp:57:17:57:23 | new | A.cpp:57:17:57:23 | new | -| A.cpp:57:28:57:30 | call to get | A.cpp:57:10:57:32 | (void *)... | -| A.cpp:64:10:64:15 | call to setOnB [c] | A.cpp:66:10:66:11 | b2 [read] [c] | -| A.cpp:64:21:64:28 | (C *)... | A.cpp:64:21:64:28 | new | -| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB [c] | +| A.cpp:64:10:64:15 | call to setOnB indirection [c] | A.cpp:66:10:66:11 | b2 indirection [c] | +| A.cpp:64:21:64:28 | new | A.cpp:64:10:64:15 | call to setOnB indirection [c] | | A.cpp:64:21:64:28 | new | A.cpp:64:21:64:28 | new | | A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | -| A.cpp:66:10:66:11 | b2 [read] [c] | A.cpp:66:10:66:14 | (void *)... | -| A.cpp:73:10:73:19 | call to setOnBWrap [c] | A.cpp:75:10:75:11 | b2 [read] [c] | -| A.cpp:73:25:73:32 | (C *)... | A.cpp:73:25:73:32 | new | -| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap [c] | +| A.cpp:66:10:66:11 | b2 indirection [c] | A.cpp:66:10:66:14 | c | +| A.cpp:66:10:66:11 | b2 indirection [c] | A.cpp:66:14:66:14 | c indirection | +| A.cpp:66:14:66:14 | c indirection | A.cpp:66:10:66:14 | c | +| A.cpp:66:14:66:14 | c indirection | A.cpp:66:14:66:14 | c | +| A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | A.cpp:75:10:75:11 | b2 indirection [c] | +| A.cpp:73:25:73:32 | new | A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | | A.cpp:73:25:73:32 | new | A.cpp:73:25:73:32 | new | | A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | -| A.cpp:75:10:75:11 | b2 [read] [c] | A.cpp:75:10:75:14 | (void *)... | +| A.cpp:75:10:75:11 | b2 indirection [c] | A.cpp:75:10:75:14 | c | +| A.cpp:75:10:75:11 | b2 indirection [c] | A.cpp:75:14:75:14 | c indirection | +| A.cpp:75:14:75:14 | c indirection | A.cpp:75:10:75:14 | c | +| A.cpp:75:14:75:14 | c indirection | A.cpp:75:14:75:14 | c | | A.cpp:78:27:78:27 | c | A.cpp:81:21:81:21 | c | -| A.cpp:81:10:81:15 | call to setOnB [c] | A.cpp:78:6:78:15 | ReturnValue [c] | -| A.cpp:81:21:81:21 | c | A.cpp:81:10:81:15 | call to setOnB [c] | +| A.cpp:81:10:81:15 | call to setOnB indirection [c] | A.cpp:78:6:78:15 | setOnBWrap indirection [c] | +| A.cpp:81:21:81:21 | c | A.cpp:81:10:81:15 | call to setOnB indirection [c] | | A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | | A.cpp:85:26:85:26 | c | A.cpp:90:15:90:15 | c | -| A.cpp:90:7:90:8 | b2 [post update] [c] | A.cpp:85:9:85:14 | ReturnValue [c] | +| A.cpp:90:7:90:8 | set output argument [c] | A.cpp:85:9:85:14 | setOnB indirection [c] | | A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | -| A.cpp:90:15:90:15 | c | A.cpp:90:7:90:8 | b2 [post update] [c] | -| A.cpp:98:12:98:18 | new | A.cpp:100:9:100:9 | a [post update] | -| A.cpp:100:9:100:9 | a [post update] | A.cpp:101:8:101:9 | c1 [a] | -| A.cpp:101:8:101:9 | c1 [a] | A.cpp:103:14:103:14 | c [a] | -| A.cpp:103:14:103:14 | c [a] | A.cpp:107:12:107:13 | c1 [read] [a] | -| A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [read] [a] | -| A.cpp:107:12:107:13 | c1 [read] [a] | A.cpp:107:12:107:16 | (void *)... | -| A.cpp:120:12:120:13 | c1 [read] [a] | A.cpp:120:12:120:16 | (void *)... | -| A.cpp:126:5:126:5 | b [post update] [c] | A.cpp:126:5:126:5 | b [post update] [c] | -| A.cpp:126:5:126:5 | b [post update] [c] | A.cpp:131:8:131:8 | b [post update] [c] | -| A.cpp:126:5:126:5 | b [post update] [c] | A.cpp:131:8:131:8 | b [post update] [c] | +| A.cpp:90:15:90:15 | c | A.cpp:90:7:90:8 | set output argument [c] | +| A.cpp:98:12:98:18 | new | A.cpp:100:5:100:13 | ... = ... | +| A.cpp:100:5:100:13 | ... = ... | A.cpp:100:9:100:9 | c1 indirection [post update] [a] | +| A.cpp:100:9:100:9 | c1 indirection [post update] [a] | A.cpp:101:8:101:9 | c1 indirection [a] | +| A.cpp:101:8:101:9 | c1 indirection [a] | A.cpp:103:14:103:14 | c indirection [a] | +| A.cpp:103:14:103:14 | c indirection [a] | A.cpp:107:12:107:13 | c1 indirection [a] | +| A.cpp:103:14:103:14 | c indirection [a] | A.cpp:120:12:120:13 | c1 indirection [a] | +| A.cpp:107:12:107:13 | c1 indirection [a] | A.cpp:107:12:107:16 | a | +| A.cpp:107:12:107:13 | c1 indirection [a] | A.cpp:107:16:107:16 | a indirection | +| A.cpp:107:16:107:16 | a indirection | A.cpp:107:12:107:16 | a | +| A.cpp:107:16:107:16 | a indirection | A.cpp:107:16:107:16 | a | +| A.cpp:120:12:120:13 | c1 indirection [a] | A.cpp:120:12:120:16 | a | +| A.cpp:120:12:120:13 | c1 indirection [a] | A.cpp:120:16:120:16 | a indirection | +| A.cpp:120:16:120:16 | a indirection | A.cpp:120:12:120:16 | a | +| A.cpp:120:16:120:16 | a indirection | A.cpp:120:16:120:16 | a | +| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] | | A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | -| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | b [post update] [c] | +| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] | | A.cpp:126:12:126:18 | new | A.cpp:126:12:126:18 | new | -| A.cpp:131:8:131:8 | b [post update] [c] | A.cpp:132:10:132:10 | b [read] [c] | -| A.cpp:132:10:132:10 | b [read] [c] | A.cpp:132:10:132:13 | (void *)... | -| A.cpp:140:13:140:13 | b | A.cpp:143:13:143:13 | b [post update] | -| A.cpp:142:10:142:10 | c [post update] | A.cpp:143:13:143:13 | b [post update] [c] | -| A.cpp:142:10:142:10 | c [post update] | A.cpp:151:18:151:18 | b [post update] [c] | -| A.cpp:142:14:142:20 | new | A.cpp:142:10:142:10 | c [post update] | -| A.cpp:143:13:143:13 | b [post update] | A.cpp:151:12:151:24 | new [post update] [b] | -| A.cpp:143:13:143:13 | b [post update] [c] | A.cpp:151:12:151:24 | new [post update] [b, c] | -| A.cpp:143:25:143:31 | new | A.cpp:143:13:143:13 | b [post update] | +| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:10:132:10 | b indirection [c] | +| A.cpp:132:10:132:10 | b indirection [c] | A.cpp:132:10:132:13 | c | +| A.cpp:132:10:132:10 | b indirection [c] | A.cpp:132:13:132:13 | c indirection | +| A.cpp:132:13:132:13 | c indirection | A.cpp:132:10:132:13 | c | +| A.cpp:132:13:132:13 | c indirection | A.cpp:132:13:132:13 | c | +| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... | +| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:10:142:10 | b indirection [post update] [c] | +| A.cpp:142:10:142:10 | b indirection [post update] [c] | A.cpp:143:7:143:31 | ... = ... indirection [c] | +| A.cpp:142:10:142:10 | b indirection [post update] [c] | A.cpp:151:18:151:18 | D output argument [c] | +| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... | +| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:13:143:13 | this indirection [post update] [b] | +| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:13:143:13 | this indirection [post update] [b] | +| A.cpp:143:7:143:31 | ... = ... indirection [c] | A.cpp:143:13:143:13 | this indirection [post update] [b indirection, c] | +| A.cpp:143:13:143:13 | this indirection [post update] [b indirection, c] | A.cpp:151:12:151:24 | call to D [b indirection, c] | +| A.cpp:143:13:143:13 | this indirection [post update] [b] | A.cpp:151:12:151:24 | call to D [b] | +| A.cpp:143:25:143:31 | new | A.cpp:143:7:143:31 | ... = ... | | A.cpp:150:12:150:18 | new | A.cpp:151:18:151:18 | b | -| A.cpp:151:12:151:24 | new [post update] [b, c] | A.cpp:153:10:153:10 | d [read] [b, c] | -| A.cpp:151:12:151:24 | new [post update] [b] | A.cpp:152:10:152:10 | d [read] [b] | +| A.cpp:151:12:151:24 | call to D [b indirection, c] | A.cpp:153:10:153:10 | d indirection [b indirection, c] | +| A.cpp:151:12:151:24 | call to D [b] | A.cpp:152:10:152:10 | d indirection [b] | +| A.cpp:151:18:151:18 | D output argument [c] | A.cpp:154:10:154:10 | b indirection [c] | | A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | -| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | new [post update] [b] | -| A.cpp:151:18:151:18 | b [post update] [c] | A.cpp:154:10:154:10 | b [read] [c] | -| A.cpp:152:10:152:10 | d [read] [b] | A.cpp:152:10:152:13 | (void *)... | -| A.cpp:153:10:153:10 | d [read] [b, c] | A.cpp:153:13:153:13 | b [read] [c] | -| A.cpp:153:13:153:13 | b [read] [c] | A.cpp:153:10:153:16 | (void *)... | -| A.cpp:154:10:154:10 | b [read] [c] | A.cpp:154:10:154:13 | (void *)... | +| A.cpp:151:18:151:18 | b | A.cpp:151:12:151:24 | call to D [b] | +| A.cpp:152:10:152:10 | d indirection [b] | A.cpp:152:10:152:13 | b | +| A.cpp:152:10:152:10 | d indirection [b] | A.cpp:152:13:152:13 | b indirection | +| A.cpp:152:13:152:13 | b indirection | A.cpp:152:10:152:13 | b | +| A.cpp:152:13:152:13 | b indirection | A.cpp:152:13:152:13 | b | +| A.cpp:153:10:153:10 | d indirection [b indirection, c] | A.cpp:153:13:153:13 | b indirection [c] | +| A.cpp:153:10:153:10 | d indirection [b indirection, c] | A.cpp:153:13:153:13 | b indirection [c] | +| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:10:153:16 | c | +| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:13:153:13 | b indirection [c] | +| A.cpp:153:13:153:13 | b indirection [c] | A.cpp:153:16:153:16 | c indirection | +| A.cpp:153:16:153:16 | c indirection | A.cpp:153:10:153:16 | c | +| A.cpp:153:16:153:16 | c indirection | A.cpp:153:16:153:16 | c | +| A.cpp:154:10:154:10 | b indirection [c] | A.cpp:154:10:154:13 | c | +| A.cpp:154:10:154:10 | b indirection [c] | A.cpp:154:13:154:13 | c indirection | +| A.cpp:154:13:154:13 | c indirection | A.cpp:154:10:154:13 | c | +| A.cpp:154:13:154:13 | c indirection | A.cpp:154:13:154:13 | c | | A.cpp:159:12:159:18 | new | A.cpp:160:29:160:29 | b | -| A.cpp:160:18:160:60 | new [post update] [head] | A.cpp:161:38:161:39 | l1 [head] | -| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | new [post update] [head] | +| A.cpp:160:18:160:60 | call to MyList [head] | A.cpp:161:38:161:39 | l1 indirection [head] | +| A.cpp:160:29:160:29 | b | A.cpp:160:18:160:60 | call to MyList [head] | | A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | -| A.cpp:161:18:161:40 | new [post update] [next, head] | A.cpp:162:38:162:39 | l2 [next, head] | -| A.cpp:161:38:161:39 | l1 [head] | A.cpp:161:18:161:40 | new [post update] [next, head] | -| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] | -| A.cpp:162:18:162:40 | new [post update] [next, next, head] | A.cpp:165:10:165:11 | l3 [read] [next, next, head] | -| A.cpp:162:18:162:40 | new [post update] [next, next, head] | A.cpp:167:44:167:44 | l [read] [next, next, head] | -| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:162:18:162:40 | new [post update] [next, next, head] | -| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] | -| A.cpp:165:10:165:11 | l3 [read] [next, next, head] | A.cpp:165:14:165:17 | next [read] [next, head] | -| A.cpp:165:14:165:17 | next [read] [next, head] | A.cpp:165:20:165:23 | next [read] [head] | -| A.cpp:165:20:165:23 | next [read] [head] | A.cpp:165:10:165:29 | (void *)... | -| A.cpp:167:44:167:44 | l [read] [next, head] | A.cpp:167:47:167:50 | FieldAddress [read] [head] | -| A.cpp:167:44:167:44 | l [read] [next, next, head] | A.cpp:167:47:167:50 | FieldAddress [read] [next, head] | -| A.cpp:167:47:167:50 | FieldAddress [read] [head] | A.cpp:169:12:169:12 | l [read] [head] | -| A.cpp:167:47:167:50 | FieldAddress [read] [next, head] | A.cpp:167:44:167:44 | l [read] [next, head] | -| A.cpp:169:12:169:12 | l [read] [head] | A.cpp:169:12:169:18 | (void *)... | -| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | head [post update] | -| A.cpp:181:32:181:35 | next [head] | A.cpp:184:13:184:16 | next [post update] [head] | -| A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:13:184:16 | next [post update] [next, head] | +| A.cpp:161:18:161:40 | call to MyList [next indirection, head] | A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | +| A.cpp:161:38:161:39 | l1 indirection [head] | A.cpp:161:18:161:40 | call to MyList [next indirection, head] | +| A.cpp:161:38:161:39 | l1 indirection [head] | A.cpp:181:32:181:35 | next indirection [head] | +| A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] | A.cpp:165:10:165:11 | l3 indirection [next indirection, next indirection, head] | +| A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] | A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | +| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] | +| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | A.cpp:181:32:181:35 | next indirection [next indirection, head] | +| A.cpp:165:10:165:11 | l3 indirection [next indirection, next indirection, head] | A.cpp:165:14:165:17 | next indirection [next indirection, head] | +| A.cpp:165:10:165:11 | l3 indirection [next indirection, next indirection, head] | A.cpp:165:14:165:17 | next indirection [next indirection, head] | +| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:14:165:17 | next indirection [next indirection, head] | +| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:20:165:23 | next indirection [head] | +| A.cpp:165:14:165:17 | next indirection [next indirection, head] | A.cpp:165:20:165:23 | next indirection [head] | +| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:10:165:29 | head | +| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:20:165:23 | next indirection [head] | +| A.cpp:165:20:165:23 | next indirection [head] | A.cpp:165:26:165:29 | head indirection | +| A.cpp:165:26:165:29 | head indirection | A.cpp:165:10:165:29 | head | +| A.cpp:165:26:165:29 | head indirection | A.cpp:165:26:165:29 | head | +| A.cpp:167:44:167:44 | l indirection [next indirection, head] | A.cpp:167:47:167:50 | next indirection [head] | +| A.cpp:167:44:167:44 | l indirection [next indirection, head] | A.cpp:167:47:167:50 | next indirection [head] | +| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | A.cpp:167:47:167:50 | next indirection [next indirection, head] | +| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | A.cpp:167:47:167:50 | next indirection [next indirection, head] | +| A.cpp:167:47:167:50 | next indirection [head] | A.cpp:169:12:169:12 | l indirection [head] | +| A.cpp:167:47:167:50 | next indirection [head] | A.cpp:169:12:169:12 | l indirection [head] | +| A.cpp:167:47:167:50 | next indirection [next indirection, head] | A.cpp:167:44:167:44 | l indirection [next indirection, head] | +| A.cpp:167:47:167:50 | next indirection [next indirection, head] | A.cpp:167:44:167:44 | l indirection [next indirection, head] | +| A.cpp:169:12:169:12 | l indirection [head] | A.cpp:169:12:169:18 | head | +| A.cpp:169:12:169:12 | l indirection [head] | A.cpp:169:15:169:18 | head indirection | +| A.cpp:169:15:169:18 | head indirection | A.cpp:169:12:169:18 | head | +| A.cpp:169:15:169:18 | head indirection | A.cpp:169:15:169:18 | head | +| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... | +| A.cpp:181:32:181:35 | next indirection [head] | A.cpp:184:7:184:23 | ... = ... indirection [head] | +| A.cpp:181:32:181:35 | next indirection [next indirection, head] | A.cpp:184:7:184:23 | ... = ... indirection [next indirection, head] | +| A.cpp:183:7:183:20 | ... = ... | A.cpp:183:7:183:10 | this indirection [post update] [head] | +| A.cpp:184:7:184:23 | ... = ... indirection [head] | A.cpp:184:13:184:16 | this indirection [post update] [next indirection, head] | +| A.cpp:184:7:184:23 | ... = ... indirection [next indirection, head] | A.cpp:184:13:184:16 | this indirection [post update] [next indirection, next indirection, head] | | B.cpp:6:15:6:24 | new | B.cpp:7:25:7:25 | e | -| B.cpp:7:16:7:35 | new [post update] [elem1] | B.cpp:8:25:8:26 | b1 [elem1] | -| B.cpp:7:25:7:25 | e | B.cpp:7:16:7:35 | new [post update] [elem1] | +| B.cpp:7:16:7:35 | call to Box1 [elem1] | B.cpp:8:25:8:26 | b1 indirection [elem1] | +| B.cpp:7:25:7:25 | e | B.cpp:7:16:7:35 | call to Box1 [elem1] | | B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | -| B.cpp:8:16:8:27 | new [post update] [box1, elem1] | B.cpp:9:10:9:11 | b2 [read] [box1, elem1] | -| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:8:16:8:27 | new [post update] [box1, elem1] | -| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] | -| B.cpp:9:10:9:11 | b2 [read] [box1, elem1] | B.cpp:9:14:9:17 | box1 [read] [elem1] | -| B.cpp:9:14:9:17 | box1 [read] [elem1] | B.cpp:9:10:9:24 | (void *)... | +| B.cpp:8:16:8:27 | call to Box2 [box1 indirection, elem1] | B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | +| B.cpp:8:25:8:26 | b1 indirection [elem1] | B.cpp:8:16:8:27 | call to Box2 [box1 indirection, elem1] | +| B.cpp:8:25:8:26 | b1 indirection [elem1] | B.cpp:44:16:44:17 | b1 indirection [elem1] | +| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] | +| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] | +| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:10:9:24 | elem1 | +| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:14:9:17 | box1 indirection [elem1] | +| B.cpp:9:14:9:17 | box1 indirection [elem1] | B.cpp:9:20:9:24 | elem1 indirection | +| B.cpp:9:20:9:24 | elem1 indirection | B.cpp:9:10:9:24 | elem1 | +| B.cpp:9:20:9:24 | elem1 indirection | B.cpp:9:20:9:24 | elem1 | | B.cpp:15:15:15:27 | new | B.cpp:16:37:16:37 | e | -| B.cpp:16:16:16:38 | new [post update] [elem2] | B.cpp:17:25:17:26 | b1 [elem2] | -| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | new [post update] [elem2] | +| B.cpp:16:16:16:38 | call to Box1 [elem2] | B.cpp:17:25:17:26 | b1 indirection [elem2] | +| B.cpp:16:37:16:37 | e | B.cpp:16:16:16:38 | call to Box1 [elem2] | | B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | -| B.cpp:17:16:17:27 | new [post update] [box1, elem2] | B.cpp:19:10:19:11 | b2 [read] [box1, elem2] | -| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:17:16:17:27 | new [post update] [box1, elem2] | -| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | -| B.cpp:19:10:19:11 | b2 [read] [box1, elem2] | B.cpp:19:14:19:17 | box1 [read] [elem2] | -| B.cpp:19:14:19:17 | box1 [read] [elem2] | B.cpp:19:10:19:24 | (void *)... | -| B.cpp:33:16:33:17 | e1 | B.cpp:35:13:35:17 | elem1 [post update] | -| B.cpp:33:26:33:27 | e2 | B.cpp:36:13:36:17 | elem2 [post update] | -| B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:13:46:16 | box1 [post update] [elem1] | -| B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:13:46:16 | box1 [post update] [elem2] | -| C.cpp:18:12:18:18 | new [post update] [s1] | C.cpp:19:5:19:5 | c [s1] | -| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] | -| C.cpp:22:3:22:3 | this [post update] [s1] | C.cpp:18:12:18:18 | new [post update] [s1] | -| C.cpp:22:9:22:22 | FieldAddress [post update] | C.cpp:22:3:22:3 | this [post update] [s1] | -| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | FieldAddress [post update] | -| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [read] [s1] | -| C.cpp:29:10:29:11 | this [read] [s1] | C.cpp:29:10:29:11 | s1 | -| D.cpp:10:11:10:17 | this [elem] | D.cpp:10:30:10:33 | this [read] [elem] | -| D.cpp:10:30:10:33 | FieldAddress [read] | D.cpp:10:11:10:17 | ReturnValue | -| D.cpp:10:30:10:33 | this [read] [elem] | D.cpp:10:30:10:33 | FieldAddress [read] | -| D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | elem [post update] | -| D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:30:17:32 | this [read] [box, elem] | -| D.cpp:17:30:17:32 | FieldAddress [read] [elem] | D.cpp:17:11:17:17 | ReturnValue [elem] | -| D.cpp:17:30:17:32 | this [read] [box, elem] | D.cpp:17:30:17:32 | FieldAddress [read] [elem] | -| D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] | -| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] | -| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:25:22:31 | call to getElem | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:22:25:22:31 | call to getElem | -| D.cpp:22:25:22:31 | call to getElem | D.cpp:22:10:22:33 | (void *)... | -| D.cpp:28:15:28:24 | new | D.cpp:30:13:30:16 | elem [post update] | -| D.cpp:30:8:30:10 | FieldAddress [post update] [elem] | D.cpp:31:14:31:14 | b [box, elem] | -| D.cpp:30:13:30:16 | elem [post update] | D.cpp:30:8:30:10 | FieldAddress [post update] [elem] | -| D.cpp:31:14:31:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] | +| B.cpp:17:16:17:27 | call to Box2 [box1 indirection, elem2] | B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | +| B.cpp:17:25:17:26 | b1 indirection [elem2] | B.cpp:17:16:17:27 | call to Box2 [box1 indirection, elem2] | +| B.cpp:17:25:17:26 | b1 indirection [elem2] | B.cpp:44:16:44:17 | b1 indirection [elem2] | +| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] | +| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] | +| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:10:19:24 | elem2 | +| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:14:19:17 | box1 indirection [elem2] | +| B.cpp:19:14:19:17 | box1 indirection [elem2] | B.cpp:19:20:19:24 | elem2 indirection | +| B.cpp:19:20:19:24 | elem2 indirection | B.cpp:19:10:19:24 | elem2 | +| B.cpp:19:20:19:24 | elem2 indirection | B.cpp:19:20:19:24 | elem2 | +| B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:22 | ... = ... | +| B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:22 | ... = ... | +| B.cpp:35:7:35:22 | ... = ... | B.cpp:35:13:35:17 | this indirection [post update] [elem1] | +| B.cpp:36:7:36:22 | ... = ... | B.cpp:36:13:36:17 | this indirection [post update] [elem2] | +| B.cpp:44:16:44:17 | b1 indirection [elem1] | B.cpp:46:7:46:21 | ... = ... indirection [elem1] | +| B.cpp:44:16:44:17 | b1 indirection [elem2] | B.cpp:46:7:46:21 | ... = ... indirection [elem2] | +| B.cpp:46:7:46:21 | ... = ... indirection [elem1] | B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem1] | +| B.cpp:46:7:46:21 | ... = ... indirection [elem2] | B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem2] | +| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c indirection [s1] | +| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c indirection [s3] | +| C.cpp:19:5:19:5 | c indirection [s1] | C.cpp:27:8:27:11 | this indirection [s1] | +| C.cpp:19:5:19:5 | c indirection [s3] | C.cpp:27:8:27:11 | this indirection [s3] | +| C.cpp:22:9:22:22 | this indirection [post update] [s1] | C.cpp:18:12:18:18 | call to C [s1] | +| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | this indirection [post update] [s1] | +| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | new | +| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:11:24:12 | this indirection [post update] [s3] | +| C.cpp:24:11:24:12 | this indirection [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] | +| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... | +| C.cpp:27:8:27:11 | this indirection [s1] | C.cpp:29:10:29:11 | this indirection [s1] | +| C.cpp:27:8:27:11 | this indirection [s3] | C.cpp:31:10:31:11 | this indirection [s3] | +| C.cpp:29:10:29:11 | s1 indirection | C.cpp:29:10:29:11 | s1 | +| C.cpp:29:10:29:11 | this indirection [s1] | C.cpp:29:10:29:11 | s1 | +| C.cpp:29:10:29:11 | this indirection [s1] | C.cpp:29:10:29:11 | s1 indirection | +| C.cpp:31:10:31:11 | s3 indirection | C.cpp:31:10:31:11 | s3 | +| C.cpp:31:10:31:11 | this indirection [s3] | C.cpp:31:10:31:11 | s3 | +| C.cpp:31:10:31:11 | this indirection [s3] | C.cpp:31:10:31:11 | s3 indirection | +| D.cpp:10:11:10:17 | this indirection [elem] | D.cpp:10:30:10:33 | this indirection [elem] | +| D.cpp:10:30:10:33 | elem | D.cpp:10:11:10:17 | getElem indirection | +| D.cpp:10:30:10:33 | elem indirection | D.cpp:10:11:10:17 | getElem indirection | +| D.cpp:10:30:10:33 | this indirection [elem] | D.cpp:10:30:10:33 | elem | +| D.cpp:10:30:10:33 | this indirection [elem] | D.cpp:10:30:10:33 | elem indirection | +| D.cpp:11:24:11:24 | e | D.cpp:11:29:11:36 | ... = ... | +| D.cpp:11:29:11:36 | ... = ... | D.cpp:11:29:11:32 | this indirection [post update] [elem] | +| D.cpp:17:11:17:17 | this indirection [box indirection, elem] | D.cpp:17:30:17:32 | this indirection [box indirection, elem] | +| D.cpp:17:30:17:32 | box indirection [elem] | D.cpp:17:11:17:17 | getBox1 indirection [elem] | +| D.cpp:17:30:17:32 | box indirection [elem] | D.cpp:17:11:17:17 | getBox1 indirection [elem] | +| D.cpp:17:30:17:32 | this indirection [box indirection, elem] | D.cpp:17:30:17:32 | box indirection [elem] | +| D.cpp:17:30:17:32 | this indirection [box indirection, elem] | D.cpp:17:30:17:32 | box indirection [elem] | +| D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | D.cpp:22:10:22:11 | b2 indirection [box indirection, elem] | +| D.cpp:22:10:22:11 | b2 indirection [box indirection, elem] | D.cpp:17:11:17:17 | this indirection [box indirection, elem] | +| D.cpp:22:10:22:11 | b2 indirection [box indirection, elem] | D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | +| D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | D.cpp:10:11:10:17 | this indirection [elem] | +| D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | D.cpp:22:10:22:33 | call to getElem | +| D.cpp:28:15:28:24 | new | D.cpp:30:5:30:20 | ... = ... | +| D.cpp:30:5:30:20 | ... = ... | D.cpp:30:13:30:16 | box indirection [post update] [elem] | +| D.cpp:30:8:30:10 | b indirection [post update] [box indirection, elem] | D.cpp:31:14:31:14 | b indirection [box indirection, elem] | +| D.cpp:30:13:30:16 | box indirection [post update] [elem] | D.cpp:30:8:30:10 | b indirection [post update] [box indirection, elem] | +| D.cpp:31:14:31:14 | b indirection [box indirection, elem] | D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | | D.cpp:35:15:35:24 | new | D.cpp:37:21:37:21 | e | -| D.cpp:37:8:37:10 | FieldAddress [post update] [elem] | D.cpp:38:14:38:14 | b [box, elem] | -| D.cpp:37:8:37:10 | box [post update] [elem] | D.cpp:37:8:37:10 | FieldAddress [post update] [elem] | +| D.cpp:37:8:37:10 | b indirection [post update] [box indirection, elem] | D.cpp:38:14:38:14 | b indirection [box indirection, elem] | +| D.cpp:37:8:37:10 | setElem output argument [elem] | D.cpp:37:8:37:10 | b indirection [post update] [box indirection, elem] | | D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | -| D.cpp:37:21:37:21 | e | D.cpp:37:8:37:10 | box [post update] [elem] | -| D.cpp:38:14:38:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] | -| D.cpp:42:15:42:24 | new | D.cpp:44:19:44:22 | elem [post update] | -| D.cpp:44:5:44:5 | b [post update] [box, elem] | D.cpp:45:14:45:14 | b [box, elem] | -| D.cpp:44:19:44:22 | elem [post update] | D.cpp:44:5:44:5 | b [post update] [box, elem] | -| D.cpp:45:14:45:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] | +| D.cpp:37:21:37:21 | e | D.cpp:37:8:37:10 | setElem output argument [elem] | +| D.cpp:38:14:38:14 | b indirection [box indirection, elem] | D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | +| D.cpp:42:15:42:24 | new | D.cpp:44:5:44:26 | ... = ... | +| D.cpp:44:5:44:5 | getBox1 output argument [box indirection, elem] | D.cpp:45:14:45:14 | b indirection [box indirection, elem] | +| D.cpp:44:5:44:26 | ... = ... | D.cpp:44:19:44:22 | call to getBox1 indirection [post update] [elem] | +| D.cpp:44:19:44:22 | call to getBox1 indirection [post update] [elem] | D.cpp:44:5:44:5 | getBox1 output argument [box indirection, elem] | +| D.cpp:45:14:45:14 | b indirection [box indirection, elem] | D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | | D.cpp:49:15:49:24 | new | D.cpp:51:27:51:27 | e | -| D.cpp:51:5:51:5 | b [post update] [box, elem] | D.cpp:52:14:52:14 | b [box, elem] | -| D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | D.cpp:51:5:51:5 | b [post update] [box, elem] | -| D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | +| D.cpp:51:5:51:5 | getBox1 output argument [box indirection, elem] | D.cpp:52:14:52:14 | b indirection [box indirection, elem] | +| D.cpp:51:8:51:14 | setElem output argument [elem] | D.cpp:51:5:51:5 | getBox1 output argument [box indirection, elem] | | D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | -| D.cpp:51:27:51:27 | e | D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | -| D.cpp:52:14:52:14 | b [box, elem] | D.cpp:21:30:21:31 | b2 [box, elem] | -| D.cpp:56:15:56:24 | new | D.cpp:58:20:58:23 | elem [post update] | -| D.cpp:58:5:58:12 | FieldAddress [post update] [box, elem] | D.cpp:59:5:59:7 | this [boxfield, box, elem] | -| D.cpp:58:15:58:17 | FieldAddress [post update] [elem] | D.cpp:58:5:58:12 | FieldAddress [post update] [box, elem] | -| D.cpp:58:20:58:23 | elem [post update] | D.cpp:58:15:58:17 | FieldAddress [post update] [elem] | -| D.cpp:59:5:59:7 | this [boxfield, box, elem] | D.cpp:63:8:63:10 | this [boxfield, box, elem] | -| D.cpp:63:8:63:10 | this [boxfield, box, elem] | D.cpp:64:10:64:17 | this [read] [boxfield, box, elem] | -| D.cpp:64:10:64:17 | boxfield [read] [box, elem] | D.cpp:64:20:64:22 | box [read] [elem] | -| D.cpp:64:10:64:17 | this [read] [boxfield, box, elem] | D.cpp:64:10:64:17 | boxfield [read] [box, elem] | -| D.cpp:64:20:64:22 | box [read] [elem] | D.cpp:64:10:64:28 | (void *)... | -| E.cpp:19:27:19:27 | *p [data, buffer] | E.cpp:21:10:21:10 | p [read] [data, buffer] | -| E.cpp:21:10:21:10 | p [read] [data, buffer] | E.cpp:21:13:21:16 | data [read] [buffer] | -| E.cpp:21:13:21:16 | data [read] [buffer] | E.cpp:21:18:21:23 | buffer | -| E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw | -| E.cpp:29:21:29:29 | argument_source output argument | E.cpp:29:24:29:29 | FieldAddress [post update] | -| E.cpp:29:24:29:29 | FieldAddress [post update] | E.cpp:32:10:32:10 | b [read] [buffer] | -| E.cpp:30:21:30:21 | p [post update] [data, buffer] | E.cpp:33:18:33:19 | & ... indirection [data, buffer] | -| E.cpp:30:21:30:33 | argument_source output argument | E.cpp:30:28:30:33 | FieldAddress [post update] | -| E.cpp:30:23:30:26 | data [post update] [buffer] | E.cpp:30:21:30:21 | p [post update] [data, buffer] | -| E.cpp:30:28:30:33 | FieldAddress [post update] | E.cpp:30:23:30:26 | data [post update] [buffer] | -| E.cpp:32:10:32:10 | b [read] [buffer] | E.cpp:32:13:32:18 | buffer | -| E.cpp:33:18:33:19 | & ... indirection [data, buffer] | E.cpp:19:27:19:27 | *p [data, buffer] | -| aliasing.cpp:9:6:9:7 | m1 [post update] | aliasing.cpp:25:17:25:19 | & ... [post update] [m1] | -| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:6:9:7 | m1 [post update] | -| aliasing.cpp:13:5:13:6 | m1 [post update] | aliasing.cpp:26:19:26:20 | s2 [post update] [m1] | -| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:5:13:6 | m1 [post update] | -| aliasing.cpp:25:17:25:19 | & ... [post update] [m1] | aliasing.cpp:29:8:29:9 | s1 [read] [m1] | -| aliasing.cpp:26:19:26:20 | s2 [post update] [m1] | aliasing.cpp:30:8:30:9 | s2 [read] [m1] | -| aliasing.cpp:29:8:29:9 | s1 [read] [m1] | aliasing.cpp:29:11:29:12 | FieldAddress [read] | -| aliasing.cpp:29:11:29:12 | FieldAddress [read] | aliasing.cpp:29:11:29:12 | m1 | -| aliasing.cpp:30:8:30:9 | s2 [read] [m1] | aliasing.cpp:30:11:30:12 | FieldAddress [read] | -| aliasing.cpp:30:11:30:12 | FieldAddress [read] | aliasing.cpp:30:11:30:12 | m1 | -| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | aliasing.cpp:62:8:62:12 | copy2 [read] [m1] | -| aliasing.cpp:60:6:60:7 | m1 [post update] | aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | -| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:6:60:7 | m1 [post update] | -| aliasing.cpp:62:8:62:12 | copy2 [read] [m1] | aliasing.cpp:62:14:62:15 | FieldAddress [read] | -| aliasing.cpp:62:14:62:15 | FieldAddress [read] | aliasing.cpp:62:14:62:15 | m1 | -| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w [read] [s, m1] | -| aliasing.cpp:92:5:92:5 | s [post update] [m1] | aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | -| aliasing.cpp:92:7:92:8 | m1 [post update] | aliasing.cpp:92:5:92:5 | s [post update] [m1] | -| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:7:92:8 | m1 [post update] | -| aliasing.cpp:93:8:93:8 | w [read] [s, m1] | aliasing.cpp:93:10:93:10 | s [read] [m1] | -| aliasing.cpp:93:10:93:10 | s [read] [m1] | aliasing.cpp:93:12:93:13 | FieldAddress [read] | -| aliasing.cpp:93:12:93:13 | FieldAddress [read] | aliasing.cpp:93:12:93:13 | m1 | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:141:17:141:20 | data [post update] | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:158:15:158:20 | data [post update] | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:164:15:164:20 | data [post update] | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:175:15:175:22 | & ... [post update] | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:187:15:187:22 | & ... [post update] | -| aliasing.cpp:106:3:106:5 | * ... [post update] | aliasing.cpp:200:15:200:24 | & ... [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:3:106:5 | * ... [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:141:17:141:20 | data [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:158:15:158:20 | data [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:164:15:164:20 | data [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:175:15:175:22 | & ... [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:187:15:187:22 | & ... [post update] | -| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:200:15:200:24 | & ... [post update] | -| aliasing.cpp:141:15:141:15 | s [post update] [data] | aliasing.cpp:143:8:143:8 | s [read] [data] | -| aliasing.cpp:141:17:141:20 | FieldAddress [post update] | aliasing.cpp:141:15:141:15 | s [post update] [data] | -| aliasing.cpp:141:17:141:20 | data [post update] | aliasing.cpp:141:17:141:20 | FieldAddress [post update] | -| aliasing.cpp:143:8:143:8 | s [read] [data] | aliasing.cpp:143:8:143:16 | access to array | -| aliasing.cpp:158:15:158:15 | s [post update] [data] | aliasing.cpp:159:9:159:9 | s [read] [data] | -| aliasing.cpp:158:15:158:20 | data [post update] | aliasing.cpp:158:17:158:20 | data [post update] | -| aliasing.cpp:158:17:158:20 | data [post update] | aliasing.cpp:158:15:158:15 | s [post update] [data] | -| aliasing.cpp:159:9:159:9 | s [read] [data] | aliasing.cpp:159:8:159:14 | * ... | -| aliasing.cpp:164:15:164:15 | s [post update] [data] | aliasing.cpp:165:8:165:8 | s [read] [data] | -| aliasing.cpp:164:15:164:20 | data [post update] | aliasing.cpp:164:17:164:20 | data [post update] | -| aliasing.cpp:164:17:164:20 | data [post update] | aliasing.cpp:164:15:164:15 | s [post update] [data] | -| aliasing.cpp:165:8:165:8 | s [read] [data] | aliasing.cpp:165:8:165:16 | access to array | -| aliasing.cpp:175:15:175:22 | & ... [post update] | aliasing.cpp:175:21:175:22 | m1 [post update] | -| aliasing.cpp:175:16:175:17 | s2 [post update] [s, m1] | aliasing.cpp:176:8:176:9 | s2 [read] [s, m1] | -| aliasing.cpp:175:19:175:19 | s [post update] [m1] | aliasing.cpp:175:16:175:17 | s2 [post update] [s, m1] | -| aliasing.cpp:175:21:175:22 | m1 [post update] | aliasing.cpp:175:19:175:19 | s [post update] [m1] | -| aliasing.cpp:176:8:176:9 | s2 [read] [s, m1] | aliasing.cpp:176:11:176:11 | s [read] [m1] | -| aliasing.cpp:176:11:176:11 | s [read] [m1] | aliasing.cpp:176:13:176:14 | FieldAddress [read] | -| aliasing.cpp:176:13:176:14 | FieldAddress [read] | aliasing.cpp:176:13:176:14 | m1 | -| aliasing.cpp:187:15:187:22 | & ... [post update] | aliasing.cpp:187:21:187:22 | m1 [post update] | -| aliasing.cpp:187:16:187:17 | s2 [post update] [s, m1] | aliasing.cpp:189:8:189:11 | s2_2 [read] [s, m1] | -| aliasing.cpp:187:19:187:19 | s [post update] [m1] | aliasing.cpp:187:16:187:17 | s2 [post update] [s, m1] | -| aliasing.cpp:187:21:187:22 | m1 [post update] | aliasing.cpp:187:19:187:19 | s [post update] [m1] | -| aliasing.cpp:189:8:189:11 | s2_2 [read] [s, m1] | aliasing.cpp:189:13:189:13 | s [read] [m1] | -| aliasing.cpp:189:13:189:13 | s [read] [m1] | aliasing.cpp:189:15:189:16 | FieldAddress [read] | -| aliasing.cpp:189:15:189:16 | FieldAddress [read] | aliasing.cpp:189:15:189:16 | m1 | -| aliasing.cpp:200:15:200:24 | & ... [post update] | aliasing.cpp:200:23:200:24 | m1 [post update] | -| aliasing.cpp:200:21:200:21 | s [post update] [m1] | aliasing.cpp:201:8:201:10 | ps2 [read] [s, m1] | -| aliasing.cpp:200:23:200:24 | m1 [post update] | aliasing.cpp:200:21:200:21 | s [post update] [m1] | -| aliasing.cpp:201:8:201:10 | ps2 [read] [s, m1] | aliasing.cpp:201:13:201:13 | s [read] [m1] | -| aliasing.cpp:201:13:201:13 | s [read] [m1] | aliasing.cpp:201:15:201:16 | FieldAddress [read] | -| aliasing.cpp:201:15:201:16 | FieldAddress [read] | aliasing.cpp:201:15:201:16 | m1 | +| D.cpp:51:27:51:27 | e | D.cpp:51:8:51:14 | setElem output argument [elem] | +| D.cpp:52:14:52:14 | b indirection [box indirection, elem] | D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | +| D.cpp:56:15:56:24 | new | D.cpp:58:5:58:27 | ... = ... | +| D.cpp:58:5:58:12 | this indirection [post update] [boxfield indirection, box indirection, elem] | D.cpp:59:5:59:7 | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:58:5:58:27 | ... = ... | D.cpp:58:20:58:23 | box indirection [post update] [elem] | +| D.cpp:58:15:58:17 | boxfield indirection [post update] [box indirection, elem] | D.cpp:58:5:58:12 | this indirection [post update] [boxfield indirection, box indirection, elem] | +| D.cpp:58:20:58:23 | box indirection [post update] [elem] | D.cpp:58:15:58:17 | boxfield indirection [post update] [box indirection, elem] | +| D.cpp:59:5:59:7 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:63:8:63:10 | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:63:8:63:10 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | +| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | D.cpp:64:20:64:22 | box indirection [elem] | +| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | D.cpp:64:20:64:22 | box indirection [elem] | +| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | +| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | +| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:10:64:28 | elem | +| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:20:64:22 | box indirection [elem] | +| D.cpp:64:20:64:22 | box indirection [elem] | D.cpp:64:25:64:28 | elem indirection | +| D.cpp:64:25:64:28 | elem indirection | D.cpp:64:10:64:28 | elem | +| D.cpp:64:25:64:28 | elem indirection | D.cpp:64:25:64:28 | elem | +| E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | +| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | E.cpp:21:13:21:16 | data indirection [buffer indirection] | +| E.cpp:21:13:21:16 | data indirection [buffer indirection] | E.cpp:21:18:21:23 | buffer indirection | +| E.cpp:21:13:21:16 | data indirection [buffer indirection] | E.cpp:21:18:21:23 | buffer indirection | +| E.cpp:21:18:21:23 | buffer indirection | E.cpp:21:18:21:23 | buffer indirection | +| E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection | +| E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection | +| E.cpp:29:21:29:29 | argument_source output argument | E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] | +| E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] | E.cpp:32:10:32:10 | b indirection [buffer indirection] | +| E.cpp:30:21:30:33 | argument_source output argument | E.cpp:30:28:30:33 | data indirection [post update] [buffer indirection] | +| E.cpp:30:23:30:26 | p indirection [post update] [data, buffer indirection] | E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] | +| E.cpp:30:28:30:33 | data indirection [post update] [buffer indirection] | E.cpp:30:23:30:26 | p indirection [post update] [data, buffer indirection] | +| E.cpp:32:10:32:10 | b indirection [buffer indirection] | E.cpp:32:13:32:18 | buffer indirection | +| E.cpp:32:10:32:10 | b indirection [buffer indirection] | E.cpp:32:13:32:18 | buffer indirection | +| E.cpp:32:13:32:18 | buffer indirection | E.cpp:32:13:32:18 | buffer indirection | +| E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] | E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | +| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] | +| aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | +| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... | +| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:5:13:6 | s indirection [post update] [m1] | +| aliasing.cpp:13:5:13:6 | s indirection [post update] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | +| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:29:8:29:9 | s1 indirection [m1] | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | aliasing.cpp:30:8:30:9 | s2 indirection [m1] | +| aliasing.cpp:29:8:29:9 | s1 indirection [m1] | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:29:8:29:9 | s1 indirection [m1] | aliasing.cpp:29:11:29:12 | m1 indirection | +| aliasing.cpp:29:11:29:12 | m1 indirection | aliasing.cpp:29:11:29:12 | m1 | +| aliasing.cpp:30:8:30:9 | s2 indirection [m1] | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:30:8:30:9 | s2 indirection [m1] | aliasing.cpp:30:11:30:12 | m1 indirection | +| aliasing.cpp:30:11:30:12 | m1 indirection | aliasing.cpp:30:11:30:12 | m1 | +| aliasing.cpp:60:3:60:22 | ... = ... | aliasing.cpp:60:6:60:7 | s2 indirection [post update] [m1] | +| aliasing.cpp:60:6:60:7 | s2 indirection [post update] [m1] | aliasing.cpp:62:8:62:12 | copy2 indirection [m1] | +| aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:60:3:60:22 | ... = ... | +| aliasing.cpp:62:8:62:12 | copy2 indirection [m1] | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:62:8:62:12 | copy2 indirection [m1] | aliasing.cpp:62:14:62:15 | m1 indirection | +| aliasing.cpp:62:14:62:15 | m1 indirection | aliasing.cpp:62:14:62:15 | m1 | +| aliasing.cpp:92:3:92:23 | ... = ... | aliasing.cpp:92:7:92:8 | s indirection [post update] [m1] | +| aliasing.cpp:92:5:92:5 | w indirection [post update] [s, m1] | aliasing.cpp:93:8:93:8 | w indirection [s, m1] | +| aliasing.cpp:92:7:92:8 | s indirection [post update] [m1] | aliasing.cpp:92:5:92:5 | w indirection [post update] [s, m1] | +| aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:92:3:92:23 | ... = ... | +| aliasing.cpp:93:8:93:8 | w indirection [s, m1] | aliasing.cpp:93:10:93:10 | s indirection [m1] | +| aliasing.cpp:93:10:93:10 | s indirection [m1] | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:93:10:93:10 | s indirection [m1] | aliasing.cpp:93:12:93:13 | m1 indirection | +| aliasing.cpp:93:12:93:13 | m1 indirection | aliasing.cpp:93:12:93:13 | m1 | +| aliasing.cpp:98:3:98:21 | ... = ... | aliasing.cpp:98:5:98:6 | s indirection [post update] [m1] | +| aliasing.cpp:98:5:98:6 | s indirection [post update] [m1] | aliasing.cpp:101:14:101:19 | s_copy indirection [m1] | +| aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:98:3:98:21 | ... = ... | +| aliasing.cpp:101:13:101:22 | & ... indirection | aliasing.cpp:102:8:102:10 | * ... | +| aliasing.cpp:101:14:101:19 | s_copy indirection [m1] | aliasing.cpp:101:13:101:22 | & ... indirection | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:121:15:121:16 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:126:15:126:20 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:131:15:131:16 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:136:15:136:17 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:141:17:141:20 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:158:15:158:20 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:164:15:164:20 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | +| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | +| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:105:23:105:24 | pa | +| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument | aliasing.cpp:122:8:122:12 | access to array | +| aliasing.cpp:126:15:126:20 | taint_a_ptr output argument | aliasing.cpp:127:8:127:16 | * ... | +| aliasing.cpp:131:15:131:16 | taint_a_ptr output argument | aliasing.cpp:132:8:132:14 | * ... | +| aliasing.cpp:136:15:136:17 | taint_a_ptr output argument | aliasing.cpp:137:8:137:11 | * ... | +| aliasing.cpp:141:17:141:20 | s indirection [post update] [data indirection] | aliasing.cpp:143:8:143:8 | s indirection [data indirection] | +| aliasing.cpp:141:17:141:20 | taint_a_ptr output argument | aliasing.cpp:141:17:141:20 | s indirection [post update] [data indirection] | +| aliasing.cpp:143:8:143:8 | s indirection [data indirection] | aliasing.cpp:143:8:143:16 | access to array | +| aliasing.cpp:143:8:143:8 | s indirection [data indirection] | aliasing.cpp:143:8:143:16 | access to array indirection | +| aliasing.cpp:143:8:143:8 | s indirection [data indirection] | aliasing.cpp:143:10:143:13 | data indirection | +| aliasing.cpp:143:8:143:16 | access to array indirection | aliasing.cpp:143:8:143:16 | access to array | +| aliasing.cpp:143:10:143:13 | data indirection | aliasing.cpp:143:8:143:16 | access to array | +| aliasing.cpp:158:15:158:20 | taint_a_ptr output argument | aliasing.cpp:158:17:158:20 | s indirection [post update] [data] | +| aliasing.cpp:158:17:158:20 | s indirection [post update] [data] | aliasing.cpp:159:9:159:9 | s indirection [data] | +| aliasing.cpp:159:9:159:9 | s indirection [data] | aliasing.cpp:159:8:159:14 | * ... | +| aliasing.cpp:159:9:159:9 | s indirection [data] | aliasing.cpp:159:9:159:14 | data indirection | +| aliasing.cpp:159:9:159:14 | data indirection | aliasing.cpp:159:8:159:14 | * ... | +| aliasing.cpp:164:15:164:20 | taint_a_ptr output argument | aliasing.cpp:164:17:164:20 | s indirection [post update] [data] | +| aliasing.cpp:164:17:164:20 | s indirection [post update] [data] | aliasing.cpp:165:8:165:8 | s indirection [data] | +| aliasing.cpp:165:8:165:8 | s indirection [data] | aliasing.cpp:165:8:165:16 | access to array | +| aliasing.cpp:165:8:165:8 | s indirection [data] | aliasing.cpp:165:8:165:16 | access to array indirection | +| aliasing.cpp:165:8:165:16 | access to array indirection | aliasing.cpp:165:8:165:16 | access to array | +| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | aliasing.cpp:175:21:175:22 | s indirection [post update] [m1] | +| aliasing.cpp:175:19:175:19 | s2 indirection [post update] [s, m1] | aliasing.cpp:176:8:176:9 | s2 indirection [s, m1] | +| aliasing.cpp:175:21:175:22 | s indirection [post update] [m1] | aliasing.cpp:175:19:175:19 | s2 indirection [post update] [s, m1] | +| aliasing.cpp:176:8:176:9 | s2 indirection [s, m1] | aliasing.cpp:176:11:176:11 | s indirection [m1] | +| aliasing.cpp:176:11:176:11 | s indirection [m1] | aliasing.cpp:176:13:176:14 | m1 | +| aliasing.cpp:176:11:176:11 | s indirection [m1] | aliasing.cpp:176:13:176:14 | m1 indirection | +| aliasing.cpp:176:13:176:14 | m1 indirection | aliasing.cpp:176:13:176:14 | m1 | +| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | aliasing.cpp:187:21:187:22 | s indirection [post update] [m1] | +| aliasing.cpp:187:19:187:19 | s2 indirection [post update] [s, m1] | aliasing.cpp:189:8:189:11 | s2_2 indirection [s, m1] | +| aliasing.cpp:187:21:187:22 | s indirection [post update] [m1] | aliasing.cpp:187:19:187:19 | s2 indirection [post update] [s, m1] | +| aliasing.cpp:189:8:189:11 | s2_2 indirection [s, m1] | aliasing.cpp:189:13:189:13 | s indirection [m1] | +| aliasing.cpp:189:13:189:13 | s indirection [m1] | aliasing.cpp:189:15:189:16 | m1 | +| aliasing.cpp:189:13:189:13 | s indirection [m1] | aliasing.cpp:189:15:189:16 | m1 indirection | +| aliasing.cpp:189:15:189:16 | m1 indirection | aliasing.cpp:189:15:189:16 | m1 | +| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | aliasing.cpp:200:23:200:24 | s indirection [post update] [m1] | +| aliasing.cpp:200:21:200:21 | ps2 indirection [post update] [s, m1] | aliasing.cpp:201:8:201:10 | ps2 indirection [s, m1] | +| aliasing.cpp:200:23:200:24 | s indirection [post update] [m1] | aliasing.cpp:200:21:200:21 | ps2 indirection [post update] [s, m1] | +| aliasing.cpp:201:8:201:10 | ps2 indirection [s, m1] | aliasing.cpp:201:13:201:13 | s indirection [m1] | +| aliasing.cpp:201:13:201:13 | s indirection [m1] | aliasing.cpp:201:15:201:16 | m1 | +| aliasing.cpp:201:13:201:13 | s indirection [m1] | aliasing.cpp:201:15:201:16 | m1 indirection | +| aliasing.cpp:201:15:201:16 | m1 indirection | aliasing.cpp:201:15:201:16 | m1 | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:7:8:7:13 | access to array | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:8:8:8:13 | access to array | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:9:8:9:11 | * ... | | arrays.cpp:6:12:6:21 | call to user_input | arrays.cpp:10:8:10:15 | * ... | | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:16:8:16:13 | access to array | | arrays.cpp:15:14:15:23 | call to user_input | arrays.cpp:17:8:17:13 | access to array | -| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | arrays.cpp:37:8:37:8 | o [read] [nested, arr, data] | -| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | arrays.cpp:38:8:38:8 | o [read] [nested, arr, data] | -| arrays.cpp:36:5:36:10 | nested [post update] [arr, data] | arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | -| arrays.cpp:36:12:36:14 | arr [post update] [data] | arrays.cpp:36:5:36:10 | nested [post update] [arr, data] | -| arrays.cpp:36:19:36:22 | data [post update] | arrays.cpp:36:12:36:14 | arr [post update] [data] | -| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:36:19:36:22 | data [post update] | -| arrays.cpp:37:8:37:8 | o [read] [nested, arr, data] | arrays.cpp:37:10:37:15 | nested [read] [arr, data] | -| arrays.cpp:37:8:37:22 | access to array [read] [data] | arrays.cpp:37:24:37:27 | data | -| arrays.cpp:37:10:37:15 | nested [read] [arr, data] | arrays.cpp:37:8:37:22 | access to array [read] [data] | -| arrays.cpp:38:8:38:8 | o [read] [nested, arr, data] | arrays.cpp:38:10:38:15 | nested [read] [arr, data] | -| arrays.cpp:38:8:38:22 | access to array [read] [data] | arrays.cpp:38:24:38:27 | data | -| arrays.cpp:38:10:38:15 | nested [read] [arr, data] | arrays.cpp:38:8:38:22 | access to array [read] [data] | -| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | arrays.cpp:43:8:43:8 | o [read] [indirect, arr, data] | -| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | arrays.cpp:44:8:44:8 | o [read] [indirect, arr, data] | -| arrays.cpp:42:5:42:12 | FieldAddress [post update] [arr, data] | arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | -| arrays.cpp:42:15:42:17 | arr [post update] [data] | arrays.cpp:42:5:42:12 | FieldAddress [post update] [arr, data] | -| arrays.cpp:42:22:42:25 | data [post update] | arrays.cpp:42:15:42:17 | arr [post update] [data] | -| arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:42:22:42:25 | data [post update] | -| arrays.cpp:43:8:43:8 | o [read] [indirect, arr, data] | arrays.cpp:43:10:43:17 | indirect [read] [arr, data] | -| arrays.cpp:43:8:43:25 | access to array [read] [data] | arrays.cpp:43:27:43:30 | data | -| arrays.cpp:43:10:43:17 | indirect [read] [arr, data] | arrays.cpp:43:8:43:25 | access to array [read] [data] | -| arrays.cpp:44:8:44:8 | o [read] [indirect, arr, data] | arrays.cpp:44:10:44:17 | indirect [read] [arr, data] | -| arrays.cpp:44:8:44:25 | access to array [read] [data] | arrays.cpp:44:27:44:30 | data | -| arrays.cpp:44:10:44:17 | indirect [read] [arr, data] | arrays.cpp:44:8:44:25 | access to array [read] [data] | -| arrays.cpp:48:3:48:3 | o [post update] [indirect, ptr, data] | arrays.cpp:49:8:49:8 | o [read] [indirect, ptr, data] | -| arrays.cpp:48:3:48:3 | o [post update] [indirect, ptr, data] | arrays.cpp:50:8:50:8 | o [read] [indirect, ptr, data] | -| arrays.cpp:48:5:48:12 | FieldAddress [post update] [ptr, data] | arrays.cpp:48:3:48:3 | o [post update] [indirect, ptr, data] | -| arrays.cpp:48:15:48:17 | FieldAddress [post update] [data] | arrays.cpp:48:5:48:12 | FieldAddress [post update] [ptr, data] | -| arrays.cpp:48:22:48:25 | data [post update] | arrays.cpp:48:15:48:17 | FieldAddress [post update] [data] | -| arrays.cpp:48:29:48:38 | call to user_input | arrays.cpp:48:22:48:25 | data [post update] | -| arrays.cpp:49:8:49:8 | o [read] [indirect, ptr, data] | arrays.cpp:49:10:49:17 | indirect [read] [ptr, data] | -| arrays.cpp:49:8:49:25 | access to array [read] [data] | arrays.cpp:49:27:49:30 | data | -| arrays.cpp:49:10:49:17 | indirect [read] [ptr, data] | arrays.cpp:49:8:49:25 | access to array [read] [data] | -| arrays.cpp:50:8:50:8 | o [read] [indirect, ptr, data] | arrays.cpp:50:10:50:17 | indirect [read] [ptr, data] | -| arrays.cpp:50:8:50:25 | access to array [read] [data] | arrays.cpp:50:27:50:30 | data | -| arrays.cpp:50:10:50:17 | indirect [read] [ptr, data] | arrays.cpp:50:8:50:25 | access to array [read] [data] | -| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:8:12:8 | a [post update] | -| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | a [post update] | +| arrays.cpp:36:3:36:37 | ... = ... | arrays.cpp:36:19:36:22 | access to array indirection [post update] [data] | +| arrays.cpp:36:5:36:10 | o indirection [post update] [nested, arr, data] | arrays.cpp:37:8:37:8 | o indirection [nested, arr, data] | +| arrays.cpp:36:5:36:10 | o indirection [post update] [nested, arr, data] | arrays.cpp:38:8:38:8 | o indirection [nested, arr, data] | +| arrays.cpp:36:12:36:14 | nested indirection [post update] [arr, data] | arrays.cpp:36:5:36:10 | o indirection [post update] [nested, arr, data] | +| arrays.cpp:36:19:36:22 | access to array indirection [post update] [data] | arrays.cpp:36:12:36:14 | nested indirection [post update] [arr, data] | +| arrays.cpp:36:26:36:35 | call to user_input | arrays.cpp:36:3:36:37 | ... = ... | +| arrays.cpp:37:8:37:8 | o indirection [nested, arr, data] | arrays.cpp:37:10:37:15 | nested indirection [arr, data] | +| arrays.cpp:37:8:37:22 | access to array indirection [data] | arrays.cpp:37:24:37:27 | data | +| arrays.cpp:37:8:37:22 | access to array indirection [data] | arrays.cpp:37:24:37:27 | data indirection | +| arrays.cpp:37:10:37:15 | nested indirection [arr, data] | arrays.cpp:37:8:37:22 | access to array indirection [data] | +| arrays.cpp:37:24:37:27 | data indirection | arrays.cpp:37:24:37:27 | data | +| arrays.cpp:38:8:38:8 | o indirection [nested, arr, data] | arrays.cpp:38:10:38:15 | nested indirection [arr, data] | +| arrays.cpp:38:8:38:22 | access to array indirection [data] | arrays.cpp:38:24:38:27 | data | +| arrays.cpp:38:8:38:22 | access to array indirection [data] | arrays.cpp:38:24:38:27 | data indirection | +| arrays.cpp:38:10:38:15 | nested indirection [arr, data] | arrays.cpp:38:8:38:22 | access to array indirection [data] | +| arrays.cpp:38:24:38:27 | data indirection | arrays.cpp:38:24:38:27 | data | +| arrays.cpp:42:3:42:40 | ... = ... | arrays.cpp:42:22:42:25 | access to array indirection [post update] [data] | +| arrays.cpp:42:5:42:12 | o indirection [post update] [indirect indirection, arr, data] | arrays.cpp:43:8:43:8 | o indirection [indirect indirection, arr, data] | +| arrays.cpp:42:5:42:12 | o indirection [post update] [indirect indirection, arr, data] | arrays.cpp:44:8:44:8 | o indirection [indirect indirection, arr, data] | +| arrays.cpp:42:15:42:17 | indirect indirection [post update] [arr, data] | arrays.cpp:42:5:42:12 | o indirection [post update] [indirect indirection, arr, data] | +| arrays.cpp:42:22:42:25 | access to array indirection [post update] [data] | arrays.cpp:42:15:42:17 | indirect indirection [post update] [arr, data] | +| arrays.cpp:42:29:42:38 | call to user_input | arrays.cpp:42:3:42:40 | ... = ... | +| arrays.cpp:43:8:43:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | +| arrays.cpp:43:8:43:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | +| arrays.cpp:43:8:43:25 | access to array indirection [data] | arrays.cpp:43:27:43:30 | data | +| arrays.cpp:43:8:43:25 | access to array indirection [data] | arrays.cpp:43:27:43:30 | data indirection | +| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | arrays.cpp:43:8:43:25 | access to array indirection [data] | +| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | +| arrays.cpp:43:27:43:30 | data indirection | arrays.cpp:43:27:43:30 | data | +| arrays.cpp:44:8:44:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | +| arrays.cpp:44:8:44:8 | o indirection [indirect indirection, arr, data] | arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | +| arrays.cpp:44:8:44:25 | access to array indirection [data] | arrays.cpp:44:27:44:30 | data | +| arrays.cpp:44:8:44:25 | access to array indirection [data] | arrays.cpp:44:27:44:30 | data indirection | +| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | arrays.cpp:44:8:44:25 | access to array indirection [data] | +| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | +| arrays.cpp:44:27:44:30 | data indirection | arrays.cpp:44:27:44:30 | data | +| arrays.cpp:48:3:48:40 | ... = ... | arrays.cpp:48:22:48:25 | access to array indirection [post update] [data] | +| arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] | +| arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] | +| arrays.cpp:48:15:48:17 | indirect indirection [post update] [ptr indirection, data] | arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | +| arrays.cpp:48:22:48:25 | access to array indirection [post update] [data] | arrays.cpp:48:15:48:17 | indirect indirection [post update] [ptr indirection, data] | +| arrays.cpp:48:29:48:38 | call to user_input | arrays.cpp:48:3:48:40 | ... = ... | +| arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:49:8:49:25 | access to array indirection [data] | arrays.cpp:49:27:49:30 | data | +| arrays.cpp:49:8:49:25 | access to array indirection [data] | arrays.cpp:49:27:49:30 | data indirection | +| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:8:49:25 | access to array indirection [data] | +| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | arrays.cpp:49:20:49:22 | ptr indirection [data] | +| arrays.cpp:49:20:49:22 | ptr indirection [data] | arrays.cpp:49:8:49:25 | access to array indirection [data] | +| arrays.cpp:49:27:49:30 | data indirection | arrays.cpp:49:27:49:30 | data | +| arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] | arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:50:8:50:25 | access to array indirection [data] | arrays.cpp:50:27:50:30 | data | +| arrays.cpp:50:8:50:25 | access to array indirection [data] | arrays.cpp:50:27:50:30 | data indirection | +| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:8:50:25 | access to array indirection [data] | +| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | +| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | arrays.cpp:50:20:50:22 | ptr indirection [data] | +| arrays.cpp:50:20:50:22 | ptr indirection [data] | arrays.cpp:50:8:50:25 | access to array indirection [data] | +| arrays.cpp:50:27:50:30 | data indirection | arrays.cpp:50:27:50:30 | data | +| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... | +| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:8:12:8 | s indirection [post update] [a] | +| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | ... = ... | +| by_reference.cpp:16:5:16:19 | ... = ... | by_reference.cpp:16:11:16:11 | this indirection [post update] [a] | | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:23:20:27 | value | -| by_reference.cpp:20:5:20:8 | this [post update] [a] | by_reference.cpp:20:5:20:8 | this [post update] [a] | | by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | -| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:20:5:20:8 | this [post update] [a] | +| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:25:24:29 | value | -| by_reference.cpp:24:19:24:22 | this [post update] [a] | by_reference.cpp:24:19:24:22 | this [post update] [a] | | by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | -| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:24:19:24:22 | this [post update] [a] | -| by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:32:12:32:12 | s [read] [a] | -| by_reference.cpp:32:12:32:12 | s [read] [a] | by_reference.cpp:32:15:32:15 | FieldAddress [read] | -| by_reference.cpp:32:15:32:15 | FieldAddress [read] | by_reference.cpp:31:16:31:28 | ReturnValue | -| by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:36:12:36:15 | this [read] [a] | -| by_reference.cpp:36:12:36:15 | this [read] [a] | by_reference.cpp:36:18:36:18 | FieldAddress [read] | -| by_reference.cpp:36:18:36:18 | FieldAddress [read] | by_reference.cpp:35:9:35:19 | ReturnValue | -| by_reference.cpp:39:9:39:21 | *#this [a] | by_reference.cpp:40:12:40:15 | this indirection [a] | -| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | +| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | +| by_reference.cpp:31:46:31:46 | s indirection [a] | by_reference.cpp:32:12:32:12 | s indirection [a] | +| by_reference.cpp:32:12:32:12 | s indirection [a] | by_reference.cpp:32:15:32:15 | a | +| by_reference.cpp:32:12:32:12 | s indirection [a] | by_reference.cpp:32:15:32:15 | a indirection | +| by_reference.cpp:32:15:32:15 | a | by_reference.cpp:31:16:31:28 | nonMemberGetA indirection | +| by_reference.cpp:32:15:32:15 | a indirection | by_reference.cpp:31:16:31:28 | nonMemberGetA indirection | +| by_reference.cpp:35:9:35:19 | this indirection [a] | by_reference.cpp:36:12:36:15 | this indirection [a] | +| by_reference.cpp:36:12:36:15 | this indirection [a] | by_reference.cpp:36:18:36:18 | a | +| by_reference.cpp:36:12:36:15 | this indirection [a] | by_reference.cpp:36:18:36:18 | a indirection | +| by_reference.cpp:36:18:36:18 | a | by_reference.cpp:35:9:35:19 | getDirectly indirection | +| by_reference.cpp:36:18:36:18 | a indirection | by_reference.cpp:35:9:35:19 | getDirectly indirection | +| by_reference.cpp:39:9:39:21 | this indirection [a] | by_reference.cpp:40:12:40:15 | this indirection [a] | +| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | this indirection [a] | | by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:40:18:40:28 | call to getDirectly | -| by_reference.cpp:40:18:40:28 | call to getDirectly | by_reference.cpp:39:9:39:21 | ReturnValue | -| by_reference.cpp:43:9:43:27 | *#this [a] | by_reference.cpp:44:26:44:29 | this indirection [a] | -| by_reference.cpp:44:12:44:24 | call to nonMemberGetA | by_reference.cpp:43:9:43:27 | ReturnValue | -| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | +| by_reference.cpp:40:18:40:28 | call to getDirectly | by_reference.cpp:39:9:39:21 | getIndirectly indirection | +| by_reference.cpp:43:9:43:27 | this indirection [a] | by_reference.cpp:44:26:44:29 | this indirection [a] | +| by_reference.cpp:44:12:44:24 | call to nonMemberGetA | by_reference.cpp:43:9:43:27 | getThroughNonMember indirection | +| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | s indirection [a] | | by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | -| by_reference.cpp:50:3:50:3 | s [post update] [a] | by_reference.cpp:51:8:51:8 | s indirection [a] | +| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | by_reference.cpp:51:8:51:8 | s indirection [a] | | by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | -| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | s [post update] [a] | -| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:17:50:26 | call to user_input | -| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | +| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | +| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | this indirection [a] | | by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:51:10:51:20 | call to getDirectly | -| by_reference.cpp:56:3:56:3 | s [post update] [a] | by_reference.cpp:57:8:57:8 | s indirection [a] | +| by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | by_reference.cpp:57:8:57:8 | s indirection [a] | | by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | -| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | s [post update] [a] | -| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:19:56:28 | call to user_input | -| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | *#this [a] | +| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | +| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | this indirection [a] | | by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:57:10:57:22 | call to getIndirectly | -| by_reference.cpp:62:3:62:3 | s [post update] [a] | by_reference.cpp:63:8:63:8 | s indirection [a] | +| by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | by_reference.cpp:63:8:63:8 | s indirection [a] | | by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | -| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | s [post update] [a] | -| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:25:62:34 | call to user_input | -| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | *#this [a] | +| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | +| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | this indirection [a] | | by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | -| by_reference.cpp:68:17:68:18 | & ... [post update] [a] | by_reference.cpp:69:22:69:23 | & ... indirection [a] | +| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | by_reference.cpp:69:22:69:23 | & ... indirection [a] | | by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | -| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | & ... [post update] [a] | -| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:21:68:30 | call to user_input | -| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | +| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | +| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | s indirection [a] | | by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | -| by_reference.cpp:84:10:84:10 | a [post update] | by_reference.cpp:102:21:102:39 | & ... [post update] [a] | -| by_reference.cpp:84:10:84:10 | a [post update] | by_reference.cpp:103:27:103:35 | inner_ptr [post update] [a] | -| by_reference.cpp:84:10:84:10 | a [post update] | by_reference.cpp:106:21:106:41 | & ... [post update] [a] | -| by_reference.cpp:84:10:84:10 | a [post update] | by_reference.cpp:107:29:107:37 | inner_ptr [post update] [a] | -| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:10:84:10 | a [post update] | -| by_reference.cpp:88:9:88:9 | a [post update] | by_reference.cpp:122:21:122:38 | inner_nested [post update] [a] | -| by_reference.cpp:88:9:88:9 | a [post update] | by_reference.cpp:123:21:123:36 | * ... [post update] [a] | -| by_reference.cpp:88:9:88:9 | a [post update] | by_reference.cpp:126:21:126:40 | inner_nested [post update] [a] | -| by_reference.cpp:88:9:88:9 | a [post update] | by_reference.cpp:127:21:127:38 | * ... [post update] [a] | -| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:9:88:9 | a [post update] | -| by_reference.cpp:92:3:92:5 | * ... [post update] | by_reference.cpp:104:15:104:22 | & ... [post update] | -| by_reference.cpp:92:3:92:5 | * ... [post update] | by_reference.cpp:108:15:108:24 | & ... [post update] | -| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:3:92:5 | * ... [post update] | -| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:104:15:104:22 | & ... [post update] | -| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:108:15:108:24 | & ... [post update] | -| by_reference.cpp:96:3:96:4 | (reference dereference) [post update] | by_reference.cpp:124:15:124:21 | a [post update] | -| by_reference.cpp:96:3:96:4 | (reference dereference) [post update] | by_reference.cpp:128:15:128:23 | a [post update] | -| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:96:3:96:4 | (reference dereference) [post update] | -| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:124:15:124:21 | a [post update] | -| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:128:15:128:23 | a [post update] | -| by_reference.cpp:102:21:102:39 | & ... [post update] [a] | by_reference.cpp:102:28:102:39 | inner_nested [post update] [a] | -| by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] | by_reference.cpp:110:8:110:12 | outer [read] [inner_nested, a] | -| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a] | by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] | -| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | by_reference.cpp:111:8:111:12 | outer [read] [inner_ptr, a] | -| by_reference.cpp:103:27:103:35 | FieldAddress [post update] [a] | by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | -| by_reference.cpp:103:27:103:35 | inner_ptr [post update] [a] | by_reference.cpp:103:27:103:35 | FieldAddress [post update] [a] | -| by_reference.cpp:104:15:104:22 | & ... [post update] | by_reference.cpp:104:22:104:22 | a [post update] | -| by_reference.cpp:104:16:104:20 | outer [post update] [a] | by_reference.cpp:112:8:112:12 | outer [read] [a] | -| by_reference.cpp:104:22:104:22 | a [post update] | by_reference.cpp:104:16:104:20 | outer [post update] [a] | -| by_reference.cpp:106:21:106:41 | & ... [post update] [a] | by_reference.cpp:106:30:106:41 | inner_nested [post update] [a] | -| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a] | by_reference.cpp:114:8:114:13 | pouter [read] [inner_nested, a] | -| by_reference.cpp:107:29:107:37 | FieldAddress [post update] [a] | by_reference.cpp:115:8:115:13 | pouter [read] [inner_ptr, a] | -| by_reference.cpp:107:29:107:37 | inner_ptr [post update] [a] | by_reference.cpp:107:29:107:37 | FieldAddress [post update] [a] | -| by_reference.cpp:108:15:108:24 | & ... [post update] | by_reference.cpp:108:24:108:24 | a [post update] | -| by_reference.cpp:108:24:108:24 | a [post update] | by_reference.cpp:116:8:116:13 | pouter [read] [a] | -| by_reference.cpp:110:8:110:12 | outer [read] [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested [read] [a] | -| by_reference.cpp:110:14:110:25 | inner_nested [read] [a] | by_reference.cpp:110:27:110:27 | a | -| by_reference.cpp:111:8:111:12 | outer [read] [inner_ptr, a] | by_reference.cpp:111:14:111:22 | inner_ptr [read] [a] | -| by_reference.cpp:111:14:111:22 | inner_ptr [read] [a] | by_reference.cpp:111:25:111:25 | a | -| by_reference.cpp:112:8:112:12 | outer [read] [a] | by_reference.cpp:112:14:112:14 | a | -| by_reference.cpp:114:8:114:13 | pouter [read] [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested [read] [a] | -| by_reference.cpp:114:16:114:27 | inner_nested [read] [a] | by_reference.cpp:114:29:114:29 | a | -| by_reference.cpp:115:8:115:13 | pouter [read] [inner_ptr, a] | by_reference.cpp:115:16:115:24 | inner_ptr [read] [a] | -| by_reference.cpp:115:16:115:24 | inner_ptr [read] [a] | by_reference.cpp:115:27:115:27 | a | -| by_reference.cpp:116:8:116:13 | pouter [read] [a] | by_reference.cpp:116:16:116:16 | a | -| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | by_reference.cpp:130:8:130:12 | outer [read] [inner_nested, a] | -| by_reference.cpp:122:21:122:38 | inner_nested [post update] [a] | by_reference.cpp:122:27:122:38 | inner_nested [post update] [a] | -| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a] | by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | -| by_reference.cpp:123:21:123:36 | * ... [post update] [a] | by_reference.cpp:123:28:123:36 | FieldAddress [post update] [a] | -| by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] | by_reference.cpp:131:8:131:12 | outer [read] [inner_ptr, a] | -| by_reference.cpp:123:28:123:36 | FieldAddress [post update] [a] | by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] | -| by_reference.cpp:124:15:124:19 | outer [post update] [a] | by_reference.cpp:132:8:132:12 | outer [read] [a] | -| by_reference.cpp:124:15:124:21 | a [post update] | by_reference.cpp:124:21:124:21 | a [post update] | -| by_reference.cpp:124:21:124:21 | a [post update] | by_reference.cpp:124:15:124:19 | outer [post update] [a] | -| by_reference.cpp:126:21:126:40 | inner_nested [post update] [a] | by_reference.cpp:126:29:126:40 | inner_nested [post update] [a] | -| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a] | by_reference.cpp:134:8:134:13 | pouter [read] [inner_nested, a] | -| by_reference.cpp:127:21:127:38 | * ... [post update] [a] | by_reference.cpp:127:30:127:38 | FieldAddress [post update] [a] | -| by_reference.cpp:127:30:127:38 | FieldAddress [post update] [a] | by_reference.cpp:135:8:135:13 | pouter [read] [inner_ptr, a] | -| by_reference.cpp:128:15:128:23 | a [post update] | by_reference.cpp:128:23:128:23 | a [post update] | -| by_reference.cpp:128:23:128:23 | a [post update] | by_reference.cpp:136:8:136:13 | pouter [read] [a] | -| by_reference.cpp:130:8:130:12 | outer [read] [inner_nested, a] | by_reference.cpp:130:14:130:25 | inner_nested [read] [a] | -| by_reference.cpp:130:14:130:25 | inner_nested [read] [a] | by_reference.cpp:130:27:130:27 | a | -| by_reference.cpp:131:8:131:12 | outer [read] [inner_ptr, a] | by_reference.cpp:131:14:131:22 | inner_ptr [read] [a] | -| by_reference.cpp:131:14:131:22 | inner_ptr [read] [a] | by_reference.cpp:131:25:131:25 | a | -| by_reference.cpp:132:8:132:12 | outer [read] [a] | by_reference.cpp:132:14:132:14 | a | -| by_reference.cpp:134:8:134:13 | pouter [read] [inner_nested, a] | by_reference.cpp:134:16:134:27 | inner_nested [read] [a] | -| by_reference.cpp:134:16:134:27 | inner_nested [read] [a] | by_reference.cpp:134:29:134:29 | a | -| by_reference.cpp:135:8:135:13 | pouter [read] [inner_ptr, a] | by_reference.cpp:135:16:135:24 | inner_ptr [read] [a] | -| by_reference.cpp:135:16:135:24 | inner_ptr [read] [a] | by_reference.cpp:135:27:135:27 | a | -| by_reference.cpp:136:8:136:13 | pouter [read] [a] | by_reference.cpp:136:16:136:16 | a | -| complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | this [read] [a_] | -| complex.cpp:9:20:9:21 | FieldAddress [read] | complex.cpp:9:7:9:7 | ReturnValue | -| complex.cpp:9:20:9:21 | this [read] [a_] | complex.cpp:9:20:9:21 | FieldAddress [read] | -| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [read] [b_] | -| complex.cpp:10:20:10:21 | FieldAddress [read] | complex.cpp:10:7:10:7 | ReturnValue | -| complex.cpp:10:20:10:21 | this [read] [b_] | complex.cpp:10:20:10:21 | FieldAddress [read] | -| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | a_ [post update] | -| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | b_ [post update] | -| complex.cpp:40:17:40:17 | *b [inner, f, a_] | complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | -| complex.cpp:40:17:40:17 | *b [inner, f, b_] | complex.cpp:43:8:43:8 | (reference dereference) [read] [inner, f, b_] | -| complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | complex.cpp:42:10:42:14 | inner [read] [f, a_] | -| complex.cpp:42:10:42:14 | inner [read] [f, a_] | complex.cpp:42:16:42:16 | f [read] [a_] | -| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:9:7:9:7 | this [a_] | -| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:42:18:42:18 | call to a | -| complex.cpp:42:16:42:16 | f [read] [a_] | complex.cpp:42:16:42:16 | f [a_] | -| complex.cpp:43:8:43:8 | (reference dereference) [read] [inner, f, b_] | complex.cpp:43:10:43:14 | inner [read] [f, b_] | -| complex.cpp:43:10:43:14 | inner [read] [f, b_] | complex.cpp:43:16:43:16 | f [read] [b_] | -| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:10:7:10:7 | this [b_] | -| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:43:16:43:16 | f [read] [b_] | complex.cpp:43:16:43:16 | f [b_] | -| complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | -| complex.cpp:53:6:53:10 | inner [post update] [f, a_] | complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | -| complex.cpp:53:12:53:12 | f [post update] [a_] | complex.cpp:53:6:53:10 | inner [post update] [f, a_] | -| complex.cpp:53:12:53:12 | f [post update] [a_] | complex.cpp:53:12:53:12 | f [post update] [a_] | +| by_reference.cpp:84:3:84:25 | ... = ... | by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | +| by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | ... = ... | +| by_reference.cpp:88:3:88:24 | ... = ... | by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | +| by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | +| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | ... = ... | +| by_reference.cpp:91:25:91:26 | pa | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | +| by_reference.cpp:91:25:91:26 | pa | by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | +| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:91:25:91:26 | pa | +| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:124:15:124:21 | taint_a_ref output argument | +| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:128:15:128:23 | taint_a_ref output argument | +| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:95:25:95:26 | pa | +| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | by_reference.cpp:102:28:102:39 | outer indirection [post update] [inner_nested, a] | +| by_reference.cpp:102:28:102:39 | outer indirection [post update] [inner_nested, a] | by_reference.cpp:110:8:110:12 | outer indirection [inner_nested, a] | +| by_reference.cpp:103:27:103:35 | outer indirection [post update] [inner_ptr indirection, a] | by_reference.cpp:111:8:111:12 | outer indirection [inner_ptr indirection, a] | +| by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | by_reference.cpp:103:27:103:35 | outer indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | by_reference.cpp:104:22:104:22 | outer indirection [post update] [a] | +| by_reference.cpp:104:22:104:22 | outer indirection [post update] [a] | by_reference.cpp:112:8:112:12 | outer indirection [a] | +| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | by_reference.cpp:106:30:106:41 | pouter indirection [post update] [inner_nested, a] | +| by_reference.cpp:106:30:106:41 | pouter indirection [post update] [inner_nested, a] | by_reference.cpp:114:8:114:13 | pouter indirection [inner_nested, a] | +| by_reference.cpp:107:29:107:37 | pouter indirection [post update] [inner_ptr indirection, a] | by_reference.cpp:115:8:115:13 | pouter indirection [inner_ptr indirection, a] | +| by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | by_reference.cpp:107:29:107:37 | pouter indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | by_reference.cpp:108:24:108:24 | pouter indirection [post update] [a] | +| by_reference.cpp:108:24:108:24 | pouter indirection [post update] [a] | by_reference.cpp:116:8:116:13 | pouter indirection [a] | +| by_reference.cpp:110:8:110:12 | outer indirection [inner_nested, a] | by_reference.cpp:110:14:110:25 | inner_nested indirection [a] | +| by_reference.cpp:110:14:110:25 | inner_nested indirection [a] | by_reference.cpp:110:27:110:27 | a | +| by_reference.cpp:110:14:110:25 | inner_nested indirection [a] | by_reference.cpp:110:27:110:27 | a indirection | +| by_reference.cpp:110:27:110:27 | a indirection | by_reference.cpp:110:27:110:27 | a | +| by_reference.cpp:111:8:111:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | +| by_reference.cpp:111:8:111:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | +| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | +| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | by_reference.cpp:111:25:111:25 | a | +| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | by_reference.cpp:111:25:111:25 | a indirection | +| by_reference.cpp:111:25:111:25 | a indirection | by_reference.cpp:111:25:111:25 | a | +| by_reference.cpp:112:8:112:12 | outer indirection [a] | by_reference.cpp:112:14:112:14 | a | +| by_reference.cpp:112:8:112:12 | outer indirection [a] | by_reference.cpp:112:14:112:14 | a indirection | +| by_reference.cpp:112:14:112:14 | a indirection | by_reference.cpp:112:14:112:14 | a | +| by_reference.cpp:114:8:114:13 | pouter indirection [inner_nested, a] | by_reference.cpp:114:16:114:27 | inner_nested indirection [a] | +| by_reference.cpp:114:16:114:27 | inner_nested indirection [a] | by_reference.cpp:114:29:114:29 | a | +| by_reference.cpp:114:16:114:27 | inner_nested indirection [a] | by_reference.cpp:114:29:114:29 | a indirection | +| by_reference.cpp:114:29:114:29 | a indirection | by_reference.cpp:114:29:114:29 | a | +| by_reference.cpp:115:8:115:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | +| by_reference.cpp:115:8:115:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | +| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | +| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | by_reference.cpp:115:27:115:27 | a | +| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | by_reference.cpp:115:27:115:27 | a indirection | +| by_reference.cpp:115:27:115:27 | a indirection | by_reference.cpp:115:27:115:27 | a | +| by_reference.cpp:116:8:116:13 | pouter indirection [a] | by_reference.cpp:116:16:116:16 | a | +| by_reference.cpp:116:8:116:13 | pouter indirection [a] | by_reference.cpp:116:16:116:16 | a indirection | +| by_reference.cpp:116:16:116:16 | a indirection | by_reference.cpp:116:16:116:16 | a | +| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:122:27:122:38 | outer indirection [post update] [inner_nested, a] | +| by_reference.cpp:122:27:122:38 | outer indirection [post update] [inner_nested, a] | by_reference.cpp:130:8:130:12 | outer indirection [inner_nested, a] | +| by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | by_reference.cpp:123:28:123:36 | outer indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:123:28:123:36 | outer indirection [post update] [inner_ptr indirection, a] | by_reference.cpp:131:8:131:12 | outer indirection [inner_ptr indirection, a] | +| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | by_reference.cpp:124:21:124:21 | outer indirection [post update] [a] | +| by_reference.cpp:124:21:124:21 | outer indirection [post update] [a] | by_reference.cpp:132:8:132:12 | outer indirection [a] | +| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | by_reference.cpp:126:29:126:40 | pouter indirection [post update] [inner_nested, a] | +| by_reference.cpp:126:29:126:40 | pouter indirection [post update] [inner_nested, a] | by_reference.cpp:134:8:134:13 | pouter indirection [inner_nested, a] | +| by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | by_reference.cpp:127:30:127:38 | pouter indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:127:30:127:38 | pouter indirection [post update] [inner_ptr indirection, a] | by_reference.cpp:135:8:135:13 | pouter indirection [inner_ptr indirection, a] | +| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | by_reference.cpp:128:23:128:23 | pouter indirection [post update] [a] | +| by_reference.cpp:128:23:128:23 | pouter indirection [post update] [a] | by_reference.cpp:136:8:136:13 | pouter indirection [a] | +| by_reference.cpp:130:8:130:12 | outer indirection [inner_nested, a] | by_reference.cpp:130:14:130:25 | inner_nested indirection [a] | +| by_reference.cpp:130:14:130:25 | inner_nested indirection [a] | by_reference.cpp:130:27:130:27 | a | +| by_reference.cpp:130:14:130:25 | inner_nested indirection [a] | by_reference.cpp:130:27:130:27 | a indirection | +| by_reference.cpp:130:27:130:27 | a indirection | by_reference.cpp:130:27:130:27 | a | +| by_reference.cpp:131:8:131:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | +| by_reference.cpp:131:8:131:12 | outer indirection [inner_ptr indirection, a] | by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | +| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | +| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | by_reference.cpp:131:25:131:25 | a | +| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | by_reference.cpp:131:25:131:25 | a indirection | +| by_reference.cpp:131:25:131:25 | a indirection | by_reference.cpp:131:25:131:25 | a | +| by_reference.cpp:132:8:132:12 | outer indirection [a] | by_reference.cpp:132:14:132:14 | a | +| by_reference.cpp:132:8:132:12 | outer indirection [a] | by_reference.cpp:132:14:132:14 | a indirection | +| by_reference.cpp:132:14:132:14 | a indirection | by_reference.cpp:132:14:132:14 | a | +| by_reference.cpp:134:8:134:13 | pouter indirection [inner_nested, a] | by_reference.cpp:134:16:134:27 | inner_nested indirection [a] | +| by_reference.cpp:134:16:134:27 | inner_nested indirection [a] | by_reference.cpp:134:29:134:29 | a | +| by_reference.cpp:134:16:134:27 | inner_nested indirection [a] | by_reference.cpp:134:29:134:29 | a indirection | +| by_reference.cpp:134:29:134:29 | a indirection | by_reference.cpp:134:29:134:29 | a | +| by_reference.cpp:135:8:135:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | +| by_reference.cpp:135:8:135:13 | pouter indirection [inner_ptr indirection, a] | by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | +| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | +| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | by_reference.cpp:135:27:135:27 | a | +| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | by_reference.cpp:135:27:135:27 | a indirection | +| by_reference.cpp:135:27:135:27 | a indirection | by_reference.cpp:135:27:135:27 | a | +| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a | +| by_reference.cpp:136:8:136:13 | pouter indirection [a] | by_reference.cpp:136:16:136:16 | a indirection | +| by_reference.cpp:136:16:136:16 | a indirection | by_reference.cpp:136:16:136:16 | a | +| complex.cpp:9:7:9:7 | this indirection [a_] | complex.cpp:9:20:9:21 | this indirection [a_] | +| complex.cpp:9:20:9:21 | a_ | complex.cpp:9:7:9:7 | a indirection | +| complex.cpp:9:20:9:21 | a_ indirection | complex.cpp:9:7:9:7 | a indirection | +| complex.cpp:9:20:9:21 | this indirection [a_] | complex.cpp:9:20:9:21 | a_ | +| complex.cpp:9:20:9:21 | this indirection [a_] | complex.cpp:9:20:9:21 | a_ indirection | +| complex.cpp:10:7:10:7 | this indirection [b_] | complex.cpp:10:20:10:21 | this indirection [b_] | +| complex.cpp:10:20:10:21 | b_ | complex.cpp:10:7:10:7 | b indirection | +| complex.cpp:10:20:10:21 | b_ indirection | complex.cpp:10:7:10:7 | b indirection | +| complex.cpp:10:20:10:21 | this indirection [b_] | complex.cpp:10:20:10:21 | b_ | +| complex.cpp:10:20:10:21 | this indirection [b_] | complex.cpp:10:20:10:21 | b_ indirection | +| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | ... = ... | +| complex.cpp:11:22:11:27 | ... = ... | complex.cpp:11:22:11:23 | this indirection [post update] [a_] | +| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | ... = ... | +| complex.cpp:12:22:12:27 | ... = ... | complex.cpp:12:22:12:23 | this indirection [post update] [b_] | +| complex.cpp:40:17:40:17 | b indirection [inner, f, a_] | complex.cpp:42:8:42:8 | b indirection [inner, f, a_] | +| complex.cpp:40:17:40:17 | b indirection [inner, f, b_] | complex.cpp:43:8:43:8 | b indirection [inner, f, b_] | +| complex.cpp:42:8:42:8 | b indirection [inner, f, a_] | complex.cpp:42:10:42:14 | inner indirection [f, a_] | +| complex.cpp:42:10:42:14 | inner indirection [f, a_] | complex.cpp:42:16:42:16 | f indirection [a_] | +| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:9:7:9:7 | this indirection [a_] | +| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:42:18:42:18 | call to a | +| complex.cpp:43:8:43:8 | b indirection [inner, f, b_] | complex.cpp:43:10:43:14 | inner indirection [f, b_] | +| complex.cpp:43:10:43:14 | inner indirection [f, b_] | complex.cpp:43:16:43:16 | f indirection [b_] | +| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:10:7:10:7 | this indirection [b_] | +| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:43:18:43:18 | call to b | +| complex.cpp:53:6:53:10 | b1 indirection [post update] [inner, f, a_] | complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | complex.cpp:53:6:53:10 | b1 indirection [post update] [inner, f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | complex.cpp:53:6:53:10 | b1 indirection [post update] [inner, f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | complex.cpp:53:6:53:10 | b1 indirection [post update] [inner, f, a_] | +| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | +| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | +| complex.cpp:53:12:53:12 | setA output argument [a_] | complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | | complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | -| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | f [post update] [a_] | -| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:19:53:28 | call to user_input | -| complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | -| complex.cpp:54:6:54:10 | inner [post update] [f, b_] | complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | -| complex.cpp:54:12:54:12 | f [post update] [b_] | complex.cpp:54:6:54:10 | inner [post update] [f, b_] | -| complex.cpp:54:12:54:12 | f [post update] [b_] | complex.cpp:54:12:54:12 | f [post update] [b_] | +| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:53:12:53:12 | setA output argument [a_] | +| complex.cpp:54:6:54:10 | b2 indirection [post update] [inner, f, b_] | complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | complex.cpp:54:6:54:10 | b2 indirection [post update] [inner, f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | complex.cpp:54:6:54:10 | b2 indirection [post update] [inner, f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | complex.cpp:54:6:54:10 | b2 indirection [post update] [inner, f, b_] | +| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | +| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | +| complex.cpp:54:12:54:12 | setB output argument [b_] | complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | -| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | f [post update] [b_] | -| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:19:54:28 | call to user_input | -| complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | -| complex.cpp:55:6:55:10 | inner [post update] [f, a_] | complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | -| complex.cpp:55:12:55:12 | f [post update] [a_] | complex.cpp:55:6:55:10 | inner [post update] [f, a_] | -| complex.cpp:55:12:55:12 | f [post update] [a_] | complex.cpp:55:12:55:12 | f [post update] [a_] | +| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:54:12:54:12 | setB output argument [b_] | +| complex.cpp:55:6:55:10 | b3 indirection [post update] [inner, f, a_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | complex.cpp:55:6:55:10 | b3 indirection [post update] [inner, f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | complex.cpp:55:6:55:10 | b3 indirection [post update] [inner, f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | complex.cpp:55:6:55:10 | b3 indirection [post update] [inner, f, a_] | +| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | +| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | +| complex.cpp:55:12:55:12 | setA output argument [a_] | complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | | complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | -| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | f [post update] [a_] | -| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:19:55:28 | call to user_input | -| complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | -| complex.cpp:56:6:56:10 | inner [post update] [f, b_] | complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | -| complex.cpp:56:12:56:12 | f [post update] [b_] | complex.cpp:56:6:56:10 | inner [post update] [f, b_] | -| complex.cpp:56:12:56:12 | f [post update] [b_] | complex.cpp:56:12:56:12 | f [post update] [b_] | +| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:55:12:55:12 | setA output argument [a_] | +| complex.cpp:56:6:56:10 | b3 indirection [post update] [inner, f, b_] | complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | complex.cpp:56:6:56:10 | b3 indirection [post update] [inner, f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | complex.cpp:56:6:56:10 | b3 indirection [post update] [inner, f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | complex.cpp:56:6:56:10 | b3 indirection [post update] [inner, f, b_] | +| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | +| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | +| complex.cpp:56:12:56:12 | setB output argument [b_] | complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | -| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | f [post update] [b_] | -| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:19:56:28 | call to user_input | -| complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | *b [inner, f, a_] | -| complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | *b [inner, f, b_] | -| complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | *b [inner, f, a_] | -| complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | *b [inner, f, b_] | -| conflated.cpp:10:7:10:7 | FieldAddress [post update] | conflated.cpp:11:9:11:10 | (reference dereference) [read] [p] | -| conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:10:7:10:7 | FieldAddress [post update] | -| conflated.cpp:11:9:11:10 | (reference dereference) [read] [p] | conflated.cpp:11:8:11:12 | * ... | -| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | (void *)... | -| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw | -| conflated.cpp:29:7:29:7 | x [post update] | conflated.cpp:30:8:30:9 | pa [read] [x] | -| conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:29:7:29:7 | x [post update] | -| conflated.cpp:30:8:30:9 | pa [read] [x] | conflated.cpp:30:12:30:12 | FieldAddress [read] | -| conflated.cpp:30:12:30:12 | FieldAddress [read] | conflated.cpp:30:12:30:12 | x | -| conflated.cpp:36:7:36:7 | x [post update] | conflated.cpp:37:8:37:9 | pa [read] [x] | -| conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:36:7:36:7 | x [post update] | -| conflated.cpp:37:8:37:9 | pa [read] [x] | conflated.cpp:37:12:37:12 | FieldAddress [read] | -| conflated.cpp:37:12:37:12 | FieldAddress [read] | conflated.cpp:37:12:37:12 | x | -| conflated.cpp:54:7:54:10 | FieldAddress [post update] [y] | conflated.cpp:55:8:55:9 | ll [read] [next, y] | -| conflated.cpp:54:13:54:13 | y [post update] | conflated.cpp:54:7:54:10 | FieldAddress [post update] [y] | -| conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:54:13:54:13 | y [post update] | -| conflated.cpp:55:8:55:9 | ll [read] [next, y] | conflated.cpp:55:12:55:15 | next [read] [y] | -| conflated.cpp:55:12:55:15 | next [read] [y] | conflated.cpp:55:18:55:18 | FieldAddress [read] | -| conflated.cpp:55:18:55:18 | FieldAddress [read] | conflated.cpp:55:18:55:18 | y | -| conflated.cpp:60:7:60:10 | FieldAddress [post update] [y] | conflated.cpp:61:8:61:9 | ll [read] [next, y] | -| conflated.cpp:60:13:60:13 | y [post update] | conflated.cpp:60:7:60:10 | FieldAddress [post update] [y] | -| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:13:60:13 | y [post update] | -| conflated.cpp:61:8:61:9 | ll [read] [next, y] | conflated.cpp:61:12:61:15 | next [read] [y] | -| conflated.cpp:61:12:61:15 | next [read] [y] | conflated.cpp:61:18:61:18 | FieldAddress [read] | -| conflated.cpp:61:18:61:18 | FieldAddress [read] | conflated.cpp:61:18:61:18 | y | -| constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:22:18:23 | this [read] [a_] | -| constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | -| constructors.cpp:18:22:18:23 | FieldAddress [read] | constructors.cpp:18:9:18:9 | ReturnValue | -| constructors.cpp:18:22:18:23 | this [read] [a_] | constructors.cpp:18:22:18:23 | FieldAddress [read] | -| constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | this [read] [b_] | -| constructors.cpp:19:22:19:23 | FieldAddress [read] | constructors.cpp:19:9:19:9 | ReturnValue | -| constructors.cpp:19:22:19:23 | this [read] [b_] | constructors.cpp:19:22:19:23 | FieldAddress [read] | -| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | FieldAddress [post update] | -| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | FieldAddress [post update] | -| constructors.cpp:23:25:23:29 | FieldAddress [post update] | constructors.cpp:23:5:23:7 | this [post update] [a_] | -| constructors.cpp:23:32:23:36 | FieldAddress [post update] | constructors.cpp:23:5:23:7 | this [post update] [b_] | -| constructors.cpp:26:15:26:15 | *f [a_] | constructors.cpp:28:10:28:10 | f indirection [a_] | -| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:28:10:28:10 | f indirection [b_] | -| constructors.cpp:26:15:26:15 | *f [b_] | constructors.cpp:29:10:29:10 | f [b_] | -| constructors.cpp:28:10:28:10 | a output argument [b_] | constructors.cpp:29:10:29:10 | f [b_] | -| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] | +| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:56:12:56:12 | setB output argument [b_] | +| complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | b indirection [inner, f, a_] | +| complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | b indirection [inner, f, b_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | complex.cpp:40:17:40:17 | b indirection [inner, f, a_] | +| complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | complex.cpp:40:17:40:17 | b indirection [inner, f, b_] | +| conflated.cpp:10:3:10:22 | ... = ... | conflated.cpp:10:7:10:7 | ra indirection [post update] [p indirection] | +| conflated.cpp:10:7:10:7 | ra indirection [post update] [p indirection] | conflated.cpp:11:9:11:10 | ra indirection [p indirection] | +| conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:10:3:10:22 | ... = ... | +| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | conflated.cpp:11:8:11:12 | * ... | +| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | conflated.cpp:11:12:11:12 | p indirection | +| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | conflated.cpp:11:12:11:12 | p indirection | +| conflated.cpp:11:12:11:12 | p indirection | conflated.cpp:11:8:11:12 | * ... | +| conflated.cpp:11:12:11:12 | p indirection | conflated.cpp:11:8:11:12 | * ... | +| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | +| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | +| conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | +| conflated.cpp:29:3:29:22 | ... = ... | conflated.cpp:29:7:29:7 | pa indirection [post update] [x] | +| conflated.cpp:29:7:29:7 | pa indirection [post update] [x] | conflated.cpp:30:8:30:9 | pa indirection [x] | +| conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:29:3:29:22 | ... = ... | +| conflated.cpp:30:8:30:9 | pa indirection [x] | conflated.cpp:30:12:30:12 | x | +| conflated.cpp:30:8:30:9 | pa indirection [x] | conflated.cpp:30:12:30:12 | x indirection | +| conflated.cpp:30:12:30:12 | x indirection | conflated.cpp:30:12:30:12 | x | +| conflated.cpp:36:3:36:22 | ... = ... | conflated.cpp:36:7:36:7 | pa indirection [post update] [x] | +| conflated.cpp:36:7:36:7 | pa indirection [post update] [x] | conflated.cpp:37:8:37:9 | pa indirection [x] | +| conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:36:3:36:22 | ... = ... | +| conflated.cpp:37:8:37:9 | pa indirection [x] | conflated.cpp:37:12:37:12 | x | +| conflated.cpp:37:8:37:9 | pa indirection [x] | conflated.cpp:37:12:37:12 | x indirection | +| conflated.cpp:37:12:37:12 | x indirection | conflated.cpp:37:12:37:12 | x | +| conflated.cpp:54:3:54:28 | ... = ... | conflated.cpp:54:13:54:13 | next indirection [post update] [y] | +| conflated.cpp:54:7:54:10 | ll indirection [post update] [next indirection, y] | conflated.cpp:55:8:55:9 | ll indirection [next indirection, y] | +| conflated.cpp:54:13:54:13 | next indirection [post update] [y] | conflated.cpp:54:7:54:10 | ll indirection [post update] [next indirection, y] | +| conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:54:3:54:28 | ... = ... | +| conflated.cpp:55:8:55:9 | ll indirection [next indirection, y] | conflated.cpp:55:12:55:15 | next indirection [y] | +| conflated.cpp:55:8:55:9 | ll indirection [next indirection, y] | conflated.cpp:55:12:55:15 | next indirection [y] | +| conflated.cpp:55:12:55:15 | next indirection [y] | conflated.cpp:55:12:55:15 | next indirection [y] | +| conflated.cpp:55:12:55:15 | next indirection [y] | conflated.cpp:55:18:55:18 | y | +| conflated.cpp:55:12:55:15 | next indirection [y] | conflated.cpp:55:18:55:18 | y indirection | +| conflated.cpp:55:18:55:18 | y indirection | conflated.cpp:55:18:55:18 | y | +| conflated.cpp:60:3:60:28 | ... = ... | conflated.cpp:60:13:60:13 | next indirection [post update] [y] | +| conflated.cpp:60:7:60:10 | ll indirection [post update] [next indirection, y] | conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] | +| conflated.cpp:60:13:60:13 | next indirection [post update] [y] | conflated.cpp:60:7:60:10 | ll indirection [post update] [next indirection, y] | +| conflated.cpp:60:17:60:26 | call to user_input | conflated.cpp:60:3:60:28 | ... = ... | +| conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] | conflated.cpp:61:12:61:15 | next indirection [y] | +| conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] | conflated.cpp:61:12:61:15 | next indirection [y] | +| conflated.cpp:61:12:61:15 | next indirection [y] | conflated.cpp:61:12:61:15 | next indirection [y] | +| conflated.cpp:61:12:61:15 | next indirection [y] | conflated.cpp:61:18:61:18 | y | +| conflated.cpp:61:12:61:15 | next indirection [y] | conflated.cpp:61:18:61:18 | y indirection | +| conflated.cpp:61:18:61:18 | y indirection | conflated.cpp:61:18:61:18 | y | +| constructors.cpp:18:9:18:9 | this indirection [a_] | constructors.cpp:18:22:18:23 | this indirection [a_] | +| constructors.cpp:18:22:18:23 | a_ | constructors.cpp:18:9:18:9 | a indirection | +| constructors.cpp:18:22:18:23 | a_ indirection | constructors.cpp:18:9:18:9 | a indirection | +| constructors.cpp:18:22:18:23 | this indirection [a_] | constructors.cpp:18:22:18:23 | a_ | +| constructors.cpp:18:22:18:23 | this indirection [a_] | constructors.cpp:18:22:18:23 | a_ indirection | +| constructors.cpp:19:9:19:9 | this indirection [b_] | constructors.cpp:19:22:19:23 | this indirection [b_] | +| constructors.cpp:19:22:19:23 | b_ | constructors.cpp:19:9:19:9 | b indirection | +| constructors.cpp:19:22:19:23 | b_ indirection | constructors.cpp:19:9:19:9 | b indirection | +| constructors.cpp:19:22:19:23 | this indirection [b_] | constructors.cpp:19:22:19:23 | b_ | +| constructors.cpp:19:22:19:23 | this indirection [b_] | constructors.cpp:19:22:19:23 | b_ indirection | +| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | a | +| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | b | +| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:25:23:29 | this indirection [post update] [a_] | +| constructors.cpp:23:35:23:35 | b | constructors.cpp:23:32:23:36 | this indirection [post update] [b_] | +| constructors.cpp:26:15:26:15 | f indirection [a_] | constructors.cpp:28:10:28:10 | f indirection [a_] | +| constructors.cpp:26:15:26:15 | f indirection [b_] | constructors.cpp:29:10:29:10 | f indirection [b_] | +| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | this indirection [a_] | | constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:28:12:28:12 | call to a | -| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | -| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | -| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | -| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:29:12:29:12 | call to b | -| constructors.cpp:34:9:34:9 | Argument this [post update] [a_] | constructors.cpp:40:9:40:9 | f indirection [a_] | +| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:19:9:19:9 | this indirection [b_] | +| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:29:12:29:12 | call to b | +| constructors.cpp:34:9:34:9 | call to Foo [a_] | constructors.cpp:40:9:40:9 | f indirection [a_] | | constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | -| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:9:34:9 | Argument this [post update] [a_] | -| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:11:34:20 | call to user_input | -| constructors.cpp:35:9:35:9 | Argument this [post update] [b_] | constructors.cpp:43:9:43:9 | g indirection [b_] | +| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:34:9:34:9 | call to Foo [a_] | +| constructors.cpp:35:9:35:9 | call to Foo [b_] | constructors.cpp:43:9:43:9 | g indirection [b_] | | constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | -| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:9:35:9 | Argument this [post update] [b_] | -| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:14:35:23 | call to user_input | -| constructors.cpp:36:9:36:9 | Argument this [post update] [a_] | constructors.cpp:46:9:46:9 | h indirection [a_] | -| constructors.cpp:36:9:36:9 | Argument this [post update] [b_] | constructors.cpp:46:9:46:9 | h indirection [b_] | +| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:35:9:35:9 | call to Foo [b_] | +| constructors.cpp:36:9:36:9 | call to Foo [a_] | constructors.cpp:46:9:46:9 | h indirection [a_] | +| constructors.cpp:36:9:36:9 | call to Foo [b_] | constructors.cpp:46:9:46:9 | h indirection [b_] | | constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | -| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:9:36:9 | Argument this [post update] [a_] | -| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:11:36:20 | call to user_input | +| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:36:9:36:9 | call to Foo [a_] | | constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | -| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:9:36:9 | Argument this [post update] [b_] | -| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:25:36:34 | call to user_input | -| constructors.cpp:40:9:40:9 | f indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | -| constructors.cpp:43:9:43:9 | g indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | -| constructors.cpp:46:9:46:9 | h indirection [a_] | constructors.cpp:26:15:26:15 | *f [a_] | -| constructors.cpp:46:9:46:9 | h indirection [b_] | constructors.cpp:26:15:26:15 | *f [b_] | -| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:36:9:36 | a [post update] | -| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:56:12:56 | a [post update] | -| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:57:13:57 | a [post update] | -| qualifiers.cpp:22:5:22:9 | outer [post update] [inner, a] | qualifiers.cpp:23:10:23:14 | outer [read] [inner, a] | -| qualifiers.cpp:22:23:22:23 | a [post update] | qualifiers.cpp:22:5:22:9 | outer [post update] [inner, a] | -| qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:22:23:22:23 | a [post update] | -| qualifiers.cpp:23:10:23:14 | outer [read] [inner, a] | qualifiers.cpp:23:16:23:20 | inner [read] [a] | -| qualifiers.cpp:23:16:23:20 | inner [read] [a] | qualifiers.cpp:23:23:23:23 | a | -| qualifiers.cpp:27:5:27:9 | outer [post update] [inner, a] | qualifiers.cpp:28:10:28:14 | outer [read] [inner, a] | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | qualifiers.cpp:27:5:27:9 | outer [post update] [inner, a] | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | +| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:36:9:36:9 | call to Foo [b_] | +| constructors.cpp:40:9:40:9 | f indirection [a_] | constructors.cpp:26:15:26:15 | f indirection [a_] | +| constructors.cpp:43:9:43:9 | g indirection [b_] | constructors.cpp:26:15:26:15 | f indirection [b_] | +| constructors.cpp:46:9:46:9 | h indirection [a_] | constructors.cpp:26:15:26:15 | f indirection [a_] | +| constructors.cpp:46:9:46:9 | h indirection [b_] | constructors.cpp:26:15:26:15 | f indirection [b_] | +| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:44 | ... = ... | +| qualifiers.cpp:9:30:9:44 | ... = ... | qualifiers.cpp:9:36:9:36 | this indirection [post update] [a] | +| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:64 | ... = ... | +| qualifiers.cpp:12:49:12:64 | ... = ... | qualifiers.cpp:12:56:12:56 | inner indirection [post update] [a] | +| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:65 | ... = ... | +| qualifiers.cpp:13:51:13:65 | ... = ... | qualifiers.cpp:13:57:13:57 | inner indirection [post update] [a] | +| qualifiers.cpp:22:5:22:9 | getInner output argument [inner indirection, a] | qualifiers.cpp:23:10:23:14 | outer indirection [inner indirection, a] | +| qualifiers.cpp:22:5:22:38 | ... = ... | qualifiers.cpp:22:23:22:23 | call to getInner indirection [post update] [a] | +| qualifiers.cpp:22:23:22:23 | call to getInner indirection [post update] [a] | qualifiers.cpp:22:5:22:9 | getInner output argument [inner indirection, a] | +| qualifiers.cpp:22:27:22:36 | call to user_input | qualifiers.cpp:22:5:22:38 | ... = ... | +| qualifiers.cpp:23:10:23:14 | outer indirection [inner indirection, a] | qualifiers.cpp:23:16:23:20 | inner indirection [a] | +| qualifiers.cpp:23:10:23:14 | outer indirection [inner indirection, a] | qualifiers.cpp:23:16:23:20 | inner indirection [a] | +| qualifiers.cpp:23:16:23:20 | inner indirection [a] | qualifiers.cpp:23:16:23:20 | inner indirection [a] | +| qualifiers.cpp:23:16:23:20 | inner indirection [a] | qualifiers.cpp:23:23:23:23 | a | +| qualifiers.cpp:23:16:23:20 | inner indirection [a] | qualifiers.cpp:23:23:23:23 | a indirection | +| qualifiers.cpp:23:23:23:23 | a indirection | qualifiers.cpp:23:23:23:23 | a | +| qualifiers.cpp:27:5:27:9 | getInner output argument [inner indirection, a] | qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] | +| qualifiers.cpp:27:11:27:18 | setA output argument [a] | qualifiers.cpp:27:5:27:9 | getInner output argument [inner indirection, a] | | qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | -| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | -| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:28:27:37 | call to user_input | -| qualifiers.cpp:28:10:28:14 | outer [read] [inner, a] | qualifiers.cpp:28:16:28:20 | inner [read] [a] | -| qualifiers.cpp:28:16:28:20 | inner [read] [a] | qualifiers.cpp:28:23:28:23 | a | -| qualifiers.cpp:32:17:32:21 | outer [post update] [inner, a] | qualifiers.cpp:33:10:33:14 | outer [read] [inner, a] | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | qualifiers.cpp:32:17:32:21 | outer [post update] [inner, a] | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | +| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:27:11:27:18 | setA output argument [a] | +| qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] | qualifiers.cpp:28:16:28:20 | inner indirection [a] | +| qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] | qualifiers.cpp:28:16:28:20 | inner indirection [a] | +| qualifiers.cpp:28:16:28:20 | inner indirection [a] | qualifiers.cpp:28:16:28:20 | inner indirection [a] | +| qualifiers.cpp:28:16:28:20 | inner indirection [a] | qualifiers.cpp:28:23:28:23 | a | +| qualifiers.cpp:28:16:28:20 | inner indirection [a] | qualifiers.cpp:28:23:28:23 | a indirection | +| qualifiers.cpp:28:23:28:23 | a indirection | qualifiers.cpp:28:23:28:23 | a | +| qualifiers.cpp:32:17:32:21 | getInner output argument [inner indirection, a] | qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] | +| qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] | qualifiers.cpp:32:17:32:21 | getInner output argument [inner indirection, a] | | qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | -| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | -| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:35:32:44 | call to user_input | -| qualifiers.cpp:33:10:33:14 | outer [read] [inner, a] | qualifiers.cpp:33:16:33:20 | inner [read] [a] | -| qualifiers.cpp:33:16:33:20 | inner [read] [a] | qualifiers.cpp:33:23:33:23 | a | -| qualifiers.cpp:37:19:37:35 | * ... [post update] [a] | qualifiers.cpp:37:20:37:24 | outer [post update] [inner, a] | -| qualifiers.cpp:37:20:37:24 | outer [post update] [inner, a] | qualifiers.cpp:38:10:38:14 | outer [read] [inner, a] | +| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] | +| qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] | qualifiers.cpp:33:16:33:20 | inner indirection [a] | +| qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] | qualifiers.cpp:33:16:33:20 | inner indirection [a] | +| qualifiers.cpp:33:16:33:20 | inner indirection [a] | qualifiers.cpp:33:16:33:20 | inner indirection [a] | +| qualifiers.cpp:33:16:33:20 | inner indirection [a] | qualifiers.cpp:33:23:33:23 | a | +| qualifiers.cpp:33:16:33:20 | inner indirection [a] | qualifiers.cpp:33:23:33:23 | a indirection | +| qualifiers.cpp:33:23:33:23 | a indirection | qualifiers.cpp:33:23:33:23 | a | +| qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] | qualifiers.cpp:37:20:37:24 | getInner output argument [inner indirection, a] | +| qualifiers.cpp:37:20:37:24 | getInner output argument [inner indirection, a] | qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, a] | | qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | -| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:19:37:35 | * ... [post update] [a] | -| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:38:37:47 | call to user_input | -| qualifiers.cpp:38:10:38:14 | outer [read] [inner, a] | qualifiers.cpp:38:16:38:20 | inner [read] [a] | -| qualifiers.cpp:38:16:38:20 | inner [read] [a] | qualifiers.cpp:38:23:38:23 | a | -| qualifiers.cpp:42:7:42:11 | outer [post update] [inner, a] | qualifiers.cpp:43:10:43:14 | outer [read] [inner, a] | -| qualifiers.cpp:42:25:42:25 | a [post update] | qualifiers.cpp:42:7:42:11 | outer [post update] [inner, a] | -| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:42:25:42:25 | a [post update] | -| qualifiers.cpp:43:10:43:14 | outer [read] [inner, a] | qualifiers.cpp:43:16:43:20 | inner [read] [a] | -| qualifiers.cpp:43:16:43:20 | inner [read] [a] | qualifiers.cpp:43:23:43:23 | a | -| qualifiers.cpp:47:6:47:11 | & ... [post update] [inner, a] | qualifiers.cpp:48:10:48:14 | outer [read] [inner, a] | -| qualifiers.cpp:47:27:47:27 | a [post update] | qualifiers.cpp:47:6:47:11 | & ... [post update] [inner, a] | -| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:27:47:27 | a [post update] | -| qualifiers.cpp:48:10:48:14 | outer [read] [inner, a] | qualifiers.cpp:48:16:48:20 | inner [read] [a] | -| qualifiers.cpp:48:16:48:20 | inner [read] [a] | qualifiers.cpp:48:23:48:23 | a | -| realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, userInput, bufferLen] | realistic.cpp:61:21:61:23 | foo [read] [bar, baz, userInput, bufferLen] | -| realistic.cpp:53:13:53:15 | bar [post update] [baz, userInput, bufferLen] | realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, userInput, bufferLen] | -| realistic.cpp:53:20:53:22 | FieldAddress [post update] [userInput, bufferLen] | realistic.cpp:53:13:53:15 | bar [post update] [baz, userInput, bufferLen] | -| realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] | realistic.cpp:53:20:53:22 | FieldAddress [post update] [userInput, bufferLen] | -| realistic.cpp:53:35:53:43 | bufferLen [post update] | realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] | -| realistic.cpp:53:47:53:66 | (size_t)... | realistic.cpp:53:35:53:43 | bufferLen [post update] | -| realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:53:35:53:43 | bufferLen [post update] | -| realistic.cpp:61:21:61:23 | foo [read] [bar, baz, userInput, bufferLen] | realistic.cpp:61:21:61:30 | access to array [read] [baz, userInput, bufferLen] | -| realistic.cpp:61:21:61:30 | access to array [read] [baz, userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz [read] [userInput, bufferLen] | -| realistic.cpp:61:32:61:34 | baz [read] [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | -| realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | realistic.cpp:61:14:61:55 | (void *)... | -| simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:22:18:23 | this [read] [a_] | -| simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:18:9:18:9 | ReturnIndirection [b_] | -| simple.cpp:18:22:18:23 | FieldAddress [read] | simple.cpp:18:9:18:9 | ReturnValue | -| simple.cpp:18:22:18:23 | this [read] [a_] | simple.cpp:18:22:18:23 | FieldAddress [read] | -| simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | this [read] [b_] | -| simple.cpp:19:22:19:23 | FieldAddress [read] | simple.cpp:19:9:19:9 | ReturnValue | -| simple.cpp:19:22:19:23 | this [read] [b_] | simple.cpp:19:22:19:23 | FieldAddress [read] | -| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | a_ [post update] | -| simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:10:21:13 | ReturnIndirection [a_] | -| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | b_ [post update] | -| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:10:28:10 | f indirection [a_] | -| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:28:10:28:10 | f indirection [b_] | -| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:10:29:10 | f [b_] | -| simple.cpp:28:10:28:10 | a output argument [b_] | simple.cpp:29:10:29:10 | f [b_] | -| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] | +| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] | +| qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, a] | qualifiers.cpp:38:16:38:20 | inner indirection [a] | +| qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, a] | qualifiers.cpp:38:16:38:20 | inner indirection [a] | +| qualifiers.cpp:38:16:38:20 | inner indirection [a] | qualifiers.cpp:38:16:38:20 | inner indirection [a] | +| qualifiers.cpp:38:16:38:20 | inner indirection [a] | qualifiers.cpp:38:23:38:23 | a | +| qualifiers.cpp:38:16:38:20 | inner indirection [a] | qualifiers.cpp:38:23:38:23 | a indirection | +| qualifiers.cpp:38:23:38:23 | a indirection | qualifiers.cpp:38:23:38:23 | a | +| qualifiers.cpp:42:5:42:40 | ... = ... | qualifiers.cpp:42:25:42:25 | * ... indirection [post update] [a] | +| qualifiers.cpp:42:7:42:11 | getInner output argument [inner indirection, a] | qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] | +| qualifiers.cpp:42:25:42:25 | * ... indirection [post update] [a] | qualifiers.cpp:42:7:42:11 | getInner output argument [inner indirection, a] | +| qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:42:5:42:40 | ... = ... | +| qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] | qualifiers.cpp:43:16:43:20 | inner indirection [a] | +| qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] | qualifiers.cpp:43:16:43:20 | inner indirection [a] | +| qualifiers.cpp:43:16:43:20 | inner indirection [a] | qualifiers.cpp:43:16:43:20 | inner indirection [a] | +| qualifiers.cpp:43:16:43:20 | inner indirection [a] | qualifiers.cpp:43:23:43:23 | a | +| qualifiers.cpp:43:16:43:20 | inner indirection [a] | qualifiers.cpp:43:23:43:23 | a indirection | +| qualifiers.cpp:43:23:43:23 | a indirection | qualifiers.cpp:43:23:43:23 | a | +| qualifiers.cpp:47:5:47:42 | ... = ... | qualifiers.cpp:47:27:47:27 | call to getInner indirection [post update] [a] | +| qualifiers.cpp:47:6:47:11 | getInner output argument [inner indirection, a] | qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] | +| qualifiers.cpp:47:27:47:27 | call to getInner indirection [post update] [a] | qualifiers.cpp:47:6:47:11 | getInner output argument [inner indirection, a] | +| qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:47:5:47:42 | ... = ... | +| qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] | qualifiers.cpp:48:16:48:20 | inner indirection [a] | +| qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] | qualifiers.cpp:48:16:48:20 | inner indirection [a] | +| qualifiers.cpp:48:16:48:20 | inner indirection [a] | qualifiers.cpp:48:16:48:20 | inner indirection [a] | +| qualifiers.cpp:48:16:48:20 | inner indirection [a] | qualifiers.cpp:48:23:48:23 | a | +| qualifiers.cpp:48:16:48:20 | inner indirection [a] | qualifiers.cpp:48:23:48:23 | a indirection | +| qualifiers.cpp:48:23:48:23 | a indirection | qualifiers.cpp:48:23:48:23 | a | +| realistic.cpp:53:9:53:66 | ... = ... | realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] | +| realistic.cpp:53:13:53:15 | foo indirection [post update] [bar, baz indirection, userInput, bufferLen] | realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | +| realistic.cpp:53:20:53:22 | access to array indirection [post update] [baz indirection, userInput, bufferLen] | realistic.cpp:53:13:53:15 | foo indirection [post update] [bar, baz indirection, userInput, bufferLen] | +| realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] | realistic.cpp:53:20:53:22 | access to array indirection [post update] [baz indirection, userInput, bufferLen] | +| realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] | realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] | +| realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... | +| realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:53:9:53:66 | ... = ... | +| realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | +| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | +| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | +| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | +| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | +| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | realistic.cpp:61:14:61:55 | bufferLen | +| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | realistic.cpp:61:47:61:55 | bufferLen indirection | +| realistic.cpp:61:47:61:55 | bufferLen indirection | realistic.cpp:61:14:61:55 | bufferLen | +| realistic.cpp:61:47:61:55 | bufferLen indirection | realistic.cpp:61:47:61:55 | bufferLen | +| simple.cpp:18:9:18:9 | this indirection [a_] | simple.cpp:18:22:18:23 | this indirection [a_] | +| simple.cpp:18:22:18:23 | a_ | simple.cpp:18:9:18:9 | a indirection | +| simple.cpp:18:22:18:23 | a_ indirection | simple.cpp:18:9:18:9 | a indirection | +| simple.cpp:18:22:18:23 | this indirection [a_] | simple.cpp:18:22:18:23 | a_ | +| simple.cpp:18:22:18:23 | this indirection [a_] | simple.cpp:18:22:18:23 | a_ indirection | +| simple.cpp:19:9:19:9 | this indirection [b_] | simple.cpp:19:22:19:23 | this indirection [b_] | +| simple.cpp:19:22:19:23 | b_ | simple.cpp:19:9:19:9 | b indirection | +| simple.cpp:19:22:19:23 | b_ indirection | simple.cpp:19:9:19:9 | b indirection | +| simple.cpp:19:22:19:23 | this indirection [b_] | simple.cpp:19:22:19:23 | b_ | +| simple.cpp:19:22:19:23 | this indirection [b_] | simple.cpp:19:22:19:23 | b_ indirection | +| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | ... = ... | +| simple.cpp:20:24:20:29 | ... = ... | simple.cpp:20:24:20:25 | this indirection [post update] [a_] | +| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | ... = ... | +| simple.cpp:21:24:21:29 | ... = ... | simple.cpp:21:24:21:25 | this indirection [post update] [b_] | +| simple.cpp:26:15:26:15 | f indirection [a_] | simple.cpp:28:10:28:10 | f indirection [a_] | +| simple.cpp:26:15:26:15 | f indirection [b_] | simple.cpp:29:10:29:10 | f indirection [b_] | +| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | this indirection [a_] | | simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:28:12:28:12 | call to a | -| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] | -| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | -| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | -| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:29:12:29:12 | call to b | -| simple.cpp:39:5:39:5 | f [post update] [a_] | simple.cpp:45:9:45:9 | f indirection [a_] | +| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:19:9:19:9 | this indirection [b_] | +| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:29:12:29:12 | call to b | +| simple.cpp:39:5:39:5 | setA output argument [a_] | simple.cpp:45:9:45:9 | f indirection [a_] | | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | -| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | f [post update] [a_] | -| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:12:39:21 | call to user_input | -| simple.cpp:40:5:40:5 | g [post update] [b_] | simple.cpp:48:9:48:9 | g indirection [b_] | +| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:39:5:39:5 | setA output argument [a_] | +| simple.cpp:40:5:40:5 | setB output argument [b_] | simple.cpp:48:9:48:9 | g indirection [b_] | | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | -| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | g [post update] [b_] | -| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:12:40:21 | call to user_input | -| simple.cpp:41:5:41:5 | h [post update] [a_] | simple.cpp:42:5:42:5 | h indirection [a_] | -| simple.cpp:41:5:41:5 | h [post update] [a_] | simple.cpp:51:9:51:9 | h indirection [a_] | +| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:40:5:40:5 | setB output argument [b_] | +| simple.cpp:41:5:41:5 | setA output argument [a_] | simple.cpp:51:9:51:9 | h indirection [a_] | | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | -| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | h [post update] [a_] | -| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:12:41:21 | call to user_input | -| simple.cpp:42:5:42:5 | h [post update] [b_] | simple.cpp:51:9:51:9 | h indirection [b_] | -| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] | -| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | -| simple.cpp:42:5:42:5 | setB output argument [a_] | simple.cpp:51:9:51:9 | h indirection [a_] | +| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:41:5:41:5 | setA output argument [a_] | +| simple.cpp:42:5:42:5 | setB output argument [b_] | simple.cpp:51:9:51:9 | h indirection [b_] | | simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | -| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | h [post update] [b_] | -| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:12:42:21 | call to user_input | -| simple.cpp:45:9:45:9 | f indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | -| simple.cpp:48:9:48:9 | g indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | -| simple.cpp:51:9:51:9 | h indirection [a_] | simple.cpp:26:15:26:15 | *f [a_] | -| simple.cpp:51:9:51:9 | h indirection [b_] | simple.cpp:26:15:26:15 | *f [b_] | -| simple.cpp:65:5:65:5 | a [post update] [i] | simple.cpp:67:10:67:11 | a2 [read] [i] | -| simple.cpp:65:7:65:7 | i [post update] | simple.cpp:65:5:65:5 | a [post update] [i] | -| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:7:65:7 | i [post update] | -| simple.cpp:67:10:67:11 | a2 [read] [i] | simple.cpp:67:13:67:13 | FieldAddress [read] | -| simple.cpp:67:13:67:13 | FieldAddress [read] | simple.cpp:67:13:67:13 | i | -| simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:79:16:79:17 | this [read] [f2, f1] | -| simple.cpp:79:16:79:17 | f2 [read] [f1] | simple.cpp:79:19:79:20 | FieldAddress [read] | -| simple.cpp:79:16:79:17 | this [read] [f2, f1] | simple.cpp:79:16:79:17 | f2 [read] [f1] | -| simple.cpp:79:19:79:20 | FieldAddress [read] | simple.cpp:78:9:78:15 | ReturnValue | -| simple.cpp:83:9:83:10 | f2 [post update] [f1] | simple.cpp:84:14:84:20 | this [f2, f1] | -| simple.cpp:83:12:83:13 | f1 [post update] | simple.cpp:83:9:83:10 | f2 [post update] [f1] | -| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:12:83:13 | f1 [post update] | -| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] | -| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 | -| simple.cpp:92:5:92:5 | a [post update] [i] | simple.cpp:94:10:94:11 | a2 [read] [i] | -| simple.cpp:92:7:92:7 | i [post update] | simple.cpp:92:5:92:5 | a [post update] [i] | -| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:7:92:7 | i [post update] | -| simple.cpp:94:10:94:11 | a2 [read] [i] | simple.cpp:94:13:94:13 | FieldAddress [read] | -| simple.cpp:94:13:94:13 | FieldAddress [read] | simple.cpp:94:13:94:13 | i | -| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | ReturnIndirection [a] | -| struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:15:8:15:9 | ab [read] [a] | -| struct_init.c:14:24:14:25 | ab [a] | struct_init.c:15:8:15:9 | ab [read] [a] | -| struct_init.c:15:8:15:9 | ab [read] [a] | struct_init.c:15:12:15:12 | a | -| struct_init.c:15:8:15:9 | ab [read] [a] | struct_init.c:15:12:15:12 | a | -| struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:22:8:22:9 | ab [read] [a] | -| struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:24:10:24:12 | & ... indirection [a] | -| struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | -| struct_init.c:20:17:20:36 | FieldAddress [post update] | struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | -| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | FieldAddress [post update] | -| struct_init.c:22:8:22:9 | ab [read] [a] | struct_init.c:22:11:22:11 | a | -| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | -| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:24:10:24:12 | absink output argument [a] | -| struct_init.c:24:10:24:12 | absink output argument [a] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | -| struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer [read] [nestedAB, a] | -| struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | -| struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | -| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | -| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | -| struct_init.c:27:5:27:23 | FieldAddress [post update] | struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | -| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | FieldAddress [post update] | -| struct_init.c:31:8:31:12 | outer [read] [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB [read] [a] | -| struct_init.c:31:14:31:21 | nestedAB [read] [a] | struct_init.c:31:23:31:23 | a | -| struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | struct_init.c:33:14:33:22 | pointerAB [read] [a] | -| struct_init.c:33:14:33:22 | pointerAB [read] [a] | struct_init.c:33:25:33:25 | a | -| struct_init.c:36:10:36:24 | & ... [a] | struct_init.c:14:24:14:25 | ab [a] | -| struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | struct_init.c:36:10:36:24 | & ... [a] | -| struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | -| struct_init.c:40:17:40:36 | FieldAddress [post update] | struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | -| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | FieldAddress [post update] | -| struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | -| struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | -| struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | struct_init.c:46:16:46:24 | pointerAB [a] | -| struct_init.c:46:16:46:24 | pointerAB [a] | struct_init.c:14:24:14:25 | ab [a] | +| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:42:5:42:5 | setB output argument [b_] | +| simple.cpp:45:9:45:9 | f indirection [a_] | simple.cpp:26:15:26:15 | f indirection [a_] | +| simple.cpp:48:9:48:9 | g indirection [b_] | simple.cpp:26:15:26:15 | f indirection [b_] | +| simple.cpp:51:9:51:9 | h indirection [a_] | simple.cpp:26:15:26:15 | f indirection [a_] | +| simple.cpp:51:9:51:9 | h indirection [b_] | simple.cpp:26:15:26:15 | f indirection [b_] | +| simple.cpp:65:5:65:22 | ... = ... | simple.cpp:65:7:65:7 | a indirection [post update] [i] | +| simple.cpp:65:7:65:7 | a indirection [post update] [i] | simple.cpp:67:10:67:11 | a2 indirection [i] | +| simple.cpp:65:11:65:20 | call to user_input | simple.cpp:65:5:65:22 | ... = ... | +| simple.cpp:67:10:67:11 | a2 indirection [i] | simple.cpp:67:13:67:13 | i | +| simple.cpp:67:10:67:11 | a2 indirection [i] | simple.cpp:67:13:67:13 | i indirection | +| simple.cpp:67:13:67:13 | i indirection | simple.cpp:67:13:67:13 | i | +| simple.cpp:78:9:78:15 | this indirection [f2, f1] | simple.cpp:79:16:79:17 | this indirection [f2, f1] | +| simple.cpp:79:16:79:17 | f2 indirection [f1] | simple.cpp:79:19:79:20 | f1 | +| simple.cpp:79:16:79:17 | f2 indirection [f1] | simple.cpp:79:19:79:20 | f1 indirection | +| simple.cpp:79:16:79:17 | this indirection [f2, f1] | simple.cpp:79:16:79:17 | f2 indirection [f1] | +| simple.cpp:79:19:79:20 | f1 | simple.cpp:78:9:78:15 | getf2f1 indirection | +| simple.cpp:79:19:79:20 | f1 indirection | simple.cpp:78:9:78:15 | getf2f1 indirection | +| simple.cpp:83:9:83:10 | this indirection [post update] [f2, f1] | simple.cpp:84:14:84:20 | this indirection [f2, f1] | +| simple.cpp:83:9:83:28 | ... = ... | simple.cpp:83:12:83:13 | f2 indirection [post update] [f1] | +| simple.cpp:83:12:83:13 | f2 indirection [post update] [f1] | simple.cpp:83:9:83:10 | this indirection [post update] [f2, f1] | +| simple.cpp:83:17:83:26 | call to user_input | simple.cpp:83:9:83:28 | ... = ... | +| simple.cpp:84:14:84:20 | this indirection [f2, f1] | simple.cpp:78:9:78:15 | this indirection [f2, f1] | +| simple.cpp:84:14:84:20 | this indirection [f2, f1] | simple.cpp:84:14:84:20 | call to getf2f1 | +| simple.cpp:92:5:92:22 | ... = ... | simple.cpp:92:7:92:7 | a indirection [post update] [i] | +| simple.cpp:92:7:92:7 | a indirection [post update] [i] | simple.cpp:94:10:94:11 | a2 indirection [i] | +| simple.cpp:92:11:92:20 | call to user_input | simple.cpp:92:5:92:22 | ... = ... | +| simple.cpp:94:10:94:11 | a2 indirection [i] | simple.cpp:94:13:94:13 | i | +| simple.cpp:94:10:94:11 | a2 indirection [i] | simple.cpp:94:13:94:13 | i indirection | +| simple.cpp:94:13:94:13 | i indirection | simple.cpp:94:13:94:13 | i | +| struct_init.c:14:24:14:25 | ab indirection [a] | struct_init.c:15:8:15:9 | ab indirection [a] | +| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a | +| struct_init.c:15:8:15:9 | ab indirection [a] | struct_init.c:15:12:15:12 | a indirection | +| struct_init.c:15:12:15:12 | a indirection | struct_init.c:15:12:15:12 | a | +| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:22:8:22:9 | ab indirection [a] | +| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:24:10:24:12 | & ... indirection [a] | +| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | struct_init.c:28:5:28:7 | & ... indirection [a] | +| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | +| struct_init.c:20:20:20:29 | call to user_input | struct_init.c:20:20:20:29 | call to user_input | +| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a | +| struct_init.c:22:8:22:9 | ab indirection [a] | struct_init.c:22:11:22:11 | a indirection | +| struct_init.c:22:11:22:11 | a indirection | struct_init.c:22:11:22:11 | a | +| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] | +| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | +| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | +| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | +| struct_init.c:27:7:27:16 | call to user_input | struct_init.c:27:7:27:16 | call to user_input | +| struct_init.c:28:5:28:7 | & ... indirection [a] | struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | +| struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] | struct_init.c:31:14:31:21 | nestedAB indirection [a] | +| struct_init.c:31:14:31:21 | nestedAB indirection [a] | struct_init.c:31:23:31:23 | a | +| struct_init.c:31:14:31:21 | nestedAB indirection [a] | struct_init.c:31:23:31:23 | a indirection | +| struct_init.c:31:23:31:23 | a indirection | struct_init.c:31:23:31:23 | a | +| struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] | struct_init.c:33:14:33:22 | pointerAB indirection [a] | +| struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] | struct_init.c:33:14:33:22 | pointerAB indirection [a] | +| struct_init.c:33:14:33:22 | pointerAB indirection [a] | struct_init.c:33:14:33:22 | pointerAB indirection [a] | +| struct_init.c:33:14:33:22 | pointerAB indirection [a] | struct_init.c:33:25:33:25 | a | +| struct_init.c:33:14:33:22 | pointerAB indirection [a] | struct_init.c:33:25:33:25 | a indirection | +| struct_init.c:33:25:33:25 | a indirection | struct_init.c:33:25:33:25 | a | +| struct_init.c:36:10:36:24 | & ... indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] | +| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | struct_init.c:36:10:36:24 | & ... indirection [a] | +| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | struct_init.c:43:5:43:7 | & ... indirection [a] | +| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | +| struct_init.c:40:20:40:29 | call to user_input | struct_init.c:40:20:40:29 | call to user_input | +| struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] | struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] | +| struct_init.c:43:5:43:7 | & ... indirection [a] | struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] | +| struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] | struct_init.c:46:16:46:24 | pointerAB indirection [a] | +| struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] | struct_init.c:46:16:46:24 | pointerAB indirection [a] | +| struct_init.c:46:16:46:24 | pointerAB indirection [a] | struct_init.c:14:24:14:25 | ab indirection [a] | +| struct_init.c:46:16:46:24 | pointerAB indirection [a] | struct_init.c:46:16:46:24 | pointerAB indirection [a] | nodes | A.cpp:23:10:23:10 | c | semmle.label | c | -| A.cpp:25:13:25:13 | c [post update] | semmle.label | c [post update] | +| A.cpp:25:7:25:17 | ... = ... | semmle.label | ... = ... | +| A.cpp:25:13:25:13 | this indirection [post update] [c] | semmle.label | this indirection [post update] [c] | | A.cpp:27:17:27:17 | c | semmle.label | c | -| A.cpp:27:28:27:28 | c [post update] | semmle.label | c [post update] | -| A.cpp:28:8:28:10 | ReturnValue | semmle.label | ReturnValue | -| A.cpp:28:8:28:10 | this [c] | semmle.label | this [c] | -| A.cpp:28:23:28:26 | this [read] [c] | semmle.label | this [read] [c] | -| A.cpp:28:29:28:29 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| A.cpp:29:15:29:18 | ReturnValue [c] | semmle.label | ReturnValue [c] | +| A.cpp:27:22:27:32 | ... = ... | semmle.label | ... = ... | +| A.cpp:27:28:27:28 | this indirection [post update] [c] | semmle.label | this indirection [post update] [c] | +| A.cpp:28:8:28:10 | get indirection | semmle.label | get indirection | +| A.cpp:28:8:28:10 | this indirection [c] | semmle.label | this indirection [c] | +| A.cpp:28:23:28:26 | this indirection [c] | semmle.label | this indirection [c] | +| A.cpp:28:29:28:29 | c | semmle.label | c | +| A.cpp:28:29:28:29 | c indirection | semmle.label | c indirection | +| A.cpp:29:15:29:18 | make indirection [c] | semmle.label | make indirection [c] | | A.cpp:29:23:29:23 | c | semmle.label | c | -| A.cpp:31:14:31:21 | new [post update] [c] | semmle.label | new [post update] [c] | +| A.cpp:31:14:31:21 | call to B [c] | semmle.label | call to B [c] | | A.cpp:31:20:31:20 | c | semmle.label | c | +| A.cpp:41:15:41:21 | new | semmle.label | new | +| A.cpp:41:15:41:21 | new | semmle.label | new | +| A.cpp:43:10:43:12 | & ... indirection | semmle.label | & ... indirection | | A.cpp:47:12:47:18 | new | semmle.label | new | -| A.cpp:48:12:48:18 | call to make [c] | semmle.label | call to make [c] | +| A.cpp:48:12:48:18 | call to make indirection [c] | semmle.label | call to make indirection [c] | | A.cpp:48:20:48:20 | c | semmle.label | c | -| A.cpp:49:10:49:10 | b [read] [c] | semmle.label | b [read] [c] | -| A.cpp:49:10:49:13 | (void *)... | semmle.label | (void *)... | -| A.cpp:55:5:55:5 | b [post update] [c] | semmle.label | b [post update] [c] | -| A.cpp:55:12:55:19 | (C *)... | semmle.label | (C *)... | +| A.cpp:49:10:49:10 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:49:10:49:13 | c | semmle.label | c | +| A.cpp:49:13:49:13 | c | semmle.label | c | +| A.cpp:49:13:49:13 | c indirection | semmle.label | c indirection | +| A.cpp:55:5:55:5 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:55:12:55:19 | new | semmle.label | new | | A.cpp:55:12:55:19 | new | semmle.label | new | -| A.cpp:56:10:56:10 | b [c] | semmle.label | b [c] | -| A.cpp:56:10:56:17 | (void *)... | semmle.label | (void *)... | -| A.cpp:56:13:56:15 | call to get | semmle.label | call to get | -| A.cpp:56:13:56:15 | call to get | semmle.label | call to get | -| A.cpp:57:10:57:32 | (void *)... | semmle.label | (void *)... | -| A.cpp:57:11:57:24 | new [c] | semmle.label | new [c] | -| A.cpp:57:11:57:24 | new [post update] [c] | semmle.label | new [post update] [c] | +| A.cpp:56:10:56:10 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:56:10:56:17 | call to get | semmle.label | call to get | +| A.cpp:57:10:57:32 | call to get | semmle.label | call to get | +| A.cpp:57:11:57:24 | call to B [c] | semmle.label | call to B [c] | +| A.cpp:57:11:57:24 | new indirection [c] | semmle.label | new indirection [c] | | A.cpp:57:17:57:23 | new | semmle.label | new | | A.cpp:57:17:57:23 | new | semmle.label | new | -| A.cpp:57:28:57:30 | call to get | semmle.label | call to get | -| A.cpp:57:28:57:30 | call to get | semmle.label | call to get | -| A.cpp:64:10:64:15 | call to setOnB [c] | semmle.label | call to setOnB [c] | -| A.cpp:64:21:64:28 | (C *)... | semmle.label | (C *)... | +| A.cpp:64:10:64:15 | call to setOnB indirection [c] | semmle.label | call to setOnB indirection [c] | | A.cpp:64:21:64:28 | new | semmle.label | new | | A.cpp:64:21:64:28 | new | semmle.label | new | -| A.cpp:66:10:66:11 | b2 [read] [c] | semmle.label | b2 [read] [c] | -| A.cpp:66:10:66:14 | (void *)... | semmle.label | (void *)... | -| A.cpp:73:10:73:19 | call to setOnBWrap [c] | semmle.label | call to setOnBWrap [c] | -| A.cpp:73:25:73:32 | (C *)... | semmle.label | (C *)... | +| A.cpp:66:10:66:11 | b2 indirection [c] | semmle.label | b2 indirection [c] | +| A.cpp:66:10:66:14 | c | semmle.label | c | +| A.cpp:66:14:66:14 | c | semmle.label | c | +| A.cpp:66:14:66:14 | c indirection | semmle.label | c indirection | +| A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | semmle.label | call to setOnBWrap indirection [c] | | A.cpp:73:25:73:32 | new | semmle.label | new | | A.cpp:73:25:73:32 | new | semmle.label | new | -| A.cpp:75:10:75:11 | b2 [read] [c] | semmle.label | b2 [read] [c] | -| A.cpp:75:10:75:14 | (void *)... | semmle.label | (void *)... | -| A.cpp:78:6:78:15 | ReturnValue [c] | semmle.label | ReturnValue [c] | +| A.cpp:75:10:75:11 | b2 indirection [c] | semmle.label | b2 indirection [c] | +| A.cpp:75:10:75:14 | c | semmle.label | c | +| A.cpp:75:14:75:14 | c | semmle.label | c | +| A.cpp:75:14:75:14 | c indirection | semmle.label | c indirection | +| A.cpp:78:6:78:15 | setOnBWrap indirection [c] | semmle.label | setOnBWrap indirection [c] | | A.cpp:78:27:78:27 | c | semmle.label | c | -| A.cpp:81:10:81:15 | call to setOnB [c] | semmle.label | call to setOnB [c] | +| A.cpp:81:10:81:15 | call to setOnB indirection [c] | semmle.label | call to setOnB indirection [c] | | A.cpp:81:21:81:21 | c | semmle.label | c | -| A.cpp:85:9:85:14 | ReturnValue [c] | semmle.label | ReturnValue [c] | +| A.cpp:85:9:85:14 | setOnB indirection [c] | semmle.label | setOnB indirection [c] | | A.cpp:85:26:85:26 | c | semmle.label | c | -| A.cpp:90:7:90:8 | b2 [post update] [c] | semmle.label | b2 [post update] [c] | +| A.cpp:90:7:90:8 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:90:15:90:15 | c | semmle.label | c | | A.cpp:98:12:98:18 | new | semmle.label | new | -| A.cpp:100:9:100:9 | a [post update] | semmle.label | a [post update] | -| A.cpp:101:8:101:9 | c1 [a] | semmle.label | c1 [a] | -| A.cpp:103:14:103:14 | c [a] | semmle.label | c [a] | -| A.cpp:107:12:107:13 | c1 [read] [a] | semmle.label | c1 [read] [a] | -| A.cpp:107:12:107:16 | (void *)... | semmle.label | (void *)... | -| A.cpp:120:12:120:13 | c1 [read] [a] | semmle.label | c1 [read] [a] | -| A.cpp:120:12:120:16 | (void *)... | semmle.label | (void *)... | -| A.cpp:126:5:126:5 | b [post update] [c] | semmle.label | b [post update] [c] | -| A.cpp:126:5:126:5 | b [post update] [c] | semmle.label | b [post update] [c] | +| A.cpp:100:5:100:13 | ... = ... | semmle.label | ... = ... | +| A.cpp:100:9:100:9 | c1 indirection [post update] [a] | semmle.label | c1 indirection [post update] [a] | +| A.cpp:101:8:101:9 | c1 indirection [a] | semmle.label | c1 indirection [a] | +| A.cpp:103:14:103:14 | c indirection [a] | semmle.label | c indirection [a] | +| A.cpp:107:12:107:13 | c1 indirection [a] | semmle.label | c1 indirection [a] | +| A.cpp:107:12:107:16 | a | semmle.label | a | +| A.cpp:107:16:107:16 | a | semmle.label | a | +| A.cpp:107:16:107:16 | a indirection | semmle.label | a indirection | +| A.cpp:120:12:120:13 | c1 indirection [a] | semmle.label | c1 indirection [a] | +| A.cpp:120:12:120:16 | a | semmle.label | a | +| A.cpp:120:16:120:16 | a | semmle.label | a | +| A.cpp:120:16:120:16 | a indirection | semmle.label | a indirection | +| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] | | A.cpp:126:12:126:18 | new | semmle.label | new | | A.cpp:126:12:126:18 | new | semmle.label | new | -| A.cpp:131:8:131:8 | b [post update] [c] | semmle.label | b [post update] [c] | -| A.cpp:132:10:132:10 | b [read] [c] | semmle.label | b [read] [c] | -| A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... | +| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] | +| A.cpp:132:10:132:10 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:132:10:132:13 | c | semmle.label | c | +| A.cpp:132:13:132:13 | c | semmle.label | c | +| A.cpp:132:13:132:13 | c indirection | semmle.label | c indirection | | A.cpp:140:13:140:13 | b | semmle.label | b | -| A.cpp:142:10:142:10 | c [post update] | semmle.label | c [post update] | +| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... | +| A.cpp:142:10:142:10 | b indirection [post update] [c] | semmle.label | b indirection [post update] [c] | | A.cpp:142:14:142:20 | new | semmle.label | new | -| A.cpp:143:13:143:13 | b [post update] | semmle.label | b [post update] | -| A.cpp:143:13:143:13 | b [post update] | semmle.label | b [post update] | -| A.cpp:143:13:143:13 | b [post update] [c] | semmle.label | b [post update] [c] | +| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... | +| A.cpp:143:7:143:31 | ... = ... | semmle.label | ... = ... | +| A.cpp:143:7:143:31 | ... = ... indirection [c] | semmle.label | ... = ... indirection [c] | +| A.cpp:143:13:143:13 | this indirection [post update] [b indirection, c] | semmle.label | this indirection [post update] [b indirection, c] | +| A.cpp:143:13:143:13 | this indirection [post update] [b] | semmle.label | this indirection [post update] [b] | +| A.cpp:143:13:143:13 | this indirection [post update] [b] | semmle.label | this indirection [post update] [b] | | A.cpp:143:25:143:31 | new | semmle.label | new | | A.cpp:150:12:150:18 | new | semmle.label | new | -| A.cpp:151:12:151:24 | new [post update] [b, c] | semmle.label | new [post update] [b, c] | -| A.cpp:151:12:151:24 | new [post update] [b] | semmle.label | new [post update] [b] | +| A.cpp:151:12:151:24 | call to D [b indirection, c] | semmle.label | call to D [b indirection, c] | +| A.cpp:151:12:151:24 | call to D [b] | semmle.label | call to D [b] | +| A.cpp:151:18:151:18 | D output argument [c] | semmle.label | D output argument [c] | | A.cpp:151:18:151:18 | b | semmle.label | b | -| A.cpp:151:18:151:18 | b [post update] [c] | semmle.label | b [post update] [c] | -| A.cpp:152:10:152:10 | d [read] [b] | semmle.label | d [read] [b] | -| A.cpp:152:10:152:13 | (void *)... | semmle.label | (void *)... | -| A.cpp:153:10:153:10 | d [read] [b, c] | semmle.label | d [read] [b, c] | -| A.cpp:153:10:153:16 | (void *)... | semmle.label | (void *)... | -| A.cpp:153:13:153:13 | b [read] [c] | semmle.label | b [read] [c] | -| A.cpp:154:10:154:10 | b [read] [c] | semmle.label | b [read] [c] | -| A.cpp:154:10:154:13 | (void *)... | semmle.label | (void *)... | +| A.cpp:152:10:152:10 | d indirection [b] | semmle.label | d indirection [b] | +| A.cpp:152:10:152:13 | b | semmle.label | b | +| A.cpp:152:13:152:13 | b | semmle.label | b | +| A.cpp:152:13:152:13 | b indirection | semmle.label | b indirection | +| A.cpp:153:10:153:10 | d indirection [b indirection, c] | semmle.label | d indirection [b indirection, c] | +| A.cpp:153:10:153:16 | c | semmle.label | c | +| A.cpp:153:13:153:13 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:153:13:153:13 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:153:16:153:16 | c | semmle.label | c | +| A.cpp:153:16:153:16 | c indirection | semmle.label | c indirection | +| A.cpp:154:10:154:10 | b indirection [c] | semmle.label | b indirection [c] | +| A.cpp:154:10:154:13 | c | semmle.label | c | +| A.cpp:154:13:154:13 | c | semmle.label | c | +| A.cpp:154:13:154:13 | c indirection | semmle.label | c indirection | | A.cpp:159:12:159:18 | new | semmle.label | new | -| A.cpp:160:18:160:60 | new [post update] [head] | semmle.label | new [post update] [head] | +| A.cpp:160:18:160:60 | call to MyList [head] | semmle.label | call to MyList [head] | | A.cpp:160:29:160:29 | b | semmle.label | b | -| A.cpp:161:18:161:40 | new [post update] [next, head] | semmle.label | new [post update] [next, head] | -| A.cpp:161:38:161:39 | l1 [head] | semmle.label | l1 [head] | -| A.cpp:162:18:162:40 | new [post update] [next, next, head] | semmle.label | new [post update] [next, next, head] | -| A.cpp:162:38:162:39 | l2 [next, head] | semmle.label | l2 [next, head] | -| A.cpp:165:10:165:11 | l3 [read] [next, next, head] | semmle.label | l3 [read] [next, next, head] | -| A.cpp:165:10:165:29 | (void *)... | semmle.label | (void *)... | -| A.cpp:165:14:165:17 | next [read] [next, head] | semmle.label | next [read] [next, head] | -| A.cpp:165:20:165:23 | next [read] [head] | semmle.label | next [read] [head] | -| A.cpp:167:44:167:44 | l [read] [next, head] | semmle.label | l [read] [next, head] | -| A.cpp:167:44:167:44 | l [read] [next, next, head] | semmle.label | l [read] [next, next, head] | -| A.cpp:167:47:167:50 | FieldAddress [read] [head] | semmle.label | FieldAddress [read] [head] | -| A.cpp:167:47:167:50 | FieldAddress [read] [next, head] | semmle.label | FieldAddress [read] [next, head] | -| A.cpp:169:12:169:12 | l [read] [head] | semmle.label | l [read] [head] | -| A.cpp:169:12:169:18 | (void *)... | semmle.label | (void *)... | +| A.cpp:161:18:161:40 | call to MyList [next indirection, head] | semmle.label | call to MyList [next indirection, head] | +| A.cpp:161:38:161:39 | l1 indirection [head] | semmle.label | l1 indirection [head] | +| A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] | semmle.label | call to MyList [next indirection, next indirection, head] | +| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | semmle.label | l2 indirection [next indirection, head] | +| A.cpp:165:10:165:11 | l3 indirection [next indirection, next indirection, head] | semmle.label | l3 indirection [next indirection, next indirection, head] | +| A.cpp:165:10:165:29 | head | semmle.label | head | +| A.cpp:165:14:165:17 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] | +| A.cpp:165:14:165:17 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] | +| A.cpp:165:20:165:23 | next indirection [head] | semmle.label | next indirection [head] | +| A.cpp:165:20:165:23 | next indirection [head] | semmle.label | next indirection [head] | +| A.cpp:165:26:165:29 | head | semmle.label | head | +| A.cpp:165:26:165:29 | head indirection | semmle.label | head indirection | +| A.cpp:167:44:167:44 | l indirection [next indirection, head] | semmle.label | l indirection [next indirection, head] | +| A.cpp:167:44:167:44 | l indirection [next indirection, next indirection, head] | semmle.label | l indirection [next indirection, next indirection, head] | +| A.cpp:167:47:167:50 | next indirection [head] | semmle.label | next indirection [head] | +| A.cpp:167:47:167:50 | next indirection [head] | semmle.label | next indirection [head] | +| A.cpp:167:47:167:50 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] | +| A.cpp:167:47:167:50 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] | +| A.cpp:169:12:169:12 | l indirection [head] | semmle.label | l indirection [head] | +| A.cpp:169:12:169:18 | head | semmle.label | head | +| A.cpp:169:15:169:18 | head | semmle.label | head | +| A.cpp:169:15:169:18 | head indirection | semmle.label | head indirection | | A.cpp:181:15:181:21 | newHead | semmle.label | newHead | -| A.cpp:181:32:181:35 | next [head] | semmle.label | next [head] | -| A.cpp:181:32:181:35 | next [next, head] | semmle.label | next [next, head] | -| A.cpp:183:7:183:10 | head [post update] | semmle.label | head [post update] | -| A.cpp:184:13:184:16 | next [post update] [head] | semmle.label | next [post update] [head] | -| A.cpp:184:13:184:16 | next [post update] [next, head] | semmle.label | next [post update] [next, head] | +| A.cpp:181:32:181:35 | next indirection [head] | semmle.label | next indirection [head] | +| A.cpp:181:32:181:35 | next indirection [next indirection, head] | semmle.label | next indirection [next indirection, head] | +| A.cpp:183:7:183:10 | this indirection [post update] [head] | semmle.label | this indirection [post update] [head] | +| A.cpp:183:7:183:20 | ... = ... | semmle.label | ... = ... | +| A.cpp:184:7:184:23 | ... = ... indirection [head] | semmle.label | ... = ... indirection [head] | +| A.cpp:184:7:184:23 | ... = ... indirection [next indirection, head] | semmle.label | ... = ... indirection [next indirection, head] | +| A.cpp:184:13:184:16 | this indirection [post update] [next indirection, head] | semmle.label | this indirection [post update] [next indirection, head] | +| A.cpp:184:13:184:16 | this indirection [post update] [next indirection, next indirection, head] | semmle.label | this indirection [post update] [next indirection, next indirection, head] | | B.cpp:6:15:6:24 | new | semmle.label | new | -| B.cpp:7:16:7:35 | new [post update] [elem1] | semmle.label | new [post update] [elem1] | +| B.cpp:7:16:7:35 | call to Box1 [elem1] | semmle.label | call to Box1 [elem1] | | B.cpp:7:25:7:25 | e | semmle.label | e | -| B.cpp:8:16:8:27 | new [post update] [box1, elem1] | semmle.label | new [post update] [box1, elem1] | -| B.cpp:8:25:8:26 | b1 [elem1] | semmle.label | b1 [elem1] | -| B.cpp:9:10:9:11 | b2 [read] [box1, elem1] | semmle.label | b2 [read] [box1, elem1] | -| B.cpp:9:10:9:24 | (void *)... | semmle.label | (void *)... | -| B.cpp:9:14:9:17 | box1 [read] [elem1] | semmle.label | box1 [read] [elem1] | +| B.cpp:8:16:8:27 | call to Box2 [box1 indirection, elem1] | semmle.label | call to Box2 [box1 indirection, elem1] | +| B.cpp:8:25:8:26 | b1 indirection [elem1] | semmle.label | b1 indirection [elem1] | +| B.cpp:9:10:9:11 | b2 indirection [box1 indirection, elem1] | semmle.label | b2 indirection [box1 indirection, elem1] | +| B.cpp:9:10:9:24 | elem1 | semmle.label | elem1 | +| B.cpp:9:14:9:17 | box1 indirection [elem1] | semmle.label | box1 indirection [elem1] | +| B.cpp:9:14:9:17 | box1 indirection [elem1] | semmle.label | box1 indirection [elem1] | +| B.cpp:9:20:9:24 | elem1 | semmle.label | elem1 | +| B.cpp:9:20:9:24 | elem1 indirection | semmle.label | elem1 indirection | | B.cpp:15:15:15:27 | new | semmle.label | new | -| B.cpp:16:16:16:38 | new [post update] [elem2] | semmle.label | new [post update] [elem2] | +| B.cpp:16:16:16:38 | call to Box1 [elem2] | semmle.label | call to Box1 [elem2] | | B.cpp:16:37:16:37 | e | semmle.label | e | -| B.cpp:17:16:17:27 | new [post update] [box1, elem2] | semmle.label | new [post update] [box1, elem2] | -| B.cpp:17:25:17:26 | b1 [elem2] | semmle.label | b1 [elem2] | -| B.cpp:19:10:19:11 | b2 [read] [box1, elem2] | semmle.label | b2 [read] [box1, elem2] | -| B.cpp:19:10:19:24 | (void *)... | semmle.label | (void *)... | -| B.cpp:19:14:19:17 | box1 [read] [elem2] | semmle.label | box1 [read] [elem2] | +| B.cpp:17:16:17:27 | call to Box2 [box1 indirection, elem2] | semmle.label | call to Box2 [box1 indirection, elem2] | +| B.cpp:17:25:17:26 | b1 indirection [elem2] | semmle.label | b1 indirection [elem2] | +| B.cpp:19:10:19:11 | b2 indirection [box1 indirection, elem2] | semmle.label | b2 indirection [box1 indirection, elem2] | +| B.cpp:19:10:19:24 | elem2 | semmle.label | elem2 | +| B.cpp:19:14:19:17 | box1 indirection [elem2] | semmle.label | box1 indirection [elem2] | +| B.cpp:19:14:19:17 | box1 indirection [elem2] | semmle.label | box1 indirection [elem2] | +| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 | +| B.cpp:19:20:19:24 | elem2 indirection | semmle.label | elem2 indirection | | B.cpp:33:16:33:17 | e1 | semmle.label | e1 | | B.cpp:33:26:33:27 | e2 | semmle.label | e2 | -| B.cpp:35:13:35:17 | elem1 [post update] | semmle.label | elem1 [post update] | -| B.cpp:36:13:36:17 | elem2 [post update] | semmle.label | elem2 [post update] | -| B.cpp:44:16:44:17 | b1 [elem1] | semmle.label | b1 [elem1] | -| B.cpp:44:16:44:17 | b1 [elem2] | semmle.label | b1 [elem2] | -| B.cpp:46:13:46:16 | box1 [post update] [elem1] | semmle.label | box1 [post update] [elem1] | -| B.cpp:46:13:46:16 | box1 [post update] [elem2] | semmle.label | box1 [post update] [elem2] | -| C.cpp:18:12:18:18 | new [post update] [s1] | semmle.label | new [post update] [s1] | -| C.cpp:19:5:19:5 | c [s1] | semmle.label | c [s1] | -| C.cpp:22:3:22:3 | this [post update] [s1] | semmle.label | this [post update] [s1] | -| C.cpp:22:9:22:22 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| B.cpp:35:7:35:22 | ... = ... | semmle.label | ... = ... | +| B.cpp:35:13:35:17 | this indirection [post update] [elem1] | semmle.label | this indirection [post update] [elem1] | +| B.cpp:36:7:36:22 | ... = ... | semmle.label | ... = ... | +| B.cpp:36:13:36:17 | this indirection [post update] [elem2] | semmle.label | this indirection [post update] [elem2] | +| B.cpp:44:16:44:17 | b1 indirection [elem1] | semmle.label | b1 indirection [elem1] | +| B.cpp:44:16:44:17 | b1 indirection [elem2] | semmle.label | b1 indirection [elem2] | +| B.cpp:46:7:46:21 | ... = ... indirection [elem1] | semmle.label | ... = ... indirection [elem1] | +| B.cpp:46:7:46:21 | ... = ... indirection [elem2] | semmle.label | ... = ... indirection [elem2] | +| B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem1] | semmle.label | this indirection [post update] [box1 indirection, elem1] | +| B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem2] | semmle.label | this indirection [post update] [box1 indirection, elem2] | +| C.cpp:18:12:18:18 | call to C [s1] | semmle.label | call to C [s1] | +| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] | +| C.cpp:19:5:19:5 | c indirection [s1] | semmle.label | c indirection [s1] | +| C.cpp:19:5:19:5 | c indirection [s3] | semmle.label | c indirection [s3] | +| C.cpp:22:9:22:22 | this indirection [post update] [s1] | semmle.label | this indirection [post update] [s1] | | C.cpp:22:12:22:21 | new | semmle.label | new | -| C.cpp:27:8:27:11 | this [s1] | semmle.label | this [s1] | +| C.cpp:22:12:22:21 | new | semmle.label | new | +| C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... | +| C.cpp:24:11:24:12 | this indirection [post update] [s3] | semmle.label | this indirection [post update] [s3] | +| C.cpp:24:16:24:25 | new | semmle.label | new | +| C.cpp:27:8:27:11 | this indirection [s1] | semmle.label | this indirection [s1] | +| C.cpp:27:8:27:11 | this indirection [s3] | semmle.label | this indirection [s3] | | C.cpp:29:10:29:11 | s1 | semmle.label | s1 | -| C.cpp:29:10:29:11 | this [read] [s1] | semmle.label | this [read] [s1] | -| D.cpp:10:11:10:17 | ReturnValue | semmle.label | ReturnValue | -| D.cpp:10:11:10:17 | this [elem] | semmle.label | this [elem] | -| D.cpp:10:30:10:33 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| D.cpp:10:30:10:33 | this [read] [elem] | semmle.label | this [read] [elem] | +| C.cpp:29:10:29:11 | s1 indirection | semmle.label | s1 indirection | +| C.cpp:29:10:29:11 | this indirection [s1] | semmle.label | this indirection [s1] | +| C.cpp:31:10:31:11 | s3 | semmle.label | s3 | +| C.cpp:31:10:31:11 | s3 indirection | semmle.label | s3 indirection | +| C.cpp:31:10:31:11 | this indirection [s3] | semmle.label | this indirection [s3] | +| D.cpp:10:11:10:17 | getElem indirection | semmle.label | getElem indirection | +| D.cpp:10:11:10:17 | this indirection [elem] | semmle.label | this indirection [elem] | +| D.cpp:10:30:10:33 | elem | semmle.label | elem | +| D.cpp:10:30:10:33 | elem indirection | semmle.label | elem indirection | +| D.cpp:10:30:10:33 | this indirection [elem] | semmle.label | this indirection [elem] | | D.cpp:11:24:11:24 | e | semmle.label | e | -| D.cpp:11:29:11:32 | elem [post update] | semmle.label | elem [post update] | -| D.cpp:17:11:17:17 | ReturnValue [elem] | semmle.label | ReturnValue [elem] | -| D.cpp:17:11:17:17 | this [box, elem] | semmle.label | this [box, elem] | -| D.cpp:17:30:17:32 | FieldAddress [read] [elem] | semmle.label | FieldAddress [read] [elem] | -| D.cpp:17:30:17:32 | this [read] [box, elem] | semmle.label | this [read] [box, elem] | -| D.cpp:21:30:21:31 | b2 [box, elem] | semmle.label | b2 [box, elem] | -| D.cpp:22:10:22:11 | b2 [box, elem] | semmle.label | b2 [box, elem] | -| D.cpp:22:10:22:33 | (void *)... | semmle.label | (void *)... | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | semmle.label | call to getBox1 [elem] | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | semmle.label | call to getBox1 [elem] | -| D.cpp:22:25:22:31 | call to getElem | semmle.label | call to getElem | -| D.cpp:22:25:22:31 | call to getElem | semmle.label | call to getElem | +| D.cpp:11:29:11:32 | this indirection [post update] [elem] | semmle.label | this indirection [post update] [elem] | +| D.cpp:11:29:11:36 | ... = ... | semmle.label | ... = ... | +| D.cpp:17:11:17:17 | getBox1 indirection [elem] | semmle.label | getBox1 indirection [elem] | +| D.cpp:17:11:17:17 | this indirection [box indirection, elem] | semmle.label | this indirection [box indirection, elem] | +| D.cpp:17:30:17:32 | box indirection [elem] | semmle.label | box indirection [elem] | +| D.cpp:17:30:17:32 | box indirection [elem] | semmle.label | box indirection [elem] | +| D.cpp:17:30:17:32 | this indirection [box indirection, elem] | semmle.label | this indirection [box indirection, elem] | +| D.cpp:21:30:21:31 | b2 indirection [box indirection, elem] | semmle.label | b2 indirection [box indirection, elem] | +| D.cpp:22:10:22:11 | b2 indirection [box indirection, elem] | semmle.label | b2 indirection [box indirection, elem] | +| D.cpp:22:10:22:33 | call to getElem | semmle.label | call to getElem | +| D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | semmle.label | call to getBox1 indirection [elem] | | D.cpp:28:15:28:24 | new | semmle.label | new | -| D.cpp:30:8:30:10 | FieldAddress [post update] [elem] | semmle.label | FieldAddress [post update] [elem] | -| D.cpp:30:13:30:16 | elem [post update] | semmle.label | elem [post update] | -| D.cpp:31:14:31:14 | b [box, elem] | semmle.label | b [box, elem] | +| D.cpp:30:5:30:20 | ... = ... | semmle.label | ... = ... | +| D.cpp:30:8:30:10 | b indirection [post update] [box indirection, elem] | semmle.label | b indirection [post update] [box indirection, elem] | +| D.cpp:30:13:30:16 | box indirection [post update] [elem] | semmle.label | box indirection [post update] [elem] | +| D.cpp:31:14:31:14 | b indirection [box indirection, elem] | semmle.label | b indirection [box indirection, elem] | | D.cpp:35:15:35:24 | new | semmle.label | new | -| D.cpp:37:8:37:10 | FieldAddress [post update] [elem] | semmle.label | FieldAddress [post update] [elem] | -| D.cpp:37:8:37:10 | box [post update] [elem] | semmle.label | box [post update] [elem] | +| D.cpp:37:8:37:10 | b indirection [post update] [box indirection, elem] | semmle.label | b indirection [post update] [box indirection, elem] | +| D.cpp:37:8:37:10 | setElem output argument [elem] | semmle.label | setElem output argument [elem] | | D.cpp:37:21:37:21 | e | semmle.label | e | -| D.cpp:38:14:38:14 | b [box, elem] | semmle.label | b [box, elem] | +| D.cpp:38:14:38:14 | b indirection [box indirection, elem] | semmle.label | b indirection [box indirection, elem] | | D.cpp:42:15:42:24 | new | semmle.label | new | -| D.cpp:44:5:44:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] | -| D.cpp:44:19:44:22 | elem [post update] | semmle.label | elem [post update] | -| D.cpp:45:14:45:14 | b [box, elem] | semmle.label | b [box, elem] | +| D.cpp:44:5:44:5 | getBox1 output argument [box indirection, elem] | semmle.label | getBox1 output argument [box indirection, elem] | +| D.cpp:44:5:44:26 | ... = ... | semmle.label | ... = ... | +| D.cpp:44:19:44:22 | call to getBox1 indirection [post update] [elem] | semmle.label | call to getBox1 indirection [post update] [elem] | +| D.cpp:45:14:45:14 | b indirection [box indirection, elem] | semmle.label | b indirection [box indirection, elem] | | D.cpp:49:15:49:24 | new | semmle.label | new | -| D.cpp:51:5:51:5 | b [post update] [box, elem] | semmle.label | b [post update] [box, elem] | -| D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | semmle.label | call to getBox1 [post update] [elem] | -| D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | semmle.label | call to getBox1 [post update] [elem] | +| D.cpp:51:5:51:5 | getBox1 output argument [box indirection, elem] | semmle.label | getBox1 output argument [box indirection, elem] | +| D.cpp:51:8:51:14 | setElem output argument [elem] | semmle.label | setElem output argument [elem] | | D.cpp:51:27:51:27 | e | semmle.label | e | -| D.cpp:52:14:52:14 | b [box, elem] | semmle.label | b [box, elem] | +| D.cpp:52:14:52:14 | b indirection [box indirection, elem] | semmle.label | b indirection [box indirection, elem] | | D.cpp:56:15:56:24 | new | semmle.label | new | -| D.cpp:58:5:58:12 | FieldAddress [post update] [box, elem] | semmle.label | FieldAddress [post update] [box, elem] | -| D.cpp:58:15:58:17 | FieldAddress [post update] [elem] | semmle.label | FieldAddress [post update] [elem] | -| D.cpp:58:20:58:23 | elem [post update] | semmle.label | elem [post update] | -| D.cpp:59:5:59:7 | this [boxfield, box, elem] | semmle.label | this [boxfield, box, elem] | -| D.cpp:63:8:63:10 | this [boxfield, box, elem] | semmle.label | this [boxfield, box, elem] | -| D.cpp:64:10:64:17 | boxfield [read] [box, elem] | semmle.label | boxfield [read] [box, elem] | -| D.cpp:64:10:64:17 | this [read] [boxfield, box, elem] | semmle.label | this [read] [boxfield, box, elem] | -| D.cpp:64:10:64:28 | (void *)... | semmle.label | (void *)... | -| D.cpp:64:20:64:22 | box [read] [elem] | semmle.label | box [read] [elem] | -| E.cpp:19:27:19:27 | *p [data, buffer] | semmle.label | *p [data, buffer] | -| E.cpp:21:10:21:10 | p [read] [data, buffer] | semmle.label | p [read] [data, buffer] | -| E.cpp:21:13:21:16 | data [read] [buffer] | semmle.label | data [read] [buffer] | -| E.cpp:21:18:21:23 | buffer | semmle.label | buffer | +| D.cpp:58:5:58:12 | this indirection [post update] [boxfield indirection, box indirection, elem] | semmle.label | this indirection [post update] [boxfield indirection, box indirection, elem] | +| D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... | +| D.cpp:58:15:58:17 | boxfield indirection [post update] [box indirection, elem] | semmle.label | boxfield indirection [post update] [box indirection, elem] | +| D.cpp:58:20:58:23 | box indirection [post update] [elem] | semmle.label | box indirection [post update] [elem] | +| D.cpp:59:5:59:7 | this indirection [boxfield indirection, box indirection, elem] | semmle.label | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:63:8:63:10 | this indirection [boxfield indirection, box indirection, elem] | semmle.label | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | semmle.label | boxfield indirection [box indirection, elem] | +| D.cpp:64:10:64:17 | boxfield indirection [box indirection, elem] | semmle.label | boxfield indirection [box indirection, elem] | +| D.cpp:64:10:64:17 | this indirection [boxfield indirection, box indirection, elem] | semmle.label | this indirection [boxfield indirection, box indirection, elem] | +| D.cpp:64:10:64:28 | elem | semmle.label | elem | +| D.cpp:64:20:64:22 | box indirection [elem] | semmle.label | box indirection [elem] | +| D.cpp:64:20:64:22 | box indirection [elem] | semmle.label | box indirection [elem] | +| D.cpp:64:25:64:28 | elem | semmle.label | elem | +| D.cpp:64:25:64:28 | elem indirection | semmle.label | elem indirection | +| E.cpp:19:27:19:27 | p indirection [data, buffer indirection] | semmle.label | p indirection [data, buffer indirection] | +| E.cpp:21:10:21:10 | p indirection [data, buffer indirection] | semmle.label | p indirection [data, buffer indirection] | +| E.cpp:21:13:21:16 | data indirection [buffer indirection] | semmle.label | data indirection [buffer indirection] | +| E.cpp:21:18:21:23 | buffer indirection | semmle.label | buffer indirection | +| E.cpp:21:18:21:23 | buffer indirection | semmle.label | buffer indirection | | E.cpp:28:21:28:23 | argument_source output argument | semmle.label | argument_source output argument | | E.cpp:29:21:29:29 | argument_source output argument | semmle.label | argument_source output argument | -| E.cpp:29:24:29:29 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| E.cpp:30:21:30:21 | p [post update] [data, buffer] | semmle.label | p [post update] [data, buffer] | +| E.cpp:29:24:29:29 | b indirection [post update] [buffer indirection] | semmle.label | b indirection [post update] [buffer indirection] | | E.cpp:30:21:30:33 | argument_source output argument | semmle.label | argument_source output argument | -| E.cpp:30:23:30:26 | data [post update] [buffer] | semmle.label | data [post update] [buffer] | -| E.cpp:30:28:30:33 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| E.cpp:31:10:31:12 | raw | semmle.label | raw | -| E.cpp:32:10:32:10 | b [read] [buffer] | semmle.label | b [read] [buffer] | -| E.cpp:32:13:32:18 | buffer | semmle.label | buffer | -| E.cpp:33:18:33:19 | & ... indirection [data, buffer] | semmle.label | & ... indirection [data, buffer] | -| aliasing.cpp:9:6:9:7 | m1 [post update] | semmle.label | m1 [post update] | +| E.cpp:30:23:30:26 | p indirection [post update] [data, buffer indirection] | semmle.label | p indirection [post update] [data, buffer indirection] | +| E.cpp:30:28:30:33 | data indirection [post update] [buffer indirection] | semmle.label | data indirection [post update] [buffer indirection] | +| E.cpp:31:10:31:12 | raw indirection | semmle.label | raw indirection | +| E.cpp:31:10:31:12 | raw indirection | semmle.label | raw indirection | +| E.cpp:32:10:32:10 | b indirection [buffer indirection] | semmle.label | b indirection [buffer indirection] | +| E.cpp:32:13:32:18 | buffer indirection | semmle.label | buffer indirection | +| E.cpp:32:13:32:18 | buffer indirection | semmle.label | buffer indirection | +| E.cpp:33:18:33:19 | & ... indirection [data, buffer indirection] | semmle.label | & ... indirection [data, buffer indirection] | +| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:9:6:9:7 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | | aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:13:5:13:6 | m1 [post update] | semmle.label | m1 [post update] | +| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:13:5:13:6 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | | aliasing.cpp:13:10:13:19 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:25:17:25:19 | & ... [post update] [m1] | semmle.label | & ... [post update] [m1] | -| aliasing.cpp:26:19:26:20 | s2 [post update] [m1] | semmle.label | s2 [post update] [m1] | -| aliasing.cpp:29:8:29:9 | s1 [read] [m1] | semmle.label | s1 [read] [m1] | -| aliasing.cpp:29:11:29:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | semmle.label | pointerSetter output argument [m1] | +| aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | semmle.label | referenceSetter output argument [m1] | +| aliasing.cpp:29:8:29:9 | s1 indirection [m1] | semmle.label | s1 indirection [m1] | | aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 | -| aliasing.cpp:30:8:30:9 | s2 [read] [m1] | semmle.label | s2 [read] [m1] | -| aliasing.cpp:30:11:30:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:29:11:29:12 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:30:8:30:9 | s2 indirection [m1] | semmle.label | s2 indirection [m1] | | aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 | -| aliasing.cpp:60:3:60:4 | s2 [post update] [m1] | semmle.label | s2 [post update] [m1] | -| aliasing.cpp:60:6:60:7 | m1 [post update] | semmle.label | m1 [post update] | +| aliasing.cpp:30:11:30:12 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:60:3:60:22 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:60:6:60:7 | s2 indirection [post update] [m1] | semmle.label | s2 indirection [post update] [m1] | | aliasing.cpp:60:11:60:20 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:62:8:62:12 | copy2 [read] [m1] | semmle.label | copy2 [read] [m1] | -| aliasing.cpp:62:14:62:15 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:62:8:62:12 | copy2 indirection [m1] | semmle.label | copy2 indirection [m1] | | aliasing.cpp:62:14:62:15 | m1 | semmle.label | m1 | -| aliasing.cpp:92:3:92:3 | w [post update] [s, m1] | semmle.label | w [post update] [s, m1] | -| aliasing.cpp:92:5:92:5 | s [post update] [m1] | semmle.label | s [post update] [m1] | -| aliasing.cpp:92:7:92:8 | m1 [post update] | semmle.label | m1 [post update] | +| aliasing.cpp:62:14:62:15 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:92:3:92:23 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:92:5:92:5 | w indirection [post update] [s, m1] | semmle.label | w indirection [post update] [s, m1] | +| aliasing.cpp:92:7:92:8 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | | aliasing.cpp:92:12:92:21 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:93:8:93:8 | w [read] [s, m1] | semmle.label | w [read] [s, m1] | -| aliasing.cpp:93:10:93:10 | s [read] [m1] | semmle.label | s [read] [m1] | -| aliasing.cpp:93:12:93:13 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:93:8:93:8 | w indirection [s, m1] | semmle.label | w indirection [s, m1] | +| aliasing.cpp:93:10:93:10 | s indirection [m1] | semmle.label | s indirection [m1] | | aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 | -| aliasing.cpp:106:3:106:5 | * ... [post update] | semmle.label | * ... [post update] | +| aliasing.cpp:93:12:93:13 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:98:3:98:21 | ... = ... | semmle.label | ... = ... | +| aliasing.cpp:98:5:98:6 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | +| aliasing.cpp:98:10:98:19 | call to user_input | semmle.label | call to user_input | +| aliasing.cpp:101:13:101:22 | & ... indirection | semmle.label | & ... indirection | +| aliasing.cpp:101:14:101:19 | s_copy indirection [m1] | semmle.label | s_copy indirection [m1] | +| aliasing.cpp:102:8:102:10 | * ... | semmle.label | * ... | +| aliasing.cpp:105:23:105:24 | pa | semmle.label | pa | | aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input | -| aliasing.cpp:141:15:141:15 | s [post update] [data] | semmle.label | s [post update] [data] | -| aliasing.cpp:141:17:141:20 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| aliasing.cpp:141:17:141:20 | data [post update] | semmle.label | data [post update] | -| aliasing.cpp:143:8:143:8 | s [read] [data] | semmle.label | s [read] [data] | +| aliasing.cpp:121:15:121:16 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:122:8:122:12 | access to array | semmle.label | access to array | +| aliasing.cpp:126:15:126:20 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:127:8:127:16 | * ... | semmle.label | * ... | +| aliasing.cpp:131:15:131:16 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:132:8:132:14 | * ... | semmle.label | * ... | +| aliasing.cpp:136:15:136:17 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:137:8:137:11 | * ... | semmle.label | * ... | +| aliasing.cpp:141:17:141:20 | s indirection [post update] [data indirection] | semmle.label | s indirection [post update] [data indirection] | +| aliasing.cpp:141:17:141:20 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:143:8:143:8 | s indirection [data indirection] | semmle.label | s indirection [data indirection] | | aliasing.cpp:143:8:143:16 | access to array | semmle.label | access to array | -| aliasing.cpp:158:15:158:15 | s [post update] [data] | semmle.label | s [post update] [data] | -| aliasing.cpp:158:15:158:20 | data [post update] | semmle.label | data [post update] | -| aliasing.cpp:158:17:158:20 | data [post update] | semmle.label | data [post update] | +| aliasing.cpp:143:8:143:16 | access to array indirection | semmle.label | access to array indirection | +| aliasing.cpp:143:10:143:13 | data indirection | semmle.label | data indirection | +| aliasing.cpp:158:15:158:20 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:158:17:158:20 | s indirection [post update] [data] | semmle.label | s indirection [post update] [data] | | aliasing.cpp:159:8:159:14 | * ... | semmle.label | * ... | -| aliasing.cpp:159:9:159:9 | s [read] [data] | semmle.label | s [read] [data] | -| aliasing.cpp:164:15:164:15 | s [post update] [data] | semmle.label | s [post update] [data] | -| aliasing.cpp:164:15:164:20 | data [post update] | semmle.label | data [post update] | -| aliasing.cpp:164:17:164:20 | data [post update] | semmle.label | data [post update] | -| aliasing.cpp:165:8:165:8 | s [read] [data] | semmle.label | s [read] [data] | +| aliasing.cpp:159:9:159:9 | s indirection [data] | semmle.label | s indirection [data] | +| aliasing.cpp:159:9:159:14 | data indirection | semmle.label | data indirection | +| aliasing.cpp:164:15:164:20 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:164:17:164:20 | s indirection [post update] [data] | semmle.label | s indirection [post update] [data] | +| aliasing.cpp:165:8:165:8 | s indirection [data] | semmle.label | s indirection [data] | | aliasing.cpp:165:8:165:16 | access to array | semmle.label | access to array | -| aliasing.cpp:175:15:175:22 | & ... [post update] | semmle.label | & ... [post update] | -| aliasing.cpp:175:16:175:17 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] | -| aliasing.cpp:175:19:175:19 | s [post update] [m1] | semmle.label | s [post update] [m1] | -| aliasing.cpp:175:21:175:22 | m1 [post update] | semmle.label | m1 [post update] | -| aliasing.cpp:176:8:176:9 | s2 [read] [s, m1] | semmle.label | s2 [read] [s, m1] | -| aliasing.cpp:176:11:176:11 | s [read] [m1] | semmle.label | s [read] [m1] | -| aliasing.cpp:176:13:176:14 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:165:8:165:16 | access to array indirection | semmle.label | access to array indirection | +| aliasing.cpp:175:15:175:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:175:19:175:19 | s2 indirection [post update] [s, m1] | semmle.label | s2 indirection [post update] [s, m1] | +| aliasing.cpp:175:21:175:22 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | +| aliasing.cpp:176:8:176:9 | s2 indirection [s, m1] | semmle.label | s2 indirection [s, m1] | +| aliasing.cpp:176:11:176:11 | s indirection [m1] | semmle.label | s indirection [m1] | | aliasing.cpp:176:13:176:14 | m1 | semmle.label | m1 | -| aliasing.cpp:187:15:187:22 | & ... [post update] | semmle.label | & ... [post update] | -| aliasing.cpp:187:16:187:17 | s2 [post update] [s, m1] | semmle.label | s2 [post update] [s, m1] | -| aliasing.cpp:187:19:187:19 | s [post update] [m1] | semmle.label | s [post update] [m1] | -| aliasing.cpp:187:21:187:22 | m1 [post update] | semmle.label | m1 [post update] | -| aliasing.cpp:189:8:189:11 | s2_2 [read] [s, m1] | semmle.label | s2_2 [read] [s, m1] | -| aliasing.cpp:189:13:189:13 | s [read] [m1] | semmle.label | s [read] [m1] | -| aliasing.cpp:189:15:189:16 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:176:13:176:14 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:187:15:187:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:187:19:187:19 | s2 indirection [post update] [s, m1] | semmle.label | s2 indirection [post update] [s, m1] | +| aliasing.cpp:187:21:187:22 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | +| aliasing.cpp:189:8:189:11 | s2_2 indirection [s, m1] | semmle.label | s2_2 indirection [s, m1] | +| aliasing.cpp:189:13:189:13 | s indirection [m1] | semmle.label | s indirection [m1] | | aliasing.cpp:189:15:189:16 | m1 | semmle.label | m1 | -| aliasing.cpp:200:15:200:24 | & ... [post update] | semmle.label | & ... [post update] | -| aliasing.cpp:200:21:200:21 | s [post update] [m1] | semmle.label | s [post update] [m1] | -| aliasing.cpp:200:23:200:24 | m1 [post update] | semmle.label | m1 [post update] | -| aliasing.cpp:201:8:201:10 | ps2 [read] [s, m1] | semmle.label | ps2 [read] [s, m1] | -| aliasing.cpp:201:13:201:13 | s [read] [m1] | semmle.label | s [read] [m1] | -| aliasing.cpp:201:15:201:16 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| aliasing.cpp:189:15:189:16 | m1 indirection | semmle.label | m1 indirection | +| aliasing.cpp:200:15:200:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| aliasing.cpp:200:21:200:21 | ps2 indirection [post update] [s, m1] | semmle.label | ps2 indirection [post update] [s, m1] | +| aliasing.cpp:200:23:200:24 | s indirection [post update] [m1] | semmle.label | s indirection [post update] [m1] | +| aliasing.cpp:201:8:201:10 | ps2 indirection [s, m1] | semmle.label | ps2 indirection [s, m1] | +| aliasing.cpp:201:13:201:13 | s indirection [m1] | semmle.label | s indirection [m1] | | aliasing.cpp:201:15:201:16 | m1 | semmle.label | m1 | +| aliasing.cpp:201:15:201:16 | m1 indirection | semmle.label | m1 indirection | | arrays.cpp:6:12:6:21 | call to user_input | semmle.label | call to user_input | | arrays.cpp:7:8:7:13 | access to array | semmle.label | access to array | | arrays.cpp:8:8:8:13 | access to array | semmle.label | access to array | @@ -961,550 +1254,601 @@ nodes | arrays.cpp:15:14:15:23 | call to user_input | semmle.label | call to user_input | | arrays.cpp:16:8:16:13 | access to array | semmle.label | access to array | | arrays.cpp:17:8:17:13 | access to array | semmle.label | access to array | -| arrays.cpp:36:3:36:3 | o [post update] [nested, arr, data] | semmle.label | o [post update] [nested, arr, data] | -| arrays.cpp:36:5:36:10 | nested [post update] [arr, data] | semmle.label | nested [post update] [arr, data] | -| arrays.cpp:36:12:36:14 | arr [post update] [data] | semmle.label | arr [post update] [data] | -| arrays.cpp:36:19:36:22 | data [post update] | semmle.label | data [post update] | +| arrays.cpp:36:3:36:37 | ... = ... | semmle.label | ... = ... | +| arrays.cpp:36:5:36:10 | o indirection [post update] [nested, arr, data] | semmle.label | o indirection [post update] [nested, arr, data] | +| arrays.cpp:36:12:36:14 | nested indirection [post update] [arr, data] | semmle.label | nested indirection [post update] [arr, data] | +| arrays.cpp:36:19:36:22 | access to array indirection [post update] [data] | semmle.label | access to array indirection [post update] [data] | | arrays.cpp:36:26:36:35 | call to user_input | semmle.label | call to user_input | -| arrays.cpp:37:8:37:8 | o [read] [nested, arr, data] | semmle.label | o [read] [nested, arr, data] | -| arrays.cpp:37:8:37:22 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:37:10:37:15 | nested [read] [arr, data] | semmle.label | nested [read] [arr, data] | +| arrays.cpp:37:8:37:8 | o indirection [nested, arr, data] | semmle.label | o indirection [nested, arr, data] | +| arrays.cpp:37:8:37:22 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:37:10:37:15 | nested indirection [arr, data] | semmle.label | nested indirection [arr, data] | | arrays.cpp:37:24:37:27 | data | semmle.label | data | -| arrays.cpp:38:8:38:8 | o [read] [nested, arr, data] | semmle.label | o [read] [nested, arr, data] | -| arrays.cpp:38:8:38:22 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:38:10:38:15 | nested [read] [arr, data] | semmle.label | nested [read] [arr, data] | +| arrays.cpp:37:24:37:27 | data indirection | semmle.label | data indirection | +| arrays.cpp:38:8:38:8 | o indirection [nested, arr, data] | semmle.label | o indirection [nested, arr, data] | +| arrays.cpp:38:8:38:22 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:38:10:38:15 | nested indirection [arr, data] | semmle.label | nested indirection [arr, data] | | arrays.cpp:38:24:38:27 | data | semmle.label | data | -| arrays.cpp:42:3:42:3 | o [post update] [indirect, arr, data] | semmle.label | o [post update] [indirect, arr, data] | -| arrays.cpp:42:5:42:12 | FieldAddress [post update] [arr, data] | semmle.label | FieldAddress [post update] [arr, data] | -| arrays.cpp:42:15:42:17 | arr [post update] [data] | semmle.label | arr [post update] [data] | -| arrays.cpp:42:22:42:25 | data [post update] | semmle.label | data [post update] | +| arrays.cpp:38:24:38:27 | data indirection | semmle.label | data indirection | +| arrays.cpp:42:3:42:40 | ... = ... | semmle.label | ... = ... | +| arrays.cpp:42:5:42:12 | o indirection [post update] [indirect indirection, arr, data] | semmle.label | o indirection [post update] [indirect indirection, arr, data] | +| arrays.cpp:42:15:42:17 | indirect indirection [post update] [arr, data] | semmle.label | indirect indirection [post update] [arr, data] | +| arrays.cpp:42:22:42:25 | access to array indirection [post update] [data] | semmle.label | access to array indirection [post update] [data] | | arrays.cpp:42:29:42:38 | call to user_input | semmle.label | call to user_input | -| arrays.cpp:43:8:43:8 | o [read] [indirect, arr, data] | semmle.label | o [read] [indirect, arr, data] | -| arrays.cpp:43:8:43:25 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:43:10:43:17 | indirect [read] [arr, data] | semmle.label | indirect [read] [arr, data] | +| arrays.cpp:43:8:43:8 | o indirection [indirect indirection, arr, data] | semmle.label | o indirection [indirect indirection, arr, data] | +| arrays.cpp:43:8:43:25 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | semmle.label | indirect indirection [arr, data] | +| arrays.cpp:43:10:43:17 | indirect indirection [arr, data] | semmle.label | indirect indirection [arr, data] | | arrays.cpp:43:27:43:30 | data | semmle.label | data | -| arrays.cpp:44:8:44:8 | o [read] [indirect, arr, data] | semmle.label | o [read] [indirect, arr, data] | -| arrays.cpp:44:8:44:25 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:44:10:44:17 | indirect [read] [arr, data] | semmle.label | indirect [read] [arr, data] | +| arrays.cpp:43:27:43:30 | data indirection | semmle.label | data indirection | +| arrays.cpp:44:8:44:8 | o indirection [indirect indirection, arr, data] | semmle.label | o indirection [indirect indirection, arr, data] | +| arrays.cpp:44:8:44:25 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | semmle.label | indirect indirection [arr, data] | +| arrays.cpp:44:10:44:17 | indirect indirection [arr, data] | semmle.label | indirect indirection [arr, data] | | arrays.cpp:44:27:44:30 | data | semmle.label | data | -| arrays.cpp:48:3:48:3 | o [post update] [indirect, ptr, data] | semmle.label | o [post update] [indirect, ptr, data] | -| arrays.cpp:48:5:48:12 | FieldAddress [post update] [ptr, data] | semmle.label | FieldAddress [post update] [ptr, data] | -| arrays.cpp:48:15:48:17 | FieldAddress [post update] [data] | semmle.label | FieldAddress [post update] [data] | -| arrays.cpp:48:22:48:25 | data [post update] | semmle.label | data [post update] | +| arrays.cpp:44:27:44:30 | data indirection | semmle.label | data indirection | +| arrays.cpp:48:3:48:40 | ... = ... | semmle.label | ... = ... | +| arrays.cpp:48:5:48:12 | o indirection [post update] [indirect indirection, ptr indirection, data] | semmle.label | o indirection [post update] [indirect indirection, ptr indirection, data] | +| arrays.cpp:48:15:48:17 | indirect indirection [post update] [ptr indirection, data] | semmle.label | indirect indirection [post update] [ptr indirection, data] | +| arrays.cpp:48:22:48:25 | access to array indirection [post update] [data] | semmle.label | access to array indirection [post update] [data] | | arrays.cpp:48:29:48:38 | call to user_input | semmle.label | call to user_input | -| arrays.cpp:49:8:49:8 | o [read] [indirect, ptr, data] | semmle.label | o [read] [indirect, ptr, data] | -| arrays.cpp:49:8:49:25 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:49:10:49:17 | indirect [read] [ptr, data] | semmle.label | indirect [read] [ptr, data] | +| arrays.cpp:49:8:49:8 | o indirection [indirect indirection, ptr indirection, data] | semmle.label | o indirection [indirect indirection, ptr indirection, data] | +| arrays.cpp:49:8:49:25 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | semmle.label | indirect indirection [ptr indirection, data] | +| arrays.cpp:49:10:49:17 | indirect indirection [ptr indirection, data] | semmle.label | indirect indirection [ptr indirection, data] | +| arrays.cpp:49:20:49:22 | ptr indirection [data] | semmle.label | ptr indirection [data] | | arrays.cpp:49:27:49:30 | data | semmle.label | data | -| arrays.cpp:50:8:50:8 | o [read] [indirect, ptr, data] | semmle.label | o [read] [indirect, ptr, data] | -| arrays.cpp:50:8:50:25 | access to array [read] [data] | semmle.label | access to array [read] [data] | -| arrays.cpp:50:10:50:17 | indirect [read] [ptr, data] | semmle.label | indirect [read] [ptr, data] | +| arrays.cpp:49:27:49:30 | data indirection | semmle.label | data indirection | +| arrays.cpp:50:8:50:8 | o indirection [indirect indirection, ptr indirection, data] | semmle.label | o indirection [indirect indirection, ptr indirection, data] | +| arrays.cpp:50:8:50:25 | access to array indirection [data] | semmle.label | access to array indirection [data] | +| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | semmle.label | indirect indirection [ptr indirection, data] | +| arrays.cpp:50:10:50:17 | indirect indirection [ptr indirection, data] | semmle.label | indirect indirection [ptr indirection, data] | +| arrays.cpp:50:20:50:22 | ptr indirection [data] | semmle.label | ptr indirection [data] | | arrays.cpp:50:27:50:30 | data | semmle.label | data | +| arrays.cpp:50:27:50:30 | data indirection | semmle.label | data indirection | | by_reference.cpp:11:48:11:52 | value | semmle.label | value | -| by_reference.cpp:12:8:12:8 | a [post update] | semmle.label | a [post update] | +| by_reference.cpp:12:5:12:16 | ... = ... | semmle.label | ... = ... | +| by_reference.cpp:12:8:12:8 | s indirection [post update] [a] | semmle.label | s indirection [post update] [a] | | by_reference.cpp:15:26:15:30 | value | semmle.label | value | -| by_reference.cpp:16:11:16:11 | a [post update] | semmle.label | a [post update] | +| by_reference.cpp:16:5:16:19 | ... = ... | semmle.label | ... = ... | +| by_reference.cpp:16:11:16:11 | this indirection [post update] [a] | semmle.label | this indirection [post update] [a] | | by_reference.cpp:19:28:19:32 | value | semmle.label | value | -| by_reference.cpp:20:5:20:8 | this [post update] [a] | semmle.label | this [post update] [a] | -| by_reference.cpp:20:5:20:8 | this [post update] [a] | semmle.label | this [post update] [a] | +| by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] | | by_reference.cpp:20:23:20:27 | value | semmle.label | value | | by_reference.cpp:23:34:23:38 | value | semmle.label | value | -| by_reference.cpp:24:19:24:22 | this [post update] [a] | semmle.label | this [post update] [a] | -| by_reference.cpp:24:19:24:22 | this [post update] [a] | semmle.label | this [post update] [a] | +| by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] | | by_reference.cpp:24:25:24:29 | value | semmle.label | value | -| by_reference.cpp:31:16:31:28 | ReturnValue | semmle.label | ReturnValue | -| by_reference.cpp:31:46:31:46 | *s [a] | semmle.label | *s [a] | -| by_reference.cpp:32:12:32:12 | s [read] [a] | semmle.label | s [read] [a] | -| by_reference.cpp:32:15:32:15 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| by_reference.cpp:35:9:35:19 | *#this [a] | semmle.label | *#this [a] | -| by_reference.cpp:35:9:35:19 | ReturnValue | semmle.label | ReturnValue | -| by_reference.cpp:36:12:36:15 | this [read] [a] | semmle.label | this [read] [a] | -| by_reference.cpp:36:18:36:18 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| by_reference.cpp:39:9:39:21 | *#this [a] | semmle.label | *#this [a] | -| by_reference.cpp:39:9:39:21 | ReturnValue | semmle.label | ReturnValue | +| by_reference.cpp:31:16:31:28 | nonMemberGetA indirection | semmle.label | nonMemberGetA indirection | +| by_reference.cpp:31:46:31:46 | s indirection [a] | semmle.label | s indirection [a] | +| by_reference.cpp:32:12:32:12 | s indirection [a] | semmle.label | s indirection [a] | +| by_reference.cpp:32:15:32:15 | a | semmle.label | a | +| by_reference.cpp:32:15:32:15 | a indirection | semmle.label | a indirection | +| by_reference.cpp:35:9:35:19 | getDirectly indirection | semmle.label | getDirectly indirection | +| by_reference.cpp:35:9:35:19 | this indirection [a] | semmle.label | this indirection [a] | +| by_reference.cpp:36:12:36:15 | this indirection [a] | semmle.label | this indirection [a] | +| by_reference.cpp:36:18:36:18 | a | semmle.label | a | +| by_reference.cpp:36:18:36:18 | a indirection | semmle.label | a indirection | +| by_reference.cpp:39:9:39:21 | getIndirectly indirection | semmle.label | getIndirectly indirection | +| by_reference.cpp:39:9:39:21 | this indirection [a] | semmle.label | this indirection [a] | | by_reference.cpp:40:12:40:15 | this indirection [a] | semmle.label | this indirection [a] | | by_reference.cpp:40:18:40:28 | call to getDirectly | semmle.label | call to getDirectly | -| by_reference.cpp:43:9:43:27 | *#this [a] | semmle.label | *#this [a] | -| by_reference.cpp:43:9:43:27 | ReturnValue | semmle.label | ReturnValue | +| by_reference.cpp:43:9:43:27 | getThroughNonMember indirection | semmle.label | getThroughNonMember indirection | +| by_reference.cpp:43:9:43:27 | this indirection [a] | semmle.label | this indirection [a] | | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | semmle.label | call to nonMemberGetA | | by_reference.cpp:44:26:44:29 | this indirection [a] | semmle.label | this indirection [a] | -| by_reference.cpp:50:3:50:3 | s [post update] [a] | semmle.label | s [post update] [a] | -| by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] | | by_reference.cpp:50:17:50:26 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:51:8:51:8 | s indirection [a] | semmle.label | s indirection [a] | | by_reference.cpp:51:10:51:20 | call to getDirectly | semmle.label | call to getDirectly | -| by_reference.cpp:56:3:56:3 | s [post update] [a] | semmle.label | s [post update] [a] | -| by_reference.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | semmle.label | setIndirectly output argument [a] | | by_reference.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:57:8:57:8 | s indirection [a] | semmle.label | s indirection [a] | | by_reference.cpp:57:10:57:22 | call to getIndirectly | semmle.label | call to getIndirectly | -| by_reference.cpp:62:3:62:3 | s [post update] [a] | semmle.label | s [post update] [a] | -| by_reference.cpp:62:25:62:34 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | semmle.label | setThroughNonMember output argument [a] | | by_reference.cpp:62:25:62:34 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:63:8:63:8 | s indirection [a] | semmle.label | s indirection [a] | | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | semmle.label | call to getThroughNonMember | -| by_reference.cpp:68:17:68:18 | & ... [post update] [a] | semmle.label | & ... [post update] [a] | -| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input | +| by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] | | by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input | | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA | | by_reference.cpp:69:22:69:23 | & ... indirection [a] | semmle.label | & ... indirection [a] | -| by_reference.cpp:84:10:84:10 | a [post update] | semmle.label | a [post update] | +| by_reference.cpp:84:3:84:25 | ... = ... | semmle.label | ... = ... | +| by_reference.cpp:84:10:84:10 | inner indirection [post update] [a] | semmle.label | inner indirection [post update] [a] | | by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:88:9:88:9 | a [post update] | semmle.label | a [post update] | +| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... | +| by_reference.cpp:88:9:88:9 | inner indirection [post update] [a] | semmle.label | inner indirection [post update] [a] | | by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:92:3:92:5 | * ... [post update] | semmle.label | * ... [post update] | +| by_reference.cpp:91:25:91:26 | pa | semmle.label | pa | | by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:96:3:96:4 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] | +| by_reference.cpp:95:25:95:26 | pa | semmle.label | pa | | by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input | -| by_reference.cpp:102:21:102:39 | & ... [post update] [a] | semmle.label | & ... [post update] [a] | -| by_reference.cpp:102:22:102:26 | outer [post update] [inner_nested, a] | semmle.label | outer [post update] [inner_nested, a] | -| by_reference.cpp:102:28:102:39 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:103:21:103:25 | outer [post update] [inner_ptr, a] | semmle.label | outer [post update] [inner_ptr, a] | -| by_reference.cpp:103:27:103:35 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| by_reference.cpp:103:27:103:35 | inner_ptr [post update] [a] | semmle.label | inner_ptr [post update] [a] | -| by_reference.cpp:104:15:104:22 | & ... [post update] | semmle.label | & ... [post update] | -| by_reference.cpp:104:16:104:20 | outer [post update] [a] | semmle.label | outer [post update] [a] | -| by_reference.cpp:104:22:104:22 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:106:21:106:41 | & ... [post update] [a] | semmle.label | & ... [post update] [a] | -| by_reference.cpp:106:30:106:41 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:107:29:107:37 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| by_reference.cpp:107:29:107:37 | inner_ptr [post update] [a] | semmle.label | inner_ptr [post update] [a] | -| by_reference.cpp:108:15:108:24 | & ... [post update] | semmle.label | & ... [post update] | -| by_reference.cpp:108:24:108:24 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:110:8:110:12 | outer [read] [inner_nested, a] | semmle.label | outer [read] [inner_nested, a] | -| by_reference.cpp:110:14:110:25 | inner_nested [read] [a] | semmle.label | inner_nested [read] [a] | +| by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:102:28:102:39 | outer indirection [post update] [inner_nested, a] | semmle.label | outer indirection [post update] [inner_nested, a] | +| by_reference.cpp:103:27:103:35 | outer indirection [post update] [inner_ptr indirection, a] | semmle.label | outer indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| by_reference.cpp:104:22:104:22 | outer indirection [post update] [a] | semmle.label | outer indirection [post update] [a] | +| by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:106:30:106:41 | pouter indirection [post update] [inner_nested, a] | semmle.label | pouter indirection [post update] [inner_nested, a] | +| by_reference.cpp:107:29:107:37 | pouter indirection [post update] [inner_ptr indirection, a] | semmle.label | pouter indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | semmle.label | taint_inner_a_ptr output argument [a] | +| by_reference.cpp:108:15:108:24 | taint_a_ptr output argument | semmle.label | taint_a_ptr output argument | +| by_reference.cpp:108:24:108:24 | pouter indirection [post update] [a] | semmle.label | pouter indirection [post update] [a] | +| by_reference.cpp:110:8:110:12 | outer indirection [inner_nested, a] | semmle.label | outer indirection [inner_nested, a] | +| by_reference.cpp:110:14:110:25 | inner_nested indirection [a] | semmle.label | inner_nested indirection [a] | | by_reference.cpp:110:27:110:27 | a | semmle.label | a | -| by_reference.cpp:111:8:111:12 | outer [read] [inner_ptr, a] | semmle.label | outer [read] [inner_ptr, a] | -| by_reference.cpp:111:14:111:22 | inner_ptr [read] [a] | semmle.label | inner_ptr [read] [a] | +| by_reference.cpp:110:27:110:27 | a indirection | semmle.label | a indirection | +| by_reference.cpp:111:8:111:12 | outer indirection [inner_ptr indirection, a] | semmle.label | outer indirection [inner_ptr indirection, a] | +| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | +| by_reference.cpp:111:14:111:22 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | | by_reference.cpp:111:25:111:25 | a | semmle.label | a | -| by_reference.cpp:112:8:112:12 | outer [read] [a] | semmle.label | outer [read] [a] | +| by_reference.cpp:111:25:111:25 | a indirection | semmle.label | a indirection | +| by_reference.cpp:112:8:112:12 | outer indirection [a] | semmle.label | outer indirection [a] | | by_reference.cpp:112:14:112:14 | a | semmle.label | a | -| by_reference.cpp:114:8:114:13 | pouter [read] [inner_nested, a] | semmle.label | pouter [read] [inner_nested, a] | -| by_reference.cpp:114:16:114:27 | inner_nested [read] [a] | semmle.label | inner_nested [read] [a] | +| by_reference.cpp:112:14:112:14 | a indirection | semmle.label | a indirection | +| by_reference.cpp:114:8:114:13 | pouter indirection [inner_nested, a] | semmle.label | pouter indirection [inner_nested, a] | +| by_reference.cpp:114:16:114:27 | inner_nested indirection [a] | semmle.label | inner_nested indirection [a] | | by_reference.cpp:114:29:114:29 | a | semmle.label | a | -| by_reference.cpp:115:8:115:13 | pouter [read] [inner_ptr, a] | semmle.label | pouter [read] [inner_ptr, a] | -| by_reference.cpp:115:16:115:24 | inner_ptr [read] [a] | semmle.label | inner_ptr [read] [a] | +| by_reference.cpp:114:29:114:29 | a indirection | semmle.label | a indirection | +| by_reference.cpp:115:8:115:13 | pouter indirection [inner_ptr indirection, a] | semmle.label | pouter indirection [inner_ptr indirection, a] | +| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | +| by_reference.cpp:115:16:115:24 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | | by_reference.cpp:115:27:115:27 | a | semmle.label | a | -| by_reference.cpp:116:8:116:13 | pouter [read] [a] | semmle.label | pouter [read] [a] | +| by_reference.cpp:115:27:115:27 | a indirection | semmle.label | a indirection | +| by_reference.cpp:116:8:116:13 | pouter indirection [a] | semmle.label | pouter indirection [a] | | by_reference.cpp:116:16:116:16 | a | semmle.label | a | -| by_reference.cpp:122:21:122:25 | outer [post update] [inner_nested, a] | semmle.label | outer [post update] [inner_nested, a] | -| by_reference.cpp:122:21:122:38 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:122:27:122:38 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:123:21:123:36 | * ... [post update] [a] | semmle.label | * ... [post update] [a] | -| by_reference.cpp:123:22:123:26 | outer [post update] [inner_ptr, a] | semmle.label | outer [post update] [inner_ptr, a] | -| by_reference.cpp:123:28:123:36 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| by_reference.cpp:124:15:124:19 | outer [post update] [a] | semmle.label | outer [post update] [a] | -| by_reference.cpp:124:15:124:21 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:124:21:124:21 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:126:21:126:40 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:126:29:126:40 | inner_nested [post update] [a] | semmle.label | inner_nested [post update] [a] | -| by_reference.cpp:127:21:127:38 | * ... [post update] [a] | semmle.label | * ... [post update] [a] | -| by_reference.cpp:127:30:127:38 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| by_reference.cpp:128:15:128:23 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:128:23:128:23 | a [post update] | semmle.label | a [post update] | -| by_reference.cpp:130:8:130:12 | outer [read] [inner_nested, a] | semmle.label | outer [read] [inner_nested, a] | -| by_reference.cpp:130:14:130:25 | inner_nested [read] [a] | semmle.label | inner_nested [read] [a] | +| by_reference.cpp:116:16:116:16 | a indirection | semmle.label | a indirection | +| by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | +| by_reference.cpp:122:27:122:38 | outer indirection [post update] [inner_nested, a] | semmle.label | outer indirection [post update] [inner_nested, a] | +| by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | +| by_reference.cpp:123:28:123:36 | outer indirection [post update] [inner_ptr indirection, a] | semmle.label | outer indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:124:15:124:21 | taint_a_ref output argument | semmle.label | taint_a_ref output argument | +| by_reference.cpp:124:21:124:21 | outer indirection [post update] [a] | semmle.label | outer indirection [post update] [a] | +| by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | +| by_reference.cpp:126:29:126:40 | pouter indirection [post update] [inner_nested, a] | semmle.label | pouter indirection [post update] [inner_nested, a] | +| by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | semmle.label | taint_inner_a_ref output argument [a] | +| by_reference.cpp:127:30:127:38 | pouter indirection [post update] [inner_ptr indirection, a] | semmle.label | pouter indirection [post update] [inner_ptr indirection, a] | +| by_reference.cpp:128:15:128:23 | taint_a_ref output argument | semmle.label | taint_a_ref output argument | +| by_reference.cpp:128:23:128:23 | pouter indirection [post update] [a] | semmle.label | pouter indirection [post update] [a] | +| by_reference.cpp:130:8:130:12 | outer indirection [inner_nested, a] | semmle.label | outer indirection [inner_nested, a] | +| by_reference.cpp:130:14:130:25 | inner_nested indirection [a] | semmle.label | inner_nested indirection [a] | | by_reference.cpp:130:27:130:27 | a | semmle.label | a | -| by_reference.cpp:131:8:131:12 | outer [read] [inner_ptr, a] | semmle.label | outer [read] [inner_ptr, a] | -| by_reference.cpp:131:14:131:22 | inner_ptr [read] [a] | semmle.label | inner_ptr [read] [a] | +| by_reference.cpp:130:27:130:27 | a indirection | semmle.label | a indirection | +| by_reference.cpp:131:8:131:12 | outer indirection [inner_ptr indirection, a] | semmle.label | outer indirection [inner_ptr indirection, a] | +| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | +| by_reference.cpp:131:14:131:22 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | | by_reference.cpp:131:25:131:25 | a | semmle.label | a | -| by_reference.cpp:132:8:132:12 | outer [read] [a] | semmle.label | outer [read] [a] | +| by_reference.cpp:131:25:131:25 | a indirection | semmle.label | a indirection | +| by_reference.cpp:132:8:132:12 | outer indirection [a] | semmle.label | outer indirection [a] | | by_reference.cpp:132:14:132:14 | a | semmle.label | a | -| by_reference.cpp:134:8:134:13 | pouter [read] [inner_nested, a] | semmle.label | pouter [read] [inner_nested, a] | -| by_reference.cpp:134:16:134:27 | inner_nested [read] [a] | semmle.label | inner_nested [read] [a] | +| by_reference.cpp:132:14:132:14 | a indirection | semmle.label | a indirection | +| by_reference.cpp:134:8:134:13 | pouter indirection [inner_nested, a] | semmle.label | pouter indirection [inner_nested, a] | +| by_reference.cpp:134:16:134:27 | inner_nested indirection [a] | semmle.label | inner_nested indirection [a] | | by_reference.cpp:134:29:134:29 | a | semmle.label | a | -| by_reference.cpp:135:8:135:13 | pouter [read] [inner_ptr, a] | semmle.label | pouter [read] [inner_ptr, a] | -| by_reference.cpp:135:16:135:24 | inner_ptr [read] [a] | semmle.label | inner_ptr [read] [a] | +| by_reference.cpp:134:29:134:29 | a indirection | semmle.label | a indirection | +| by_reference.cpp:135:8:135:13 | pouter indirection [inner_ptr indirection, a] | semmle.label | pouter indirection [inner_ptr indirection, a] | +| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | +| by_reference.cpp:135:16:135:24 | inner_ptr indirection [a] | semmle.label | inner_ptr indirection [a] | | by_reference.cpp:135:27:135:27 | a | semmle.label | a | -| by_reference.cpp:136:8:136:13 | pouter [read] [a] | semmle.label | pouter [read] [a] | +| by_reference.cpp:135:27:135:27 | a indirection | semmle.label | a indirection | +| by_reference.cpp:136:8:136:13 | pouter indirection [a] | semmle.label | pouter indirection [a] | | by_reference.cpp:136:16:136:16 | a | semmle.label | a | -| complex.cpp:9:7:9:7 | ReturnValue | semmle.label | ReturnValue | -| complex.cpp:9:7:9:7 | this [a_] | semmle.label | this [a_] | -| complex.cpp:9:20:9:21 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| complex.cpp:9:20:9:21 | this [read] [a_] | semmle.label | this [read] [a_] | -| complex.cpp:10:7:10:7 | ReturnValue | semmle.label | ReturnValue | -| complex.cpp:10:7:10:7 | this [b_] | semmle.label | this [b_] | -| complex.cpp:10:20:10:21 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| complex.cpp:10:20:10:21 | this [read] [b_] | semmle.label | this [read] [b_] | +| by_reference.cpp:136:16:136:16 | a indirection | semmle.label | a indirection | +| complex.cpp:9:7:9:7 | a indirection | semmle.label | a indirection | +| complex.cpp:9:7:9:7 | this indirection [a_] | semmle.label | this indirection [a_] | +| complex.cpp:9:20:9:21 | a_ | semmle.label | a_ | +| complex.cpp:9:20:9:21 | a_ indirection | semmle.label | a_ indirection | +| complex.cpp:9:20:9:21 | this indirection [a_] | semmle.label | this indirection [a_] | +| complex.cpp:10:7:10:7 | b indirection | semmle.label | b indirection | +| complex.cpp:10:7:10:7 | this indirection [b_] | semmle.label | this indirection [b_] | +| complex.cpp:10:20:10:21 | b_ | semmle.label | b_ | +| complex.cpp:10:20:10:21 | b_ indirection | semmle.label | b_ indirection | +| complex.cpp:10:20:10:21 | this indirection [b_] | semmle.label | this indirection [b_] | | complex.cpp:11:17:11:17 | a | semmle.label | a | -| complex.cpp:11:22:11:23 | a_ [post update] | semmle.label | a_ [post update] | +| complex.cpp:11:22:11:23 | this indirection [post update] [a_] | semmle.label | this indirection [post update] [a_] | +| complex.cpp:11:22:11:27 | ... = ... | semmle.label | ... = ... | | complex.cpp:12:17:12:17 | b | semmle.label | b | -| complex.cpp:12:22:12:23 | b_ [post update] | semmle.label | b_ [post update] | -| complex.cpp:40:17:40:17 | *b [inner, f, a_] | semmle.label | *b [inner, f, a_] | -| complex.cpp:40:17:40:17 | *b [inner, f, b_] | semmle.label | *b [inner, f, b_] | -| complex.cpp:42:8:42:8 | (reference dereference) [read] [inner, f, a_] | semmle.label | (reference dereference) [read] [inner, f, a_] | -| complex.cpp:42:10:42:14 | inner [read] [f, a_] | semmle.label | inner [read] [f, a_] | -| complex.cpp:42:16:42:16 | f [a_] | semmle.label | f [a_] | -| complex.cpp:42:16:42:16 | f [read] [a_] | semmle.label | f [read] [a_] | +| complex.cpp:12:22:12:23 | this indirection [post update] [b_] | semmle.label | this indirection [post update] [b_] | +| complex.cpp:12:22:12:27 | ... = ... | semmle.label | ... = ... | +| complex.cpp:40:17:40:17 | b indirection [inner, f, a_] | semmle.label | b indirection [inner, f, a_] | +| complex.cpp:40:17:40:17 | b indirection [inner, f, b_] | semmle.label | b indirection [inner, f, b_] | +| complex.cpp:42:8:42:8 | b indirection [inner, f, a_] | semmle.label | b indirection [inner, f, a_] | +| complex.cpp:42:10:42:14 | inner indirection [f, a_] | semmle.label | inner indirection [f, a_] | +| complex.cpp:42:16:42:16 | f indirection [a_] | semmle.label | f indirection [a_] | | complex.cpp:42:18:42:18 | call to a | semmle.label | call to a | -| complex.cpp:43:8:43:8 | (reference dereference) [read] [inner, f, b_] | semmle.label | (reference dereference) [read] [inner, f, b_] | -| complex.cpp:43:10:43:14 | inner [read] [f, b_] | semmle.label | inner [read] [f, b_] | -| complex.cpp:43:16:43:16 | f [b_] | semmle.label | f [b_] | -| complex.cpp:43:16:43:16 | f [read] [b_] | semmle.label | f [read] [b_] | +| complex.cpp:43:8:43:8 | b indirection [inner, f, b_] | semmle.label | b indirection [inner, f, b_] | +| complex.cpp:43:10:43:14 | inner indirection [f, b_] | semmle.label | inner indirection [f, b_] | +| complex.cpp:43:16:43:16 | f indirection [b_] | semmle.label | f indirection [b_] | | complex.cpp:43:18:43:18 | call to b | semmle.label | call to b | -| complex.cpp:53:3:53:4 | b1 [post update] [inner, f, a_] | semmle.label | b1 [post update] [inner, f, a_] | -| complex.cpp:53:6:53:10 | inner [post update] [f, a_] | semmle.label | inner [post update] [f, a_] | -| complex.cpp:53:12:53:12 | f [post update] [a_] | semmle.label | f [post update] [a_] | -| complex.cpp:53:12:53:12 | f [post update] [a_] | semmle.label | f [post update] [a_] | +| complex.cpp:53:6:53:10 | b1 indirection [post update] [inner, f, a_] | semmle.label | b1 indirection [post update] [inner, f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:53:12:53:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:53:12:53:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:53:19:53:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:54:3:54:4 | b2 [post update] [inner, f, b_] | semmle.label | b2 [post update] [inner, f, b_] | -| complex.cpp:54:6:54:10 | inner [post update] [f, b_] | semmle.label | inner [post update] [f, b_] | -| complex.cpp:54:12:54:12 | f [post update] [b_] | semmle.label | f [post update] [b_] | -| complex.cpp:54:12:54:12 | f [post update] [b_] | semmle.label | f [post update] [b_] | +| complex.cpp:54:6:54:10 | b2 indirection [post update] [inner, f, b_] | semmle.label | b2 indirection [post update] [inner, f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:54:12:54:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:54:12:54:12 | setB output argument [b_] | semmle.label | setB output argument [b_] | | complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:54:19:54:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:55:3:55:4 | b3 [post update] [inner, f, a_] | semmle.label | b3 [post update] [inner, f, a_] | -| complex.cpp:55:6:55:10 | inner [post update] [f, a_] | semmle.label | inner [post update] [f, a_] | -| complex.cpp:55:12:55:12 | f [post update] [a_] | semmle.label | f [post update] [a_] | -| complex.cpp:55:12:55:12 | f [post update] [a_] | semmle.label | f [post update] [a_] | +| complex.cpp:55:6:55:10 | b3 indirection [post update] [inner, f, a_] | semmle.label | b3 indirection [post update] [inner, f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:55:12:55:12 | inner indirection [post update] [f, a_] | semmle.label | inner indirection [post update] [f, a_] | +| complex.cpp:55:12:55:12 | setA output argument [a_] | semmle.label | setA output argument [a_] | | complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:55:19:55:28 | call to user_input | semmle.label | call to user_input | -| complex.cpp:56:3:56:4 | b3 [post update] [inner, f, b_] | semmle.label | b3 [post update] [inner, f, b_] | -| complex.cpp:56:6:56:10 | inner [post update] [f, b_] | semmle.label | inner [post update] [f, b_] | -| complex.cpp:56:12:56:12 | f [post update] [b_] | semmle.label | f [post update] [b_] | -| complex.cpp:56:12:56:12 | f [post update] [b_] | semmle.label | f [post update] [b_] | -| complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | +| complex.cpp:56:6:56:10 | b3 indirection [post update] [inner, f, b_] | semmle.label | b3 indirection [post update] [inner, f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:56:12:56:12 | inner indirection [post update] [f, b_] | semmle.label | inner indirection [post update] [f, b_] | +| complex.cpp:56:12:56:12 | setB output argument [b_] | semmle.label | setB output argument [b_] | | complex.cpp:56:19:56:28 | call to user_input | semmle.label | call to user_input | | complex.cpp:59:7:59:8 | b1 indirection [inner, f, a_] | semmle.label | b1 indirection [inner, f, a_] | | complex.cpp:62:7:62:8 | b2 indirection [inner, f, b_] | semmle.label | b2 indirection [inner, f, b_] | | complex.cpp:65:7:65:8 | b3 indirection [inner, f, a_] | semmle.label | b3 indirection [inner, f, a_] | | complex.cpp:65:7:65:8 | b3 indirection [inner, f, b_] | semmle.label | b3 indirection [inner, f, b_] | -| conflated.cpp:10:7:10:7 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| conflated.cpp:10:3:10:22 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:10:7:10:7 | ra indirection [post update] [p indirection] | semmle.label | ra indirection [post update] [p indirection] | | conflated.cpp:10:11:10:20 | call to user_input | semmle.label | call to user_input | | conflated.cpp:11:8:11:12 | * ... | semmle.label | * ... | -| conflated.cpp:11:9:11:10 | (reference dereference) [read] [p] | semmle.label | (reference dereference) [read] [p] | +| conflated.cpp:11:9:11:10 | ra indirection [p indirection] | semmle.label | ra indirection [p indirection] | +| conflated.cpp:11:12:11:12 | p indirection | semmle.label | p indirection | +| conflated.cpp:11:12:11:12 | p indirection | semmle.label | p indirection | | conflated.cpp:19:19:19:21 | argument_source output argument | semmle.label | argument_source output argument | -| conflated.cpp:20:8:20:10 | (void *)... | semmle.label | (void *)... | -| conflated.cpp:20:8:20:10 | raw | semmle.label | raw | -| conflated.cpp:29:7:29:7 | x [post update] | semmle.label | x [post update] | +| conflated.cpp:20:8:20:10 | raw indirection | semmle.label | raw indirection | +| conflated.cpp:20:8:20:10 | raw indirection | semmle.label | raw indirection | +| conflated.cpp:20:8:20:10 | raw indirection | semmle.label | raw indirection | +| conflated.cpp:29:3:29:22 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:29:7:29:7 | pa indirection [post update] [x] | semmle.label | pa indirection [post update] [x] | | conflated.cpp:29:11:29:20 | call to user_input | semmle.label | call to user_input | -| conflated.cpp:30:8:30:9 | pa [read] [x] | semmle.label | pa [read] [x] | -| conflated.cpp:30:12:30:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| conflated.cpp:30:8:30:9 | pa indirection [x] | semmle.label | pa indirection [x] | | conflated.cpp:30:12:30:12 | x | semmle.label | x | -| conflated.cpp:36:7:36:7 | x [post update] | semmle.label | x [post update] | +| conflated.cpp:30:12:30:12 | x indirection | semmle.label | x indirection | +| conflated.cpp:36:3:36:22 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:36:7:36:7 | pa indirection [post update] [x] | semmle.label | pa indirection [post update] [x] | | conflated.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input | -| conflated.cpp:37:8:37:9 | pa [read] [x] | semmle.label | pa [read] [x] | -| conflated.cpp:37:12:37:12 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| conflated.cpp:37:8:37:9 | pa indirection [x] | semmle.label | pa indirection [x] | | conflated.cpp:37:12:37:12 | x | semmle.label | x | -| conflated.cpp:54:7:54:10 | FieldAddress [post update] [y] | semmle.label | FieldAddress [post update] [y] | -| conflated.cpp:54:13:54:13 | y [post update] | semmle.label | y [post update] | +| conflated.cpp:37:12:37:12 | x indirection | semmle.label | x indirection | +| conflated.cpp:54:3:54:28 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:54:7:54:10 | ll indirection [post update] [next indirection, y] | semmle.label | ll indirection [post update] [next indirection, y] | +| conflated.cpp:54:13:54:13 | next indirection [post update] [y] | semmle.label | next indirection [post update] [y] | | conflated.cpp:54:17:54:26 | call to user_input | semmle.label | call to user_input | -| conflated.cpp:55:8:55:9 | ll [read] [next, y] | semmle.label | ll [read] [next, y] | -| conflated.cpp:55:12:55:15 | next [read] [y] | semmle.label | next [read] [y] | -| conflated.cpp:55:18:55:18 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| conflated.cpp:55:8:55:9 | ll indirection [next indirection, y] | semmle.label | ll indirection [next indirection, y] | +| conflated.cpp:55:12:55:15 | next indirection [y] | semmle.label | next indirection [y] | +| conflated.cpp:55:12:55:15 | next indirection [y] | semmle.label | next indirection [y] | | conflated.cpp:55:18:55:18 | y | semmle.label | y | -| conflated.cpp:60:7:60:10 | FieldAddress [post update] [y] | semmle.label | FieldAddress [post update] [y] | -| conflated.cpp:60:13:60:13 | y [post update] | semmle.label | y [post update] | +| conflated.cpp:55:18:55:18 | y indirection | semmle.label | y indirection | +| conflated.cpp:60:3:60:28 | ... = ... | semmle.label | ... = ... | +| conflated.cpp:60:7:60:10 | ll indirection [post update] [next indirection, y] | semmle.label | ll indirection [post update] [next indirection, y] | +| conflated.cpp:60:13:60:13 | next indirection [post update] [y] | semmle.label | next indirection [post update] [y] | | conflated.cpp:60:17:60:26 | call to user_input | semmle.label | call to user_input | -| conflated.cpp:61:8:61:9 | ll [read] [next, y] | semmle.label | ll [read] [next, y] | -| conflated.cpp:61:12:61:15 | next [read] [y] | semmle.label | next [read] [y] | -| conflated.cpp:61:18:61:18 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| conflated.cpp:61:8:61:9 | ll indirection [next indirection, y] | semmle.label | ll indirection [next indirection, y] | +| conflated.cpp:61:12:61:15 | next indirection [y] | semmle.label | next indirection [y] | +| conflated.cpp:61:12:61:15 | next indirection [y] | semmle.label | next indirection [y] | | conflated.cpp:61:18:61:18 | y | semmle.label | y | -| constructors.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] | -| constructors.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] | -| constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | semmle.label | ReturnIndirection [b_] | -| constructors.cpp:18:9:18:9 | ReturnValue | semmle.label | ReturnValue | -| constructors.cpp:18:22:18:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| constructors.cpp:18:22:18:23 | this [read] [a_] | semmle.label | this [read] [a_] | -| constructors.cpp:19:9:19:9 | ReturnValue | semmle.label | ReturnValue | -| constructors.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] | -| constructors.cpp:19:22:19:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| constructors.cpp:19:22:19:23 | this [read] [b_] | semmle.label | this [read] [b_] | -| constructors.cpp:23:5:23:7 | this [post update] [a_] | semmle.label | this [post update] [a_] | -| constructors.cpp:23:5:23:7 | this [post update] [b_] | semmle.label | this [post update] [b_] | +| conflated.cpp:61:18:61:18 | y indirection | semmle.label | y indirection | +| constructors.cpp:18:9:18:9 | a indirection | semmle.label | a indirection | +| constructors.cpp:18:9:18:9 | this indirection [a_] | semmle.label | this indirection [a_] | +| constructors.cpp:18:22:18:23 | a_ | semmle.label | a_ | +| constructors.cpp:18:22:18:23 | a_ indirection | semmle.label | a_ indirection | +| constructors.cpp:18:22:18:23 | this indirection [a_] | semmle.label | this indirection [a_] | +| constructors.cpp:19:9:19:9 | b indirection | semmle.label | b indirection | +| constructors.cpp:19:9:19:9 | this indirection [b_] | semmle.label | this indirection [b_] | +| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ | +| constructors.cpp:19:22:19:23 | b_ indirection | semmle.label | b_ indirection | +| constructors.cpp:19:22:19:23 | this indirection [b_] | semmle.label | this indirection [b_] | | constructors.cpp:23:13:23:13 | a | semmle.label | a | | constructors.cpp:23:20:23:20 | b | semmle.label | b | -| constructors.cpp:23:25:23:29 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| constructors.cpp:23:32:23:36 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | -| constructors.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | -| constructors.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | -| constructors.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | +| constructors.cpp:23:25:23:29 | this indirection [post update] [a_] | semmle.label | this indirection [post update] [a_] | +| constructors.cpp:23:28:23:28 | a | semmle.label | a | +| constructors.cpp:23:32:23:36 | this indirection [post update] [b_] | semmle.label | this indirection [post update] [b_] | +| constructors.cpp:23:35:23:35 | b | semmle.label | b | +| constructors.cpp:26:15:26:15 | f indirection [a_] | semmle.label | f indirection [a_] | +| constructors.cpp:26:15:26:15 | f indirection [b_] | semmle.label | f indirection [b_] | | constructors.cpp:28:10:28:10 | f indirection [a_] | semmle.label | f indirection [a_] | -| constructors.cpp:28:10:28:10 | f indirection [b_] | semmle.label | f indirection [b_] | | constructors.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| constructors.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] | +| constructors.cpp:29:10:29:10 | f indirection [b_] | semmle.label | f indirection [b_] | | constructors.cpp:29:12:29:12 | call to b | semmle.label | call to b | -| constructors.cpp:34:9:34:9 | Argument this [post update] [a_] | semmle.label | Argument this [post update] [a_] | +| constructors.cpp:34:9:34:9 | call to Foo [a_] | semmle.label | call to Foo [a_] | | constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:34:11:34:20 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:35:9:35:9 | Argument this [post update] [b_] | semmle.label | Argument this [post update] [b_] | +| constructors.cpp:35:9:35:9 | call to Foo [b_] | semmle.label | call to Foo [b_] | | constructors.cpp:35:14:35:23 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:35:14:35:23 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:36:9:36:9 | Argument this [post update] [a_] | semmle.label | Argument this [post update] [a_] | -| constructors.cpp:36:9:36:9 | Argument this [post update] [b_] | semmle.label | Argument this [post update] [b_] | +| constructors.cpp:36:9:36:9 | call to Foo [a_] | semmle.label | call to Foo [a_] | +| constructors.cpp:36:9:36:9 | call to Foo [b_] | semmle.label | call to Foo [b_] | | constructors.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:36:11:36:20 | call to user_input | semmle.label | call to user_input | -| constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input | | constructors.cpp:36:25:36:34 | call to user_input | semmle.label | call to user_input | | constructors.cpp:40:9:40:9 | f indirection [a_] | semmle.label | f indirection [a_] | | constructors.cpp:43:9:43:9 | g indirection [b_] | semmle.label | g indirection [b_] | | constructors.cpp:46:9:46:9 | h indirection [a_] | semmle.label | h indirection [a_] | | constructors.cpp:46:9:46:9 | h indirection [b_] | semmle.label | h indirection [b_] | | qualifiers.cpp:9:21:9:25 | value | semmle.label | value | -| qualifiers.cpp:9:36:9:36 | a [post update] | semmle.label | a [post update] | +| qualifiers.cpp:9:30:9:44 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:9:36:9:36 | this indirection [post update] [a] | semmle.label | this indirection [post update] [a] | | qualifiers.cpp:12:40:12:44 | value | semmle.label | value | -| qualifiers.cpp:12:56:12:56 | a [post update] | semmle.label | a [post update] | +| qualifiers.cpp:12:49:12:64 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:12:56:12:56 | inner indirection [post update] [a] | semmle.label | inner indirection [post update] [a] | | qualifiers.cpp:13:42:13:46 | value | semmle.label | value | -| qualifiers.cpp:13:57:13:57 | a [post update] | semmle.label | a [post update] | -| qualifiers.cpp:22:5:22:9 | outer [post update] [inner, a] | semmle.label | outer [post update] [inner, a] | -| qualifiers.cpp:22:23:22:23 | a [post update] | semmle.label | a [post update] | +| qualifiers.cpp:13:51:13:65 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:13:57:13:57 | inner indirection [post update] [a] | semmle.label | inner indirection [post update] [a] | +| qualifiers.cpp:22:5:22:9 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | +| qualifiers.cpp:22:5:22:38 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:22:23:22:23 | call to getInner indirection [post update] [a] | semmle.label | call to getInner indirection [post update] [a] | | qualifiers.cpp:22:27:22:36 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:23:10:23:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:23:16:23:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:23:10:23:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:23:16:23:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:23:16:23:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:23:23:23:23 | a | semmle.label | a | -| qualifiers.cpp:27:5:27:9 | outer [post update] [inner, a] | semmle.label | outer [post update] [inner, a] | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] | -| qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] | +| qualifiers.cpp:23:23:23:23 | a indirection | semmle.label | a indirection | +| qualifiers.cpp:27:5:27:9 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | +| qualifiers.cpp:27:11:27:18 | setA output argument [a] | semmle.label | setA output argument [a] | | qualifiers.cpp:27:28:27:37 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:27:28:27:37 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:28:10:28:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:28:16:28:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:28:10:28:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:28:16:28:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:28:16:28:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:28:23:28:23 | a | semmle.label | a | -| qualifiers.cpp:32:17:32:21 | outer [post update] [inner, a] | semmle.label | outer [post update] [inner, a] | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] | -| qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | semmle.label | call to getInner [post update] [a] | +| qualifiers.cpp:28:23:28:23 | a indirection | semmle.label | a indirection | +| qualifiers.cpp:32:17:32:21 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | +| qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] | semmle.label | pointerSetA output argument [a] | | qualifiers.cpp:32:35:32:44 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:32:35:32:44 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:33:10:33:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:33:16:33:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:33:10:33:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:33:16:33:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:33:16:33:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:33:23:33:23 | a | semmle.label | a | -| qualifiers.cpp:37:19:37:35 | * ... [post update] [a] | semmle.label | * ... [post update] [a] | -| qualifiers.cpp:37:20:37:24 | outer [post update] [inner, a] | semmle.label | outer [post update] [inner, a] | +| qualifiers.cpp:33:23:33:23 | a indirection | semmle.label | a indirection | +| qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] | semmle.label | referenceSetA output argument [a] | +| qualifiers.cpp:37:20:37:24 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | | qualifiers.cpp:37:38:37:47 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:37:38:37:47 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:38:10:38:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:38:16:38:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:38:10:38:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:38:16:38:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:38:16:38:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:38:23:38:23 | a | semmle.label | a | -| qualifiers.cpp:42:7:42:11 | outer [post update] [inner, a] | semmle.label | outer [post update] [inner, a] | -| qualifiers.cpp:42:25:42:25 | a [post update] | semmle.label | a [post update] | +| qualifiers.cpp:38:23:38:23 | a indirection | semmle.label | a indirection | +| qualifiers.cpp:42:5:42:40 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:42:7:42:11 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | +| qualifiers.cpp:42:25:42:25 | * ... indirection [post update] [a] | semmle.label | * ... indirection [post update] [a] | | qualifiers.cpp:42:29:42:38 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:43:10:43:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:43:16:43:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:43:10:43:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:43:16:43:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:43:16:43:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:43:23:43:23 | a | semmle.label | a | -| qualifiers.cpp:47:6:47:11 | & ... [post update] [inner, a] | semmle.label | & ... [post update] [inner, a] | -| qualifiers.cpp:47:27:47:27 | a [post update] | semmle.label | a [post update] | +| qualifiers.cpp:43:23:43:23 | a indirection | semmle.label | a indirection | +| qualifiers.cpp:47:5:47:42 | ... = ... | semmle.label | ... = ... | +| qualifiers.cpp:47:6:47:11 | getInner output argument [inner indirection, a] | semmle.label | getInner output argument [inner indirection, a] | +| qualifiers.cpp:47:27:47:27 | call to getInner indirection [post update] [a] | semmle.label | call to getInner indirection [post update] [a] | | qualifiers.cpp:47:31:47:40 | call to user_input | semmle.label | call to user_input | -| qualifiers.cpp:48:10:48:14 | outer [read] [inner, a] | semmle.label | outer [read] [inner, a] | -| qualifiers.cpp:48:16:48:20 | inner [read] [a] | semmle.label | inner [read] [a] | +| qualifiers.cpp:48:10:48:14 | outer indirection [inner indirection, a] | semmle.label | outer indirection [inner indirection, a] | +| qualifiers.cpp:48:16:48:20 | inner indirection [a] | semmle.label | inner indirection [a] | +| qualifiers.cpp:48:16:48:20 | inner indirection [a] | semmle.label | inner indirection [a] | | qualifiers.cpp:48:23:48:23 | a | semmle.label | a | -| realistic.cpp:53:9:53:11 | foo [post update] [bar, baz, userInput, bufferLen] | semmle.label | foo [post update] [bar, baz, userInput, bufferLen] | -| realistic.cpp:53:13:53:15 | bar [post update] [baz, userInput, bufferLen] | semmle.label | bar [post update] [baz, userInput, bufferLen] | -| realistic.cpp:53:20:53:22 | FieldAddress [post update] [userInput, bufferLen] | semmle.label | FieldAddress [post update] [userInput, bufferLen] | -| realistic.cpp:53:25:53:33 | userInput [post update] [bufferLen] | semmle.label | userInput [post update] [bufferLen] | -| realistic.cpp:53:35:53:43 | bufferLen [post update] | semmle.label | bufferLen [post update] | -| realistic.cpp:53:47:53:66 | (size_t)... | semmle.label | (size_t)... | +| qualifiers.cpp:48:23:48:23 | a indirection | semmle.label | a indirection | +| realistic.cpp:53:9:53:66 | ... = ... | semmle.label | ... = ... | +| realistic.cpp:53:13:53:15 | foo indirection [post update] [bar, baz indirection, userInput, bufferLen] | semmle.label | foo indirection [post update] [bar, baz indirection, userInput, bufferLen] | +| realistic.cpp:53:20:53:22 | access to array indirection [post update] [baz indirection, userInput, bufferLen] | semmle.label | access to array indirection [post update] [baz indirection, userInput, bufferLen] | +| realistic.cpp:53:25:53:33 | baz indirection [post update] [userInput, bufferLen] | semmle.label | baz indirection [post update] [userInput, bufferLen] | +| realistic.cpp:53:35:53:43 | userInput indirection [post update] [bufferLen] | semmle.label | userInput indirection [post update] [bufferLen] | +| realistic.cpp:53:47:53:66 | call to user_input | semmle.label | call to user_input | | realistic.cpp:53:55:53:64 | call to user_input | semmle.label | call to user_input | -| realistic.cpp:61:14:61:55 | (void *)... | semmle.label | (void *)... | -| realistic.cpp:61:21:61:23 | foo [read] [bar, baz, userInput, bufferLen] | semmle.label | foo [read] [bar, baz, userInput, bufferLen] | -| realistic.cpp:61:21:61:30 | access to array [read] [baz, userInput, bufferLen] | semmle.label | access to array [read] [baz, userInput, bufferLen] | -| realistic.cpp:61:32:61:34 | baz [read] [userInput, bufferLen] | semmle.label | baz [read] [userInput, bufferLen] | -| realistic.cpp:61:37:61:45 | userInput [read] [bufferLen] | semmle.label | userInput [read] [bufferLen] | -| simple.cpp:18:9:18:9 | *#this [a_] | semmle.label | *#this [a_] | -| simple.cpp:18:9:18:9 | *#this [b_] | semmle.label | *#this [b_] | -| simple.cpp:18:9:18:9 | ReturnIndirection [b_] | semmle.label | ReturnIndirection [b_] | -| simple.cpp:18:9:18:9 | ReturnValue | semmle.label | ReturnValue | -| simple.cpp:18:22:18:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| simple.cpp:18:22:18:23 | this [read] [a_] | semmle.label | this [read] [a_] | -| simple.cpp:19:9:19:9 | ReturnValue | semmle.label | ReturnValue | -| simple.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] | -| simple.cpp:19:22:19:23 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| simple.cpp:19:22:19:23 | this [read] [b_] | semmle.label | this [read] [b_] | +| realistic.cpp:61:14:61:55 | bufferLen | semmle.label | bufferLen | +| realistic.cpp:61:21:61:23 | foo indirection [bar, baz indirection, userInput, bufferLen] | semmle.label | foo indirection [bar, baz indirection, userInput, bufferLen] | +| realistic.cpp:61:21:61:30 | access to array indirection [baz indirection, userInput, bufferLen] | semmle.label | access to array indirection [baz indirection, userInput, bufferLen] | +| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | semmle.label | baz indirection [userInput, bufferLen] | +| realistic.cpp:61:32:61:34 | baz indirection [userInput, bufferLen] | semmle.label | baz indirection [userInput, bufferLen] | +| realistic.cpp:61:37:61:45 | userInput indirection [bufferLen] | semmle.label | userInput indirection [bufferLen] | +| realistic.cpp:61:47:61:55 | bufferLen | semmle.label | bufferLen | +| realistic.cpp:61:47:61:55 | bufferLen indirection | semmle.label | bufferLen indirection | +| simple.cpp:18:9:18:9 | a indirection | semmle.label | a indirection | +| simple.cpp:18:9:18:9 | this indirection [a_] | semmle.label | this indirection [a_] | +| simple.cpp:18:22:18:23 | a_ | semmle.label | a_ | +| simple.cpp:18:22:18:23 | a_ indirection | semmle.label | a_ indirection | +| simple.cpp:18:22:18:23 | this indirection [a_] | semmle.label | this indirection [a_] | +| simple.cpp:19:9:19:9 | b indirection | semmle.label | b indirection | +| simple.cpp:19:9:19:9 | this indirection [b_] | semmle.label | this indirection [b_] | +| simple.cpp:19:22:19:23 | b_ | semmle.label | b_ | +| simple.cpp:19:22:19:23 | b_ indirection | semmle.label | b_ indirection | +| simple.cpp:19:22:19:23 | this indirection [b_] | semmle.label | this indirection [b_] | | simple.cpp:20:19:20:19 | a | semmle.label | a | -| simple.cpp:20:24:20:25 | a_ [post update] | semmle.label | a_ [post update] | -| simple.cpp:21:10:21:13 | *#this [a_] | semmle.label | *#this [a_] | -| simple.cpp:21:10:21:13 | ReturnIndirection [a_] | semmle.label | ReturnIndirection [a_] | +| simple.cpp:20:24:20:25 | this indirection [post update] [a_] | semmle.label | this indirection [post update] [a_] | +| simple.cpp:20:24:20:29 | ... = ... | semmle.label | ... = ... | | simple.cpp:21:19:21:19 | b | semmle.label | b | -| simple.cpp:21:24:21:25 | b_ [post update] | semmle.label | b_ [post update] | -| simple.cpp:26:15:26:15 | *f [a_] | semmle.label | *f [a_] | -| simple.cpp:26:15:26:15 | *f [b_] | semmle.label | *f [b_] | -| simple.cpp:28:10:28:10 | a output argument [b_] | semmle.label | a output argument [b_] | +| simple.cpp:21:24:21:25 | this indirection [post update] [b_] | semmle.label | this indirection [post update] [b_] | +| simple.cpp:21:24:21:29 | ... = ... | semmle.label | ... = ... | +| simple.cpp:26:15:26:15 | f indirection [a_] | semmle.label | f indirection [a_] | +| simple.cpp:26:15:26:15 | f indirection [b_] | semmle.label | f indirection [b_] | | simple.cpp:28:10:28:10 | f indirection [a_] | semmle.label | f indirection [a_] | -| simple.cpp:28:10:28:10 | f indirection [b_] | semmle.label | f indirection [b_] | | simple.cpp:28:12:28:12 | call to a | semmle.label | call to a | -| simple.cpp:29:10:29:10 | f [b_] | semmle.label | f [b_] | +| simple.cpp:29:10:29:10 | f indirection [b_] | semmle.label | f indirection [b_] | | simple.cpp:29:12:29:12 | call to b | semmle.label | call to b | -| simple.cpp:39:5:39:5 | f [post update] [a_] | semmle.label | f [post update] [a_] | +| simple.cpp:39:5:39:5 | setA output argument [a_] | semmle.label | setA output argument [a_] | | simple.cpp:39:12:39:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:39:12:39:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:40:5:40:5 | g [post update] [b_] | semmle.label | g [post update] [b_] | +| simple.cpp:40:5:40:5 | setB output argument [b_] | semmle.label | setB output argument [b_] | | simple.cpp:40:12:40:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:40:12:40:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:41:5:41:5 | h [post update] [a_] | semmle.label | h [post update] [a_] | +| simple.cpp:41:5:41:5 | setA output argument [a_] | semmle.label | setA output argument [a_] | | simple.cpp:41:12:41:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:41:12:41:21 | call to user_input | semmle.label | call to user_input | -| simple.cpp:42:5:42:5 | h [post update] [b_] | semmle.label | h [post update] [b_] | -| simple.cpp:42:5:42:5 | h indirection [a_] | semmle.label | h indirection [a_] | -| simple.cpp:42:5:42:5 | setB output argument [a_] | semmle.label | setB output argument [a_] | -| simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input | +| simple.cpp:42:5:42:5 | setB output argument [b_] | semmle.label | setB output argument [b_] | | simple.cpp:42:12:42:21 | call to user_input | semmle.label | call to user_input | | simple.cpp:45:9:45:9 | f indirection [a_] | semmle.label | f indirection [a_] | | simple.cpp:48:9:48:9 | g indirection [b_] | semmle.label | g indirection [b_] | | simple.cpp:51:9:51:9 | h indirection [a_] | semmle.label | h indirection [a_] | | simple.cpp:51:9:51:9 | h indirection [b_] | semmle.label | h indirection [b_] | -| simple.cpp:65:5:65:5 | a [post update] [i] | semmle.label | a [post update] [i] | -| simple.cpp:65:7:65:7 | i [post update] | semmle.label | i [post update] | +| simple.cpp:65:5:65:22 | ... = ... | semmle.label | ... = ... | +| simple.cpp:65:7:65:7 | a indirection [post update] [i] | semmle.label | a indirection [post update] [i] | | simple.cpp:65:11:65:20 | call to user_input | semmle.label | call to user_input | -| simple.cpp:67:10:67:11 | a2 [read] [i] | semmle.label | a2 [read] [i] | -| simple.cpp:67:13:67:13 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| simple.cpp:67:10:67:11 | a2 indirection [i] | semmle.label | a2 indirection [i] | | simple.cpp:67:13:67:13 | i | semmle.label | i | -| simple.cpp:78:9:78:15 | ReturnValue | semmle.label | ReturnValue | -| simple.cpp:78:9:78:15 | this [f2, f1] | semmle.label | this [f2, f1] | -| simple.cpp:79:16:79:17 | f2 [read] [f1] | semmle.label | f2 [read] [f1] | -| simple.cpp:79:16:79:17 | this [read] [f2, f1] | semmle.label | this [read] [f2, f1] | -| simple.cpp:79:19:79:20 | FieldAddress [read] | semmle.label | FieldAddress [read] | -| simple.cpp:83:9:83:10 | f2 [post update] [f1] | semmle.label | f2 [post update] [f1] | -| simple.cpp:83:12:83:13 | f1 [post update] | semmle.label | f1 [post update] | +| simple.cpp:67:13:67:13 | i indirection | semmle.label | i indirection | +| simple.cpp:78:9:78:15 | getf2f1 indirection | semmle.label | getf2f1 indirection | +| simple.cpp:78:9:78:15 | this indirection [f2, f1] | semmle.label | this indirection [f2, f1] | +| simple.cpp:79:16:79:17 | f2 indirection [f1] | semmle.label | f2 indirection [f1] | +| simple.cpp:79:16:79:17 | this indirection [f2, f1] | semmle.label | this indirection [f2, f1] | +| simple.cpp:79:19:79:20 | f1 | semmle.label | f1 | +| simple.cpp:79:19:79:20 | f1 indirection | semmle.label | f1 indirection | +| simple.cpp:83:9:83:10 | this indirection [post update] [f2, f1] | semmle.label | this indirection [post update] [f2, f1] | +| simple.cpp:83:9:83:28 | ... = ... | semmle.label | ... = ... | +| simple.cpp:83:12:83:13 | f2 indirection [post update] [f1] | semmle.label | f2 indirection [post update] [f1] | | simple.cpp:83:17:83:26 | call to user_input | semmle.label | call to user_input | | simple.cpp:84:14:84:20 | call to getf2f1 | semmle.label | call to getf2f1 | -| simple.cpp:84:14:84:20 | this [f2, f1] | semmle.label | this [f2, f1] | -| simple.cpp:92:5:92:5 | a [post update] [i] | semmle.label | a [post update] [i] | -| simple.cpp:92:7:92:7 | i [post update] | semmle.label | i [post update] | +| simple.cpp:84:14:84:20 | this indirection [f2, f1] | semmle.label | this indirection [f2, f1] | +| simple.cpp:92:5:92:22 | ... = ... | semmle.label | ... = ... | +| simple.cpp:92:7:92:7 | a indirection [post update] [i] | semmle.label | a indirection [post update] [i] | | simple.cpp:92:11:92:20 | call to user_input | semmle.label | call to user_input | -| simple.cpp:94:10:94:11 | a2 [read] [i] | semmle.label | a2 [read] [i] | -| simple.cpp:94:13:94:13 | FieldAddress [read] | semmle.label | FieldAddress [read] | +| simple.cpp:94:10:94:11 | a2 indirection [i] | semmle.label | a2 indirection [i] | | simple.cpp:94:13:94:13 | i | semmle.label | i | -| struct_init.c:14:24:14:25 | *ab [a] | semmle.label | *ab [a] | -| struct_init.c:14:24:14:25 | ReturnIndirection [a] | semmle.label | ReturnIndirection [a] | -| struct_init.c:14:24:14:25 | ab [a] | semmle.label | ab [a] | -| struct_init.c:15:8:15:9 | ab [read] [a] | semmle.label | ab [read] [a] | -| struct_init.c:15:8:15:9 | ab [read] [a] | semmle.label | ab [read] [a] | +| simple.cpp:94:13:94:13 | i indirection | semmle.label | i indirection | +| struct_init.c:14:24:14:25 | ab indirection [a] | semmle.label | ab indirection [a] | +| struct_init.c:15:8:15:9 | ab indirection [a] | semmle.label | ab indirection [a] | | struct_init.c:15:12:15:12 | a | semmle.label | a | -| struct_init.c:20:13:20:14 | VariableAddress [post update] [a] | semmle.label | VariableAddress [post update] [a] | -| struct_init.c:20:17:20:36 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| struct_init.c:15:12:15:12 | a indirection | semmle.label | a indirection | +| struct_init.c:20:17:20:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] | | struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | -| struct_init.c:22:8:22:9 | ab [read] [a] | semmle.label | ab [read] [a] | +| struct_init.c:20:20:20:29 | call to user_input | semmle.label | call to user_input | +| struct_init.c:22:8:22:9 | ab indirection [a] | semmle.label | ab indirection [a] | | struct_init.c:22:11:22:11 | a | semmle.label | a | +| struct_init.c:22:11:22:11 | a indirection | semmle.label | a indirection | | struct_init.c:24:10:24:12 | & ... indirection [a] | semmle.label | & ... indirection [a] | -| struct_init.c:24:10:24:12 | absink output argument [a] | semmle.label | absink output argument [a] | -| struct_init.c:26:16:26:20 | VariableAddress [post update] [nestedAB, a] | semmle.label | VariableAddress [post update] [nestedAB, a] | -| struct_init.c:26:16:26:20 | VariableAddress [post update] [pointerAB, a] | semmle.label | VariableAddress [post update] [pointerAB, a] | -| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| struct_init.c:26:23:29:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| struct_init.c:27:5:27:23 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [nestedAB, a] | semmle.label | definition of outer indirection [post update] [nestedAB, a] | +| struct_init.c:26:23:29:3 | definition of outer indirection [post update] [pointerAB indirection, a] | semmle.label | definition of outer indirection [post update] [pointerAB indirection, a] | +| struct_init.c:27:5:27:23 | {...} indirection [post update] [a] | semmle.label | {...} indirection [post update] [a] | | struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | -| struct_init.c:31:8:31:12 | outer [read] [nestedAB, a] | semmle.label | outer [read] [nestedAB, a] | -| struct_init.c:31:14:31:21 | nestedAB [read] [a] | semmle.label | nestedAB [read] [a] | +| struct_init.c:27:7:27:16 | call to user_input | semmle.label | call to user_input | +| struct_init.c:28:5:28:7 | & ... indirection [a] | semmle.label | & ... indirection [a] | +| struct_init.c:31:8:31:12 | outer indirection [nestedAB, a] | semmle.label | outer indirection [nestedAB, a] | +| struct_init.c:31:14:31:21 | nestedAB indirection [a] | semmle.label | nestedAB indirection [a] | | struct_init.c:31:23:31:23 | a | semmle.label | a | -| struct_init.c:33:8:33:12 | outer [read] [pointerAB, a] | semmle.label | outer [read] [pointerAB, a] | -| struct_init.c:33:14:33:22 | pointerAB [read] [a] | semmle.label | pointerAB [read] [a] | +| struct_init.c:31:23:31:23 | a indirection | semmle.label | a indirection | +| struct_init.c:33:8:33:12 | outer indirection [pointerAB indirection, a] | semmle.label | outer indirection [pointerAB indirection, a] | +| struct_init.c:33:14:33:22 | pointerAB indirection [a] | semmle.label | pointerAB indirection [a] | +| struct_init.c:33:14:33:22 | pointerAB indirection [a] | semmle.label | pointerAB indirection [a] | | struct_init.c:33:25:33:25 | a | semmle.label | a | -| struct_init.c:36:10:36:24 | & ... [a] | semmle.label | & ... [a] | -| struct_init.c:36:11:36:15 | outer [read] [nestedAB, a] | semmle.label | outer [read] [nestedAB, a] | -| struct_init.c:40:13:40:14 | VariableAddress [post update] [a] | semmle.label | VariableAddress [post update] [a] | -| struct_init.c:40:17:40:36 | FieldAddress [post update] | semmle.label | FieldAddress [post update] | +| struct_init.c:33:25:33:25 | a indirection | semmle.label | a indirection | +| struct_init.c:36:10:36:24 | & ... indirection [a] | semmle.label | & ... indirection [a] | +| struct_init.c:36:11:36:15 | outer indirection [nestedAB, a] | semmle.label | outer indirection [nestedAB, a] | +| struct_init.c:40:17:40:36 | definition of ab indirection [post update] [a] | semmle.label | definition of ab indirection [post update] [a] | | struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input | -| struct_init.c:41:16:41:20 | VariableAddress [post update] [pointerAB, a] | semmle.label | VariableAddress [post update] [pointerAB, a] | -| struct_init.c:41:23:44:3 | FieldAddress [post update] [a] | semmle.label | FieldAddress [post update] [a] | -| struct_init.c:46:10:46:14 | outer [read] [pointerAB, a] | semmle.label | outer [read] [pointerAB, a] | -| struct_init.c:46:16:46:24 | pointerAB [a] | semmle.label | pointerAB [a] | +| struct_init.c:40:20:40:29 | call to user_input | semmle.label | call to user_input | +| struct_init.c:41:23:44:3 | definition of outer indirection [post update] [pointerAB indirection, a] | semmle.label | definition of outer indirection [post update] [pointerAB indirection, a] | +| struct_init.c:43:5:43:7 | & ... indirection [a] | semmle.label | & ... indirection [a] | +| struct_init.c:46:10:46:14 | outer indirection [pointerAB indirection, a] | semmle.label | outer indirection [pointerAB indirection, a] | +| struct_init.c:46:16:46:24 | pointerAB indirection [a] | semmle.label | pointerAB indirection [a] | +| struct_init.c:46:16:46:24 | pointerAB indirection [a] | semmle.label | pointerAB indirection [a] | subpaths -| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | c [post update] | A.cpp:31:14:31:21 | new [post update] [c] | -| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:29:15:29:18 | ReturnValue [c] | A.cpp:48:12:48:18 | call to make [c] | -| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | c [post update] | A.cpp:55:5:55:5 | b [post update] [c] | -| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:56:13:56:15 | call to get | -| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:56:13:56:15 | call to get | -| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:57:28:57:30 | call to get | -| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:8:28:10 | ReturnValue | A.cpp:57:28:57:30 | call to get | -| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | c [post update] | A.cpp:57:11:57:24 | new [post update] [c] | -| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | ReturnValue [c] | A.cpp:64:10:64:15 | call to setOnB [c] | -| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | A.cpp:78:6:78:15 | ReturnValue [c] | A.cpp:73:10:73:19 | call to setOnBWrap [c] | -| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | ReturnValue [c] | A.cpp:81:10:81:15 | call to setOnB [c] | -| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | c [post update] | A.cpp:90:7:90:8 | b2 [post update] [c] | -| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | c [post update] | A.cpp:126:5:126:5 | b [post update] [c] | -| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:13:143:13 | b [post update] | A.cpp:151:12:151:24 | new [post update] [b] | -| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | head [post update] | A.cpp:160:18:160:60 | new [post update] [head] | -| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] | A.cpp:184:13:184:16 | next [post update] [head] | A.cpp:161:18:161:40 | new [post update] [next, head] | -| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:13:184:16 | next [post update] [next, head] | A.cpp:162:18:162:40 | new [post update] [next, next, head] | -| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:35:13:35:17 | elem1 [post update] | B.cpp:7:16:7:35 | new [post update] [elem1] | -| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:13:46:16 | box1 [post update] [elem1] | B.cpp:8:16:8:27 | new [post update] [box1, elem1] | -| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:36:13:36:17 | elem2 [post update] | B.cpp:16:16:16:38 | new [post update] [elem2] | -| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:13:46:16 | box1 [post update] [elem2] | B.cpp:17:16:17:27 | new [post update] [box1, elem2] | -| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:11:17:17 | ReturnValue [elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:11:10:17 | ReturnValue | D.cpp:22:25:22:31 | call to getElem | -| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:11:10:17 | ReturnValue | D.cpp:22:25:22:31 | call to getElem | -| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | elem [post update] | D.cpp:37:8:37:10 | box [post update] [elem] | -| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | elem [post update] | D.cpp:51:8:51:14 | call to getBox1 [post update] [elem] | -| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | a [post update] | by_reference.cpp:20:5:20:8 | this [post update] [a] | -| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:8:12:8 | a [post update] | by_reference.cpp:24:19:24:22 | this [post update] [a] | -| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:35:9:35:19 | ReturnValue | by_reference.cpp:40:18:40:28 | call to getDirectly | -| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | ReturnValue | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | -| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | a [post update] | by_reference.cpp:50:3:50:3 | s [post update] [a] | -| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | *#this [a] | by_reference.cpp:35:9:35:19 | ReturnValue | by_reference.cpp:51:10:51:20 | call to getDirectly | -| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | this [post update] [a] | by_reference.cpp:56:3:56:3 | s [post update] [a] | -| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | this [post update] [a] | by_reference.cpp:56:3:56:3 | s [post update] [a] | -| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | *#this [a] | by_reference.cpp:39:9:39:21 | ReturnValue | by_reference.cpp:57:10:57:22 | call to getIndirectly | -| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | this [post update] [a] | by_reference.cpp:62:3:62:3 | s [post update] [a] | -| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | this [post update] [a] | by_reference.cpp:62:3:62:3 | s [post update] [a] | -| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | *#this [a] | by_reference.cpp:43:9:43:27 | ReturnValue | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | -| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:8:12:8 | a [post update] | by_reference.cpp:68:17:68:18 | & ... [post update] [a] | -| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | ReturnValue | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | -| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:7:9:7 | ReturnValue | complex.cpp:42:18:42:18 | call to a | -| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:7:10:7 | ReturnValue | complex.cpp:43:18:43:18 | call to b | -| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | a_ [post update] | complex.cpp:53:12:53:12 | f [post update] [a_] | -| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | b_ [post update] | complex.cpp:54:12:54:12 | f [post update] [b_] | -| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | a_ [post update] | complex.cpp:55:12:55:12 | f [post update] [a_] | -| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | b_ [post update] | complex.cpp:56:12:56:12 | f [post update] [b_] | -| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | *#this [a_] | constructors.cpp:18:9:18:9 | ReturnValue | constructors.cpp:28:12:28:12 | call to a | -| constructors.cpp:28:10:28:10 | f indirection [b_] | constructors.cpp:18:9:18:9 | *#this [b_] | constructors.cpp:18:9:18:9 | ReturnIndirection [b_] | constructors.cpp:28:10:28:10 | a output argument [b_] | -| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:9:19:9 | ReturnValue | constructors.cpp:29:12:29:12 | call to b | -| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | this [post update] [a_] | constructors.cpp:34:9:34:9 | Argument this [post update] [a_] | -| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | this [post update] [b_] | constructors.cpp:35:9:35:9 | Argument this [post update] [b_] | -| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | this [post update] [a_] | constructors.cpp:36:9:36:9 | Argument this [post update] [a_] | -| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | this [post update] [b_] | constructors.cpp:36:9:36:9 | Argument this [post update] [b_] | -| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:36:9:36 | a [post update] | qualifiers.cpp:27:11:27:18 | call to getInner [post update] [a] | -| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:56:12:56 | a [post update] | qualifiers.cpp:32:23:32:30 | call to getInner [post update] [a] | -| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:57:13:57 | a [post update] | qualifiers.cpp:37:19:37:35 | * ... [post update] [a] | -| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | *#this [a_] | simple.cpp:18:9:18:9 | ReturnValue | simple.cpp:28:12:28:12 | call to a | -| simple.cpp:28:10:28:10 | f indirection [b_] | simple.cpp:18:9:18:9 | *#this [b_] | simple.cpp:18:9:18:9 | ReturnIndirection [b_] | simple.cpp:28:10:28:10 | a output argument [b_] | -| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:9:19:9 | ReturnValue | simple.cpp:29:12:29:12 | call to b | -| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | a_ [post update] | simple.cpp:39:5:39:5 | f [post update] [a_] | -| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | b_ [post update] | simple.cpp:40:5:40:5 | g [post update] [b_] | -| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | a_ [post update] | simple.cpp:41:5:41:5 | h [post update] [a_] | -| simple.cpp:42:5:42:5 | h indirection [a_] | simple.cpp:21:10:21:13 | *#this [a_] | simple.cpp:21:10:21:13 | ReturnIndirection [a_] | simple.cpp:42:5:42:5 | setB output argument [a_] | -| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | b_ [post update] | simple.cpp:42:5:42:5 | h [post update] [b_] | -| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:78:9:78:15 | ReturnValue | simple.cpp:84:14:84:20 | call to getf2f1 | -| struct_init.c:24:10:24:12 | & ... indirection [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | ReturnIndirection [a] | struct_init.c:24:10:24:12 | absink output argument [a] | +| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | this indirection [post update] [c] | A.cpp:31:14:31:21 | call to B [c] | +| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:29:15:29:18 | make indirection [c] | A.cpp:48:12:48:18 | call to make indirection [c] | +| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | this indirection [post update] [c] | A.cpp:55:5:55:5 | set output argument [c] | +| A.cpp:56:10:56:10 | b indirection [c] | A.cpp:28:8:28:10 | this indirection [c] | A.cpp:28:8:28:10 | get indirection | A.cpp:56:10:56:17 | call to get | +| A.cpp:57:11:57:24 | new indirection [c] | A.cpp:28:8:28:10 | this indirection [c] | A.cpp:28:8:28:10 | get indirection | A.cpp:57:10:57:32 | call to get | +| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:13:25:13 | this indirection [post update] [c] | A.cpp:57:11:57:24 | call to B [c] | +| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | setOnB indirection [c] | A.cpp:64:10:64:15 | call to setOnB indirection [c] | +| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | A.cpp:78:6:78:15 | setOnBWrap indirection [c] | A.cpp:73:10:73:19 | call to setOnBWrap indirection [c] | +| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | setOnB indirection [c] | A.cpp:81:10:81:15 | call to setOnB indirection [c] | +| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | this indirection [post update] [c] | A.cpp:90:7:90:8 | set output argument [c] | +| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:28:27:28 | this indirection [post update] [c] | A.cpp:126:5:126:5 | set output argument [c] | +| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:13:143:13 | this indirection [post update] [b] | A.cpp:151:12:151:24 | call to D [b] | +| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | this indirection [post update] [head] | A.cpp:160:18:160:60 | call to MyList [head] | +| A.cpp:161:38:161:39 | l1 indirection [head] | A.cpp:181:32:181:35 | next indirection [head] | A.cpp:184:13:184:16 | this indirection [post update] [next indirection, head] | A.cpp:161:18:161:40 | call to MyList [next indirection, head] | +| A.cpp:162:38:162:39 | l2 indirection [next indirection, head] | A.cpp:181:32:181:35 | next indirection [next indirection, head] | A.cpp:184:13:184:16 | this indirection [post update] [next indirection, next indirection, head] | A.cpp:162:18:162:40 | call to MyList [next indirection, next indirection, head] | +| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:35:13:35:17 | this indirection [post update] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] | +| B.cpp:8:25:8:26 | b1 indirection [elem1] | B.cpp:44:16:44:17 | b1 indirection [elem1] | B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem1] | B.cpp:8:16:8:27 | call to Box2 [box1 indirection, elem1] | +| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:36:13:36:17 | this indirection [post update] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] | +| B.cpp:17:25:17:26 | b1 indirection [elem2] | B.cpp:44:16:44:17 | b1 indirection [elem2] | B.cpp:46:13:46:16 | this indirection [post update] [box1 indirection, elem2] | B.cpp:17:16:17:27 | call to Box2 [box1 indirection, elem2] | +| D.cpp:22:10:22:11 | b2 indirection [box indirection, elem] | D.cpp:17:11:17:17 | this indirection [box indirection, elem] | D.cpp:17:11:17:17 | getBox1 indirection [elem] | D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | +| D.cpp:22:14:22:20 | call to getBox1 indirection [elem] | D.cpp:10:11:10:17 | this indirection [elem] | D.cpp:10:11:10:17 | getElem indirection | D.cpp:22:10:22:33 | call to getElem | +| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this indirection [post update] [elem] | D.cpp:37:8:37:10 | setElem output argument [elem] | +| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this indirection [post update] [elem] | D.cpp:51:8:51:14 | setElem output argument [elem] | +| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | this indirection [post update] [a] | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | +| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:8:12:8 | s indirection [post update] [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | +| by_reference.cpp:40:12:40:15 | this indirection [a] | by_reference.cpp:35:9:35:19 | this indirection [a] | by_reference.cpp:35:9:35:19 | getDirectly indirection | by_reference.cpp:40:18:40:28 | call to getDirectly | +| by_reference.cpp:44:26:44:29 | this indirection [a] | by_reference.cpp:31:46:31:46 | s indirection [a] | by_reference.cpp:31:16:31:28 | nonMemberGetA indirection | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | +| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:11:16:11 | this indirection [post update] [a] | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] | +| by_reference.cpp:51:8:51:8 | s indirection [a] | by_reference.cpp:35:9:35:19 | this indirection [a] | by_reference.cpp:35:9:35:19 | getDirectly indirection | by_reference.cpp:51:10:51:20 | call to getDirectly | +| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] | +| by_reference.cpp:57:8:57:8 | s indirection [a] | by_reference.cpp:39:9:39:21 | this indirection [a] | by_reference.cpp:39:9:39:21 | getIndirectly indirection | by_reference.cpp:57:10:57:22 | call to getIndirectly | +| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] | +| by_reference.cpp:63:8:63:8 | s indirection [a] | by_reference.cpp:43:9:43:27 | this indirection [a] | by_reference.cpp:43:9:43:27 | getThroughNonMember indirection | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | +| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:8:12:8 | s indirection [post update] [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | +| by_reference.cpp:69:22:69:23 | & ... indirection [a] | by_reference.cpp:31:46:31:46 | s indirection [a] | by_reference.cpp:31:16:31:28 | nonMemberGetA indirection | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | +| complex.cpp:42:16:42:16 | f indirection [a_] | complex.cpp:9:7:9:7 | this indirection [a_] | complex.cpp:9:7:9:7 | a indirection | complex.cpp:42:18:42:18 | call to a | +| complex.cpp:43:16:43:16 | f indirection [b_] | complex.cpp:10:7:10:7 | this indirection [b_] | complex.cpp:10:7:10:7 | b indirection | complex.cpp:43:18:43:18 | call to b | +| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this indirection [post update] [a_] | complex.cpp:53:12:53:12 | setA output argument [a_] | +| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this indirection [post update] [b_] | complex.cpp:54:12:54:12 | setB output argument [b_] | +| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this indirection [post update] [a_] | complex.cpp:55:12:55:12 | setA output argument [a_] | +| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this indirection [post update] [b_] | complex.cpp:56:12:56:12 | setB output argument [b_] | +| constructors.cpp:28:10:28:10 | f indirection [a_] | constructors.cpp:18:9:18:9 | this indirection [a_] | constructors.cpp:18:9:18:9 | a indirection | constructors.cpp:28:12:28:12 | call to a | +| constructors.cpp:29:10:29:10 | f indirection [b_] | constructors.cpp:19:9:19:9 | this indirection [b_] | constructors.cpp:19:9:19:9 | b indirection | constructors.cpp:29:12:29:12 | call to b | +| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | this indirection [post update] [a_] | constructors.cpp:34:9:34:9 | call to Foo [a_] | +| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | this indirection [post update] [b_] | constructors.cpp:35:9:35:9 | call to Foo [b_] | +| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | this indirection [post update] [a_] | constructors.cpp:36:9:36:9 | call to Foo [a_] | +| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | this indirection [post update] [b_] | constructors.cpp:36:9:36:9 | call to Foo [b_] | +| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:36:9:36 | this indirection [post update] [a] | qualifiers.cpp:27:11:27:18 | setA output argument [a] | +| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:56:12:56 | inner indirection [post update] [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] | +| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:57:13:57 | inner indirection [post update] [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] | +| simple.cpp:28:10:28:10 | f indirection [a_] | simple.cpp:18:9:18:9 | this indirection [a_] | simple.cpp:18:9:18:9 | a indirection | simple.cpp:28:12:28:12 | call to a | +| simple.cpp:29:10:29:10 | f indirection [b_] | simple.cpp:19:9:19:9 | this indirection [b_] | simple.cpp:19:9:19:9 | b indirection | simple.cpp:29:12:29:12 | call to b | +| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this indirection [post update] [a_] | simple.cpp:39:5:39:5 | setA output argument [a_] | +| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this indirection [post update] [b_] | simple.cpp:40:5:40:5 | setB output argument [b_] | +| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this indirection [post update] [a_] | simple.cpp:41:5:41:5 | setA output argument [a_] | +| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this indirection [post update] [b_] | simple.cpp:42:5:42:5 | setB output argument [b_] | +| simple.cpp:84:14:84:20 | this indirection [f2, f1] | simple.cpp:78:9:78:15 | this indirection [f2, f1] | simple.cpp:78:9:78:15 | getf2f1 indirection | simple.cpp:84:14:84:20 | call to getf2f1 | #select -| A.cpp:49:10:49:13 | (void *)... | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | (void *)... | (void *)... flows from $@ | A.cpp:47:12:47:18 | new | new | -| A.cpp:56:10:56:17 | (void *)... | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:10:56:17 | (void *)... | (void *)... flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... | -| A.cpp:56:10:56:17 | (void *)... | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | (void *)... | (void *)... flows from $@ | A.cpp:55:12:55:19 | new | new | -| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | (C *)... | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | (C *)... | (C *)... | -| A.cpp:56:13:56:15 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:13:56:15 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new | -| A.cpp:57:10:57:32 | (void *)... | A.cpp:57:17:57:23 | new | A.cpp:57:10:57:32 | (void *)... | (void *)... flows from $@ | A.cpp:57:17:57:23 | new | new | -| A.cpp:57:28:57:30 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:28:57:30 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new | -| A.cpp:66:10:66:14 | (void *)... | A.cpp:64:21:64:28 | (C *)... | A.cpp:66:10:66:14 | (void *)... | (void *)... flows from $@ | A.cpp:64:21:64:28 | (C *)... | (C *)... | -| A.cpp:66:10:66:14 | (void *)... | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | (void *)... | (void *)... flows from $@ | A.cpp:64:21:64:28 | new | new | -| A.cpp:75:10:75:14 | (void *)... | A.cpp:73:25:73:32 | (C *)... | A.cpp:75:10:75:14 | (void *)... | (void *)... flows from $@ | A.cpp:73:25:73:32 | (C *)... | (C *)... | -| A.cpp:75:10:75:14 | (void *)... | A.cpp:73:25:73:32 | new | A.cpp:75:10:75:14 | (void *)... | (void *)... flows from $@ | A.cpp:73:25:73:32 | new | new | -| A.cpp:107:12:107:16 | (void *)... | A.cpp:98:12:98:18 | new | A.cpp:107:12:107:16 | (void *)... | (void *)... flows from $@ | A.cpp:98:12:98:18 | new | new | -| A.cpp:120:12:120:16 | (void *)... | A.cpp:98:12:98:18 | new | A.cpp:120:12:120:16 | (void *)... | (void *)... flows from $@ | A.cpp:98:12:98:18 | new | new | -| A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new | new | -| A.cpp:152:10:152:13 | (void *)... | A.cpp:143:25:143:31 | new | A.cpp:152:10:152:13 | (void *)... | (void *)... flows from $@ | A.cpp:143:25:143:31 | new | new | -| A.cpp:152:10:152:13 | (void *)... | A.cpp:150:12:150:18 | new | A.cpp:152:10:152:13 | (void *)... | (void *)... flows from $@ | A.cpp:150:12:150:18 | new | new | -| A.cpp:153:10:153:16 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:153:10:153:16 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new | -| A.cpp:154:10:154:13 | (void *)... | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | (void *)... | (void *)... flows from $@ | A.cpp:142:14:142:20 | new | new | -| A.cpp:165:10:165:29 | (void *)... | A.cpp:159:12:159:18 | new | A.cpp:165:10:165:29 | (void *)... | (void *)... flows from $@ | A.cpp:159:12:159:18 | new | new | -| A.cpp:169:12:169:18 | (void *)... | A.cpp:159:12:159:18 | new | A.cpp:169:12:169:18 | (void *)... | (void *)... flows from $@ | A.cpp:159:12:159:18 | new | new | -| B.cpp:9:10:9:24 | (void *)... | B.cpp:6:15:6:24 | new | B.cpp:9:10:9:24 | (void *)... | (void *)... flows from $@ | B.cpp:6:15:6:24 | new | new | -| B.cpp:19:10:19:24 | (void *)... | B.cpp:15:15:15:27 | new | B.cpp:19:10:19:24 | (void *)... | (void *)... flows from $@ | B.cpp:15:15:15:27 | new | new | +| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new | +| A.cpp:43:10:43:12 | & ... indirection | A.cpp:41:15:41:21 | new | A.cpp:43:10:43:12 | & ... indirection | & ... indirection flows from $@ | A.cpp:41:15:41:21 | new | new | +| A.cpp:49:10:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:10:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new | +| A.cpp:49:13:49:13 | c | A.cpp:47:12:47:18 | new | A.cpp:49:13:49:13 | c | c flows from $@ | A.cpp:47:12:47:18 | new | new | +| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new | +| A.cpp:56:10:56:17 | call to get | A.cpp:55:12:55:19 | new | A.cpp:56:10:56:17 | call to get | call to get flows from $@ | A.cpp:55:12:55:19 | new | new | +| A.cpp:57:10:57:32 | call to get | A.cpp:57:17:57:23 | new | A.cpp:57:10:57:32 | call to get | call to get flows from $@ | A.cpp:57:17:57:23 | new | new | +| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new | +| A.cpp:66:10:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:10:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new | +| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new | +| A.cpp:66:14:66:14 | c | A.cpp:64:21:64:28 | new | A.cpp:66:14:66:14 | c | c flows from $@ | A.cpp:64:21:64:28 | new | new | +| A.cpp:75:10:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:10:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new | +| A.cpp:75:10:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:10:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new | +| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new | +| A.cpp:75:14:75:14 | c | A.cpp:73:25:73:32 | new | A.cpp:75:14:75:14 | c | c flows from $@ | A.cpp:73:25:73:32 | new | new | +| A.cpp:107:12:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:12:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | +| A.cpp:107:16:107:16 | a | A.cpp:98:12:98:18 | new | A.cpp:107:16:107:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | +| A.cpp:120:12:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:12:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | +| A.cpp:120:16:120:16 | a | A.cpp:98:12:98:18 | new | A.cpp:120:16:120:16 | a | a flows from $@ | A.cpp:98:12:98:18 | new | new | +| A.cpp:132:10:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:10:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new | +| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new | new | +| A.cpp:152:10:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new | +| A.cpp:152:10:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:10:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new | +| A.cpp:152:13:152:13 | b | A.cpp:143:25:143:31 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:143:25:143:31 | new | new | +| A.cpp:152:13:152:13 | b | A.cpp:150:12:150:18 | new | A.cpp:152:13:152:13 | b | b flows from $@ | A.cpp:150:12:150:18 | new | new | +| A.cpp:153:10:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:10:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:153:16:153:16 | c | A.cpp:142:14:142:20 | new | A.cpp:153:16:153:16 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:154:10:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:10:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:154:13:154:13 | c | A.cpp:142:14:142:20 | new | A.cpp:154:13:154:13 | c | c flows from $@ | A.cpp:142:14:142:20 | new | new | +| A.cpp:165:10:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:10:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | +| A.cpp:165:26:165:29 | head | A.cpp:159:12:159:18 | new | A.cpp:165:26:165:29 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | +| A.cpp:169:12:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:12:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | +| A.cpp:169:15:169:18 | head | A.cpp:159:12:159:18 | new | A.cpp:169:15:169:18 | head | head flows from $@ | A.cpp:159:12:159:18 | new | new | +| B.cpp:9:10:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:10:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new | +| B.cpp:9:20:9:24 | elem1 | B.cpp:6:15:6:24 | new | B.cpp:9:20:9:24 | elem1 | elem1 flows from $@ | B.cpp:6:15:6:24 | new | new | +| B.cpp:19:10:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:10:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new | +| B.cpp:19:20:19:24 | elem2 | B.cpp:15:15:15:27 | new | B.cpp:19:20:19:24 | elem2 | elem2 flows from $@ | B.cpp:15:15:15:27 | new | new | | C.cpp:29:10:29:11 | s1 | C.cpp:22:12:22:21 | new | C.cpp:29:10:29:11 | s1 | s1 flows from $@ | C.cpp:22:12:22:21 | new | new | -| D.cpp:22:10:22:33 | (void *)... | D.cpp:28:15:28:24 | new | D.cpp:22:10:22:33 | (void *)... | (void *)... flows from $@ | D.cpp:28:15:28:24 | new | new | -| D.cpp:22:10:22:33 | (void *)... | D.cpp:35:15:35:24 | new | D.cpp:22:10:22:33 | (void *)... | (void *)... flows from $@ | D.cpp:35:15:35:24 | new | new | -| D.cpp:22:10:22:33 | (void *)... | D.cpp:42:15:42:24 | new | D.cpp:22:10:22:33 | (void *)... | (void *)... flows from $@ | D.cpp:42:15:42:24 | new | new | -| D.cpp:22:10:22:33 | (void *)... | D.cpp:49:15:49:24 | new | D.cpp:22:10:22:33 | (void *)... | (void *)... flows from $@ | D.cpp:49:15:49:24 | new | new | -| D.cpp:22:25:22:31 | call to getElem | D.cpp:28:15:28:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:28:15:28:24 | new | new | -| D.cpp:22:25:22:31 | call to getElem | D.cpp:35:15:35:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:35:15:35:24 | new | new | -| D.cpp:22:25:22:31 | call to getElem | D.cpp:42:15:42:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:42:15:42:24 | new | new | -| D.cpp:22:25:22:31 | call to getElem | D.cpp:49:15:49:24 | new | D.cpp:22:25:22:31 | call to getElem | call to getElem flows from $@ | D.cpp:49:15:49:24 | new | new | -| D.cpp:64:10:64:28 | (void *)... | D.cpp:56:15:56:24 | new | D.cpp:64:10:64:28 | (void *)... | (void *)... flows from $@ | D.cpp:56:15:56:24 | new | new | -| E.cpp:21:18:21:23 | buffer | E.cpp:30:21:30:33 | argument_source output argument | E.cpp:21:18:21:23 | buffer | buffer flows from $@ | E.cpp:30:21:30:33 | argument_source output argument | argument_source output argument | -| E.cpp:31:10:31:12 | raw | E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw | raw flows from $@ | E.cpp:28:21:28:23 | argument_source output argument | argument_source output argument | -| E.cpp:32:13:32:18 | buffer | E.cpp:29:21:29:29 | argument_source output argument | E.cpp:32:13:32:18 | buffer | buffer flows from $@ | E.cpp:29:21:29:29 | argument_source output argument | argument_source output argument | +| C.cpp:31:10:31:11 | s3 | C.cpp:24:16:24:25 | new | C.cpp:31:10:31:11 | s3 | s3 flows from $@ | C.cpp:24:16:24:25 | new | new | +| D.cpp:22:10:22:33 | call to getElem | D.cpp:28:15:28:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:28:15:28:24 | new | new | +| D.cpp:22:10:22:33 | call to getElem | D.cpp:35:15:35:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:35:15:35:24 | new | new | +| D.cpp:22:10:22:33 | call to getElem | D.cpp:42:15:42:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:42:15:42:24 | new | new | +| D.cpp:22:10:22:33 | call to getElem | D.cpp:49:15:49:24 | new | D.cpp:22:10:22:33 | call to getElem | call to getElem flows from $@ | D.cpp:49:15:49:24 | new | new | +| D.cpp:64:10:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:10:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new | +| D.cpp:64:25:64:28 | elem | D.cpp:56:15:56:24 | new | D.cpp:64:25:64:28 | elem | elem flows from $@ | D.cpp:56:15:56:24 | new | new | +| E.cpp:21:18:21:23 | buffer indirection | E.cpp:30:21:30:33 | argument_source output argument | E.cpp:21:18:21:23 | buffer indirection | buffer indirection flows from $@ | E.cpp:30:21:30:33 | argument_source output argument | argument_source output argument | +| E.cpp:31:10:31:12 | raw indirection | E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection | raw indirection flows from $@ | E.cpp:28:21:28:23 | argument_source output argument | argument_source output argument | +| E.cpp:31:10:31:12 | raw indirection | E.cpp:28:21:28:23 | argument_source output argument | E.cpp:31:10:31:12 | raw indirection | raw indirection flows from $@ | E.cpp:28:21:28:23 | argument_source output argument | argument_source output argument | +| E.cpp:32:13:32:18 | buffer indirection | E.cpp:29:21:29:29 | argument_source output argument | E.cpp:32:13:32:18 | buffer indirection | buffer indirection flows from $@ | E.cpp:29:21:29:29 | argument_source output argument | argument_source output argument | | aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input | call to user_input | | aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input | call to user_input | | aliasing.cpp:62:14:62:15 | m1 | aliasing.cpp:60:11:60:20 | call to user_input | aliasing.cpp:62:14:62:15 | m1 | m1 flows from $@ | aliasing.cpp:60:11:60:20 | call to user_input | call to user_input | | aliasing.cpp:93:12:93:13 | m1 | aliasing.cpp:92:12:92:21 | call to user_input | aliasing.cpp:93:12:93:13 | m1 | m1 flows from $@ | aliasing.cpp:92:12:92:21 | call to user_input | call to user_input | +| aliasing.cpp:102:8:102:10 | * ... | aliasing.cpp:98:10:98:19 | call to user_input | aliasing.cpp:102:8:102:10 | * ... | * ... flows from $@ | aliasing.cpp:98:10:98:19 | call to user_input | call to user_input | +| aliasing.cpp:122:8:122:12 | access to array | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:122:8:122:12 | access to array | access to array flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | +| aliasing.cpp:127:8:127:16 | * ... | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:127:8:127:16 | * ... | * ... flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | +| aliasing.cpp:132:8:132:14 | * ... | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:132:8:132:14 | * ... | * ... flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | +| aliasing.cpp:137:8:137:11 | * ... | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:137:8:137:11 | * ... | * ... flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:143:8:143:16 | access to array | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:143:8:143:16 | access to array | access to array flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:159:8:159:14 | * ... | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:159:8:159:14 | * ... | * ... flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | | aliasing.cpp:165:8:165:16 | access to array | aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:165:8:165:16 | access to array | access to array flows from $@ | aliasing.cpp:106:9:106:18 | call to user_input | call to user_input | @@ -1544,8 +1888,9 @@ subpaths | complex.cpp:43:18:43:18 | call to b | complex.cpp:54:19:54:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:54:19:54:28 | call to user_input | call to user_input | | complex.cpp:43:18:43:18 | call to b | complex.cpp:56:19:56:28 | call to user_input | complex.cpp:43:18:43:18 | call to b | call to b flows from $@ | complex.cpp:56:19:56:28 | call to user_input | call to user_input | | conflated.cpp:11:8:11:12 | * ... | conflated.cpp:10:11:10:20 | call to user_input | conflated.cpp:11:8:11:12 | * ... | * ... flows from $@ | conflated.cpp:10:11:10:20 | call to user_input | call to user_input | -| conflated.cpp:20:8:20:10 | (void *)... | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | (void *)... | (void *)... flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument | -| conflated.cpp:20:8:20:10 | raw | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw | raw flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument | +| conflated.cpp:20:8:20:10 | raw indirection | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | raw indirection flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument | +| conflated.cpp:20:8:20:10 | raw indirection | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | raw indirection flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument | +| conflated.cpp:20:8:20:10 | raw indirection | conflated.cpp:19:19:19:21 | argument_source output argument | conflated.cpp:20:8:20:10 | raw indirection | raw indirection flows from $@ | conflated.cpp:19:19:19:21 | argument_source output argument | argument_source output argument | | conflated.cpp:30:12:30:12 | x | conflated.cpp:29:11:29:20 | call to user_input | conflated.cpp:30:12:30:12 | x | x flows from $@ | conflated.cpp:29:11:29:20 | call to user_input | call to user_input | | conflated.cpp:37:12:37:12 | x | conflated.cpp:36:11:36:20 | call to user_input | conflated.cpp:37:12:37:12 | x | x flows from $@ | conflated.cpp:36:11:36:20 | call to user_input | call to user_input | | conflated.cpp:55:18:55:18 | y | conflated.cpp:54:17:54:26 | call to user_input | conflated.cpp:55:18:55:18 | y | y flows from $@ | conflated.cpp:54:17:54:26 | call to user_input | call to user_input | @@ -1560,8 +1905,10 @@ subpaths | qualifiers.cpp:38:23:38:23 | a | qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:38:23:38:23 | a | a flows from $@ | qualifiers.cpp:37:38:37:47 | call to user_input | call to user_input | | qualifiers.cpp:43:23:43:23 | a | qualifiers.cpp:42:29:42:38 | call to user_input | qualifiers.cpp:43:23:43:23 | a | a flows from $@ | qualifiers.cpp:42:29:42:38 | call to user_input | call to user_input | | qualifiers.cpp:48:23:48:23 | a | qualifiers.cpp:47:31:47:40 | call to user_input | qualifiers.cpp:48:23:48:23 | a | a flows from $@ | qualifiers.cpp:47:31:47:40 | call to user_input | call to user_input | -| realistic.cpp:61:14:61:55 | (void *)... | realistic.cpp:53:47:53:66 | (size_t)... | realistic.cpp:61:14:61:55 | (void *)... | (void *)... flows from $@ | realistic.cpp:53:47:53:66 | (size_t)... | (size_t)... | -| realistic.cpp:61:14:61:55 | (void *)... | realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:14:61:55 | (void *)... | (void *)... flows from $@ | realistic.cpp:53:55:53:64 | call to user_input | call to user_input | +| realistic.cpp:61:14:61:55 | bufferLen | realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:61:14:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:47:53:66 | call to user_input | call to user_input | +| realistic.cpp:61:14:61:55 | bufferLen | realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:14:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:55:53:64 | call to user_input | call to user_input | +| realistic.cpp:61:47:61:55 | bufferLen | realistic.cpp:53:47:53:66 | call to user_input | realistic.cpp:61:47:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:47:53:66 | call to user_input | call to user_input | +| realistic.cpp:61:47:61:55 | bufferLen | realistic.cpp:53:55:53:64 | call to user_input | realistic.cpp:61:47:61:55 | bufferLen | bufferLen flows from $@ | realistic.cpp:53:55:53:64 | call to user_input | call to user_input | | simple.cpp:28:12:28:12 | call to a | simple.cpp:39:12:39:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:39:12:39:21 | call to user_input | call to user_input | | simple.cpp:28:12:28:12 | call to a | simple.cpp:41:12:41:21 | call to user_input | simple.cpp:28:12:28:12 | call to a | call to a flows from $@ | simple.cpp:41:12:41:21 | call to user_input | call to user_input | | simple.cpp:29:12:29:12 | call to b | simple.cpp:40:12:40:21 | call to user_input | simple.cpp:29:12:29:12 | call to b | call to b flows from $@ | simple.cpp:40:12:40:21 | call to user_input | call to user_input | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected index ba1c3c274b7..6749e278fba 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-diff.expected @@ -1,7 +1,10 @@ | A.cpp:25:13:25:13 | c | AST only | | A.cpp:27:28:27:28 | c | AST only | +| A.cpp:28:29:28:29 | this | IR only | | A.cpp:31:14:31:21 | new | IR only | | A.cpp:40:15:40:21 | 0 | IR only | +| A.cpp:40:15:40:21 | 0 | IR only | +| A.cpp:41:15:41:21 | new | IR only | | A.cpp:41:15:41:21 | new | IR only | | A.cpp:41:15:41:21 | new | IR only | | A.cpp:47:12:47:18 | new | IR only | @@ -41,6 +44,7 @@ | A.cpp:161:29:161:35 | 0 | IR only | | A.cpp:162:18:162:40 | new | IR only | | A.cpp:162:29:162:35 | 0 | IR only | +| A.cpp:167:47:167:50 | l | IR only | | A.cpp:183:7:183:10 | head | AST only | | A.cpp:184:13:184:16 | next | AST only | | B.cpp:7:16:7:35 | new | IR only | @@ -54,12 +58,12 @@ | B.cpp:46:13:46:16 | box1 | AST only | | C.cpp:18:12:18:18 | new | IR only | | C.cpp:24:11:24:12 | s3 | AST only | -| C.cpp:30:10:30:11 | s2 | IR only | | C.cpp:30:10:30:11 | this | IR only | -| C.cpp:32:10:32:11 | s4 | IR only | | D.cpp:9:21:9:24 | elem | AST only | +| D.cpp:10:30:10:33 | this | IR only | | D.cpp:11:29:11:32 | elem | AST only | | D.cpp:16:21:16:23 | box | AST only | +| D.cpp:17:30:17:32 | this | IR only | | D.cpp:18:29:18:31 | box | AST only | | D.cpp:29:15:29:41 | new | IR only | | D.cpp:29:24:29:40 | new | IR only | @@ -88,60 +92,139 @@ | aliasing.cpp:9:6:9:7 | m1 | AST only | | aliasing.cpp:13:5:13:6 | m1 | AST only | | aliasing.cpp:17:5:17:6 | m1 | AST only | +| aliasing.cpp:29:11:29:12 | s1 | IR only | +| aliasing.cpp:30:11:30:12 | s2 | IR only | +| aliasing.cpp:31:11:31:12 | s3 | IR only | | aliasing.cpp:37:8:37:9 | m1 | AST only | +| aliasing.cpp:38:11:38:12 | s1 | IR only | | aliasing.cpp:42:6:42:7 | m1 | AST only | +| aliasing.cpp:43:13:43:14 | ref2 | IR only | | aliasing.cpp:49:9:49:10 | m1 | AST only | +| aliasing.cpp:50:11:50:12 | s1 | IR only | | aliasing.cpp:54:6:54:7 | m1 | AST only | +| aliasing.cpp:55:14:55:15 | copy2 | IR only | | aliasing.cpp:60:6:60:7 | m1 | AST only | +| aliasing.cpp:62:14:62:15 | copy2 | IR only | +| aliasing.cpp:71:11:71:11 | w | IR only | | aliasing.cpp:72:5:72:6 | m1 | AST only | +| aliasing.cpp:73:10:73:10 | w | IR only | +| aliasing.cpp:73:12:73:13 | s | IR only | +| aliasing.cpp:78:13:78:13 | w | IR only | | aliasing.cpp:79:6:79:7 | m1 | AST only | +| aliasing.cpp:80:10:80:10 | w | IR only | +| aliasing.cpp:80:12:80:13 | s | IR only | +| aliasing.cpp:85:12:85:12 | w | IR only | | aliasing.cpp:86:5:86:6 | m1 | AST only | +| aliasing.cpp:87:10:87:10 | w | IR only | +| aliasing.cpp:87:12:87:13 | s | IR only | | aliasing.cpp:92:7:92:8 | m1 | AST only | +| aliasing.cpp:93:10:93:10 | w | IR only | +| aliasing.cpp:93:12:93:13 | s | IR only | | aliasing.cpp:98:5:98:6 | m1 | AST only | +| aliasing.cpp:101:21:101:22 | s_copy | IR only | | aliasing.cpp:106:3:106:5 | * ... | AST only | +| aliasing.cpp:112:10:112:11 | s | IR only | +| aliasing.cpp:143:10:143:13 | s | IR only | +| aliasing.cpp:148:13:148:14 | access to array | IR only | +| aliasing.cpp:159:11:159:14 | s | IR only | +| aliasing.cpp:165:10:165:13 | s | IR only | +| aliasing.cpp:176:11:176:11 | s2 | IR only | +| aliasing.cpp:176:13:176:14 | s | IR only | +| aliasing.cpp:182:11:182:11 | s2 | IR only | +| aliasing.cpp:182:13:182:14 | s | IR only | +| aliasing.cpp:189:13:189:13 | s2_2 | IR only | +| aliasing.cpp:189:15:189:16 | s | IR only | +| aliasing.cpp:196:13:196:13 | s2_2 | IR only | +| aliasing.cpp:196:15:196:16 | s | IR only | +| aliasing.cpp:201:13:201:13 | ps2 | IR only | +| aliasing.cpp:201:15:201:16 | s | IR only | +| aliasing.cpp:206:13:206:13 | ps2 | IR only | +| aliasing.cpp:206:15:206:16 | s | IR only | | arrays.cpp:6:3:6:8 | access to array | AST only | | arrays.cpp:7:8:7:13 | access to array | IR only | +| arrays.cpp:7:8:7:13 | access to array | IR only | +| arrays.cpp:8:8:8:13 | access to array | IR only | | arrays.cpp:8:8:8:13 | access to array | IR only | | arrays.cpp:9:8:9:11 | * ... | IR only | +| arrays.cpp:9:8:9:11 | * ... | IR only | +| arrays.cpp:10:8:10:15 | * ... | IR only | | arrays.cpp:10:8:10:15 | * ... | IR only | | arrays.cpp:15:3:15:10 | * ... | AST only | | arrays.cpp:16:8:16:13 | access to array | IR only | +| arrays.cpp:16:8:16:13 | access to array | IR only | +| arrays.cpp:17:8:17:13 | access to array | IR only | | arrays.cpp:17:8:17:13 | access to array | IR only | | arrays.cpp:36:19:36:22 | data | AST only | | arrays.cpp:42:22:42:25 | data | AST only | | arrays.cpp:48:22:48:25 | data | AST only | | by_reference.cpp:12:8:12:8 | a | AST only | | by_reference.cpp:16:11:16:11 | a | AST only | -| by_reference.cpp:40:12:40:15 | this | AST only | -| by_reference.cpp:51:8:51:8 | s | AST only | -| by_reference.cpp:57:8:57:8 | s | AST only | -| by_reference.cpp:63:8:63:8 | s | AST only | +| by_reference.cpp:32:15:32:15 | s | IR only | +| by_reference.cpp:36:18:36:18 | this | IR only | +| by_reference.cpp:44:26:44:29 | this | IR only | +| by_reference.cpp:69:22:69:23 | & ... | IR only | | by_reference.cpp:84:10:84:10 | a | AST only | | by_reference.cpp:88:9:88:9 | a | AST only | | by_reference.cpp:92:3:92:5 | * ... | AST only | | by_reference.cpp:96:3:96:4 | pa | AST only | +| complex.cpp:9:20:9:21 | this | IR only | +| complex.cpp:10:20:10:21 | this | IR only | | complex.cpp:11:22:11:23 | a_ | AST only | | complex.cpp:12:22:12:23 | b_ | AST only | | conflated.cpp:10:3:10:7 | * ... | AST only | +| conflated.cpp:11:12:11:12 | ra | IR only | | conflated.cpp:29:7:29:7 | x | AST only | +| conflated.cpp:30:12:30:12 | pa | IR only | | conflated.cpp:36:7:36:7 | x | AST only | +| conflated.cpp:37:12:37:12 | pa | IR only | | conflated.cpp:53:7:53:10 | next | AST only | | conflated.cpp:54:13:54:13 | y | AST only | +| conflated.cpp:55:12:55:15 | ll | IR only | +| conflated.cpp:55:18:55:18 | next | IR only | | conflated.cpp:59:20:59:39 | new | IR only | | conflated.cpp:60:13:60:13 | y | AST only | +| conflated.cpp:61:12:61:15 | ll | IR only | +| conflated.cpp:61:18:61:18 | next | IR only | +| constructors.cpp:18:22:18:23 | this | IR only | +| constructors.cpp:19:22:19:23 | this | IR only | | constructors.cpp:20:24:20:25 | a_ | AST only | | constructors.cpp:21:24:21:25 | b_ | AST only | | qualifiers.cpp:9:36:9:36 | a | AST only | | qualifiers.cpp:12:56:12:56 | a | AST only | | qualifiers.cpp:13:57:13:57 | a | AST only | +| qualifiers.cpp:18:32:18:36 | this | IR only | | qualifiers.cpp:22:23:22:23 | a | AST only | | qualifiers.cpp:42:25:42:25 | a | AST only | | qualifiers.cpp:47:27:47:27 | a | AST only | | realistic.cpp:26:5:26:10 | offset | AST only | | realistic.cpp:49:20:49:22 | baz | AST only | | realistic.cpp:53:35:53:43 | bufferLen | AST only | +| realistic.cpp:54:50:54:61 | call to user_input | IR only | +| realistic.cpp:55:16:55:18 | foo | IR only | +| realistic.cpp:55:23:55:25 | access to array | IR only | +| realistic.cpp:55:28:55:36 | baz | IR only | +| realistic.cpp:55:38:55:46 | userInput | IR only | +| realistic.cpp:57:92:57:94 | foo | IR only | +| realistic.cpp:57:99:57:101 | access to array | IR only | +| realistic.cpp:57:104:57:112 | baz | IR only | +| realistic.cpp:57:114:57:122 | userInput | IR only | +| realistic.cpp:60:21:60:52 | buffer | IR only | +| realistic.cpp:60:25:60:27 | foo | IR only | +| realistic.cpp:60:32:60:34 | access to array | IR only | +| realistic.cpp:60:37:60:45 | baz | IR only | +| realistic.cpp:60:47:60:52 | userInput | IR only | +| realistic.cpp:60:59:60:61 | foo | IR only | +| realistic.cpp:60:66:60:68 | access to array | IR only | +| realistic.cpp:60:71:60:79 | baz | IR only | +| realistic.cpp:60:81:60:89 | userInput | IR only | +| simple.cpp:18:22:18:23 | this | IR only | +| simple.cpp:19:22:19:23 | this | IR only | | simple.cpp:20:24:20:25 | a_ | AST only | | simple.cpp:21:24:21:25 | b_ | AST only | | simple.cpp:65:7:65:7 | i | AST only | +| simple.cpp:67:13:67:13 | a2 | IR only | +| simple.cpp:79:16:79:17 | this | IR only | +| simple.cpp:79:19:79:20 | f2 | IR only | | simple.cpp:83:12:83:13 | f1 | AST only | | simple.cpp:92:7:92:7 | i | AST only | +| simple.cpp:94:13:94:13 | a2 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected index 8ed0e3c4032..1818cea24bb 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/partial-definition-ir.expected @@ -1,5 +1,6 @@ | A.cpp:25:7:25:10 | this | | A.cpp:27:22:27:25 | this | +| A.cpp:28:23:28:26 | this | | A.cpp:31:14:31:21 | new | | A.cpp:31:20:31:20 | c | | A.cpp:40:5:40:6 | cc | @@ -101,6 +102,7 @@ | A.cpp:166:20:166:23 | next | | A.cpp:166:26:166:29 | next | | A.cpp:166:32:166:35 | head | +| A.cpp:167:44:167:44 | l | | A.cpp:169:12:169:12 | l | | A.cpp:169:15:169:18 | head | | A.cpp:183:7:183:10 | this | @@ -135,14 +137,14 @@ | C.cpp:24:5:24:8 | this | | C.cpp:29:10:29:11 | s1 | | C.cpp:29:10:29:11 | this | -| C.cpp:30:10:30:11 | s2 | | C.cpp:30:10:30:11 | this | | C.cpp:31:10:31:11 | s3 | | C.cpp:31:10:31:11 | this | -| C.cpp:32:10:32:11 | s4 | | D.cpp:9:21:9:24 | this | +| D.cpp:10:30:10:33 | this | | D.cpp:11:29:11:32 | this | | D.cpp:16:21:16:23 | this | +| D.cpp:17:30:17:32 | this | | D.cpp:18:29:18:31 | this | | D.cpp:22:10:22:11 | b2 | | D.cpp:22:14:22:20 | call to getBox1 | @@ -203,49 +205,86 @@ | aliasing.cpp:17:3:17:3 | s | | aliasing.cpp:25:17:25:19 | & ... | | aliasing.cpp:26:19:26:20 | s2 | +| aliasing.cpp:29:8:29:9 | s1 | +| aliasing.cpp:30:8:30:9 | s2 | +| aliasing.cpp:31:8:31:9 | s3 | | aliasing.cpp:37:3:37:6 | ref1 | +| aliasing.cpp:38:8:38:9 | s1 | | aliasing.cpp:42:3:42:4 | s2 | +| aliasing.cpp:43:8:43:11 | ref2 | | aliasing.cpp:49:3:49:7 | copy1 | +| aliasing.cpp:50:8:50:9 | s1 | | aliasing.cpp:54:3:54:4 | s2 | +| aliasing.cpp:55:8:55:12 | copy2 | | aliasing.cpp:60:3:60:4 | s2 | +| aliasing.cpp:62:8:62:12 | copy2 | +| aliasing.cpp:71:9:71:9 | w | | aliasing.cpp:72:3:72:3 | s | +| aliasing.cpp:73:8:73:8 | w | +| aliasing.cpp:73:10:73:10 | s | +| aliasing.cpp:78:11:78:11 | w | | aliasing.cpp:79:3:79:3 | s | +| aliasing.cpp:80:8:80:8 | w | +| aliasing.cpp:80:10:80:10 | s | +| aliasing.cpp:85:10:85:10 | w | | aliasing.cpp:86:3:86:3 | s | +| aliasing.cpp:87:8:87:8 | w | +| aliasing.cpp:87:10:87:10 | s | | aliasing.cpp:92:3:92:3 | w | | aliasing.cpp:92:5:92:5 | s | +| aliasing.cpp:93:8:93:8 | w | +| aliasing.cpp:93:10:93:10 | s | | aliasing.cpp:98:3:98:3 | s | +| aliasing.cpp:101:14:101:19 | s_copy | | aliasing.cpp:111:15:111:19 | & ... | | aliasing.cpp:111:16:111:16 | s | +| aliasing.cpp:112:8:112:8 | s | | aliasing.cpp:121:15:121:16 | xs | | aliasing.cpp:126:15:126:20 | ... - ... | | aliasing.cpp:131:15:131:16 | xs | | aliasing.cpp:136:15:136:17 | + ... | | aliasing.cpp:141:15:141:15 | s | | aliasing.cpp:141:17:141:20 | data | +| aliasing.cpp:143:8:143:8 | s | | aliasing.cpp:147:15:147:22 | & ... | | aliasing.cpp:147:16:147:19 | access to array | +| aliasing.cpp:148:8:148:11 | access to array | | aliasing.cpp:158:15:158:15 | s | | aliasing.cpp:158:17:158:20 | data | +| aliasing.cpp:159:9:159:9 | s | | aliasing.cpp:164:15:164:15 | s | | aliasing.cpp:164:17:164:20 | data | +| aliasing.cpp:165:8:165:8 | s | | aliasing.cpp:175:15:175:22 | & ... | | aliasing.cpp:175:16:175:17 | s2 | | aliasing.cpp:175:19:175:19 | s | +| aliasing.cpp:176:8:176:9 | s2 | +| aliasing.cpp:176:11:176:11 | s | | aliasing.cpp:181:15:181:22 | & ... | | aliasing.cpp:181:16:181:17 | s2 | | aliasing.cpp:181:19:181:19 | s | +| aliasing.cpp:182:8:182:9 | s2 | +| aliasing.cpp:182:11:182:11 | s | | aliasing.cpp:187:15:187:22 | & ... | | aliasing.cpp:187:16:187:17 | s2 | | aliasing.cpp:187:19:187:19 | s | +| aliasing.cpp:189:8:189:11 | s2_2 | +| aliasing.cpp:189:13:189:13 | s | | aliasing.cpp:194:15:194:22 | & ... | | aliasing.cpp:194:16:194:17 | s2 | | aliasing.cpp:194:19:194:19 | s | +| aliasing.cpp:196:8:196:11 | s2_2 | +| aliasing.cpp:196:13:196:13 | s | | aliasing.cpp:200:15:200:24 | & ... | | aliasing.cpp:200:16:200:18 | ps2 | | aliasing.cpp:200:21:200:21 | s | +| aliasing.cpp:201:8:201:10 | ps2 | +| aliasing.cpp:201:13:201:13 | s | | aliasing.cpp:205:15:205:24 | & ... | | aliasing.cpp:205:16:205:18 | ps2 | | aliasing.cpp:205:21:205:21 | s | +| aliasing.cpp:206:8:206:10 | ps2 | +| aliasing.cpp:206:13:206:13 | s | | arrays.cpp:7:8:7:13 | access to array | | arrays.cpp:8:8:8:13 | access to array | | arrays.cpp:9:8:9:11 | * ... | @@ -291,18 +330,26 @@ | by_reference.cpp:20:23:20:27 | value | | by_reference.cpp:24:19:24:22 | this | | by_reference.cpp:24:25:24:29 | value | +| by_reference.cpp:32:12:32:12 | s | +| by_reference.cpp:36:12:36:15 | this | +| by_reference.cpp:40:12:40:15 | this | +| by_reference.cpp:44:26:44:29 | this | | by_reference.cpp:50:3:50:3 | s | | by_reference.cpp:50:17:50:26 | call to user_input | +| by_reference.cpp:51:8:51:8 | s | | by_reference.cpp:51:10:51:20 | call to getDirectly | | by_reference.cpp:56:3:56:3 | s | | by_reference.cpp:56:19:56:28 | call to user_input | +| by_reference.cpp:57:8:57:8 | s | | by_reference.cpp:57:10:57:22 | call to getIndirectly | | by_reference.cpp:62:3:62:3 | s | | by_reference.cpp:62:25:62:34 | call to user_input | +| by_reference.cpp:63:8:63:8 | s | | by_reference.cpp:63:10:63:28 | call to getThroughNonMember | | by_reference.cpp:68:17:68:18 | & ... | | by_reference.cpp:68:21:68:30 | call to user_input | | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | +| by_reference.cpp:69:22:69:23 | & ... | | by_reference.cpp:84:3:84:7 | inner | | by_reference.cpp:88:3:88:7 | inner | | by_reference.cpp:102:21:102:39 | & ... | @@ -361,6 +408,8 @@ | by_reference.cpp:135:27:135:27 | a | | by_reference.cpp:136:8:136:13 | pouter | | by_reference.cpp:136:16:136:16 | a | +| complex.cpp:9:20:9:21 | this | +| complex.cpp:10:20:10:21 | this | | complex.cpp:11:22:11:23 | this | | complex.cpp:12:22:12:23 | this | | complex.cpp:42:8:42:8 | b | @@ -386,17 +435,26 @@ | complex.cpp:65:7:65:8 | b3 | | complex.cpp:68:7:68:8 | b4 | | conflated.cpp:10:4:10:5 | ra | +| conflated.cpp:11:9:11:10 | ra | | conflated.cpp:19:19:19:21 | raw | | conflated.cpp:20:8:20:10 | raw | | conflated.cpp:29:3:29:4 | pa | +| conflated.cpp:30:8:30:9 | pa | | conflated.cpp:36:3:36:4 | pa | +| conflated.cpp:37:8:37:9 | pa | | conflated.cpp:53:3:53:4 | ll | | conflated.cpp:54:3:54:4 | ll | | conflated.cpp:54:7:54:10 | next | +| conflated.cpp:55:8:55:9 | ll | +| conflated.cpp:55:12:55:15 | next | | conflated.cpp:59:20:59:39 | new | | conflated.cpp:59:35:59:38 | next | | conflated.cpp:60:3:60:4 | ll | | conflated.cpp:60:7:60:10 | next | +| conflated.cpp:61:8:61:9 | ll | +| conflated.cpp:61:12:61:15 | next | +| constructors.cpp:18:22:18:23 | this | +| constructors.cpp:19:22:19:23 | this | | constructors.cpp:20:24:20:25 | this | | constructors.cpp:21:24:21:25 | this | | constructors.cpp:28:10:28:10 | f | @@ -408,6 +466,7 @@ | qualifiers.cpp:9:30:9:33 | this | | qualifiers.cpp:12:49:12:53 | inner | | qualifiers.cpp:13:51:13:55 | inner | +| qualifiers.cpp:18:32:18:36 | this | | qualifiers.cpp:22:5:22:9 | outer | | qualifiers.cpp:22:11:22:18 | call to getInner | | qualifiers.cpp:23:10:23:14 | outer | @@ -453,7 +512,25 @@ | realistic.cpp:54:27:54:29 | baz | | realistic.cpp:54:32:54:40 | userInput | | realistic.cpp:54:42:54:47 | buffer | +| realistic.cpp:54:50:54:59 | call to user_input | +| realistic.cpp:55:12:55:14 | foo | +| realistic.cpp:55:12:55:21 | access to array | +| realistic.cpp:55:23:55:25 | baz | +| realistic.cpp:55:28:55:36 | userInput | +| realistic.cpp:57:88:57:90 | foo | +| realistic.cpp:57:88:57:97 | access to array | +| realistic.cpp:57:99:57:101 | baz | +| realistic.cpp:57:104:57:112 | userInput | | realistic.cpp:60:16:60:18 | dst | +| realistic.cpp:60:21:60:23 | foo | +| realistic.cpp:60:21:60:30 | access to array | +| realistic.cpp:60:32:60:34 | baz | +| realistic.cpp:60:37:60:45 | userInput | +| realistic.cpp:60:47:60:52 | buffer | +| realistic.cpp:60:55:60:57 | foo | +| realistic.cpp:60:55:60:64 | access to array | +| realistic.cpp:60:66:60:68 | baz | +| realistic.cpp:60:71:60:79 | userInput | | realistic.cpp:61:21:61:23 | foo | | realistic.cpp:61:21:61:30 | access to array | | realistic.cpp:61:32:61:34 | baz | @@ -465,6 +542,8 @@ | realistic.cpp:65:37:65:45 | userInput | | realistic.cpp:65:47:65:52 | buffer | | realistic.cpp:66:21:66:23 | dst | +| simple.cpp:18:22:18:23 | this | +| simple.cpp:19:22:19:23 | this | | simple.cpp:20:24:20:25 | this | | simple.cpp:21:24:21:25 | this | | simple.cpp:28:10:28:10 | f | @@ -478,10 +557,14 @@ | simple.cpp:51:9:51:9 | h | | simple.cpp:54:9:54:9 | i | | simple.cpp:65:5:65:5 | a | +| simple.cpp:67:10:67:11 | a2 | +| simple.cpp:79:16:79:17 | f2 | +| simple.cpp:79:16:79:17 | this | | simple.cpp:83:9:83:10 | f2 | | simple.cpp:83:9:83:10 | this | | simple.cpp:84:14:84:20 | this | | simple.cpp:92:5:92:5 | a | +| simple.cpp:94:10:94:11 | a2 | | struct_init.c:15:8:15:9 | ab | | struct_init.c:15:12:15:12 | a | | struct_init.c:16:8:16:9 | ab | diff --git a/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql b/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql index fb94b0144b0..f72965eb785 100644 --- a/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql +++ b/cpp/ql/test/library-tests/dataflow/recursion/chained_use.ql @@ -1,11 +1,10 @@ import cpp -import semmle.code.cpp.dataflow.DataFlow -import semmle.code.cpp.dataflow.DataFlow2 -import semmle.code.cpp.dataflow.DataFlow3 -import semmle.code.cpp.dataflow.DataFlow4 -import semmle.code.cpp.dataflow.TaintTracking -import semmle.code.cpp.dataflow.TaintTracking2 -import semmle.code.cpp.dataflow.RecursionPrevention +import semmle.code.cpp.ir.dataflow.DataFlow +import semmle.code.cpp.ir.dataflow.DataFlow2 +import semmle.code.cpp.ir.dataflow.DataFlow3 +import semmle.code.cpp.ir.dataflow.DataFlow4 +import semmle.code.cpp.ir.dataflow.TaintTracking +import semmle.code.cpp.ir.dataflow.TaintTracking2 class TestConf1 extends DataFlow::Configuration { TestConf1() { this = "TestConf1" } diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected index 5d732c45866..a26a4994992 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_diff.expected @@ -28,7 +28,7 @@ WARNING: Predicate taintedIncludingGlobalVars has been deprecated and may be rem | test.cpp:68:28:68:33 | call to getenv | test.cpp:69:10:69:13 | copy | AST only | | test.cpp:68:28:68:33 | call to getenv | test.cpp:70:5:70:10 | call to strcpy | AST only | | test.cpp:68:28:68:33 | call to getenv | test.cpp:70:12:70:15 | copy | AST only | -| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | AST only | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | array to pointer conversion | IR only | | test.cpp:75:20:75:25 | call to getenv | test.cpp:15:22:15:25 | nptr | AST only | | test.cpp:83:28:83:33 | call to getenv | test.cpp:8:24:8:25 | s1 | AST only | | test.cpp:83:28:83:33 | call to getenv | test.cpp:11:20:11:21 | s1 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected index 4b439122fa3..27d00060e4c 100644 --- a/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/security-taint/tainted_ir.expected @@ -22,6 +22,8 @@ WARNING: Module TaintedWithPath has been deprecated and may be removed in future | test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:33 | call to getenv | | test.cpp:68:28:68:33 | call to getenv | test.cpp:68:28:68:46 | (const char *)... | | test.cpp:68:28:68:33 | call to getenv | test.cpp:70:18:70:25 | userName | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | array to pointer conversion | +| test.cpp:68:28:68:33 | call to getenv | test.cpp:71:12:71:15 | copy | | test.cpp:75:20:75:25 | call to getenv | test.cpp:75:15:75:18 | call to atoi | | test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:25 | call to getenv | | test.cpp:75:20:75:25 | call to getenv | test.cpp:75:20:75:45 | (const char *)... | diff --git a/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp b/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp index 532a39ea7b2..8d0dd6b1220 100644 --- a/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/smart-pointers-taint/test.cpp @@ -7,8 +7,8 @@ void test_unique_ptr_int() { std::unique_ptr p1(new int(source())); std::unique_ptr p2 = std::make_unique(source()); - sink(*p1); // $ MISSING: ast,ir - sink(*p2); // $ ast ir=8:50 + sink(*p1); // $ ir MISSING: ast + sink(*p2); // $ ast ir } struct A { @@ -21,9 +21,9 @@ void test_unique_ptr_struct() { std::unique_ptr p1(new A{source(), 0}); std::unique_ptr p2 = std::make_unique(source(), 0); - sink(p1->x); // $ MISSING: ast,ir + sink(p1->x); // $ ir MISSING: ast sink(p1->y); - sink(p2->x); // $ MISSING: ast,ir=22:46 + sink(p2->x); // $ ir MISSING: ast sink(p2->y); } @@ -31,8 +31,8 @@ void test_shared_ptr_int() { std::shared_ptr p1(new int(source())); std::shared_ptr p2 = std::make_shared(source()); - sink(*p1); // $ ast MISSING: ir - sink(*p2); // $ ast ir=32:50 + sink(*p1); // $ ast,ir + sink(*p2); // $ ast ir } void test_shared_ptr_struct() { diff --git a/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp b/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp index fcc4ee0a315..f51d67e5335 100644 --- a/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp +++ b/cpp/ql/test/library-tests/dataflow/source-sink-tests/sources-and-sinks.cpp @@ -3,9 +3,9 @@ char *secure_getenv(const char *name); wchar_t *_wgetenv(const wchar_t *name); void test_getenv() { - void *var1 = getenv("VAR"); // $ local_source - void *var2 = secure_getenv("VAR"); // $ local_source - void *var3 = _wgetenv(L"VAR"); // $ local_source + void *var1 = getenv("VAR"); // $ local_source=6:18 local_source=6:18 + void *var2 = secure_getenv("VAR"); // $ local_source=7:18 local_source=7:18 + void *var3 = _wgetenv(L"VAR"); // $ local_source=8:18 local_source=8:18 } int send(int, const void*, int, int); diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/arrayassignment.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/arrayassignment.cpp index b541e50c72b..8c73d6c552c 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/arrayassignment.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/arrayassignment.cpp @@ -53,8 +53,8 @@ void test_myint_member_assignment() mi.i = source(); - sink(mi); // $ MISSING: ast,ir - sink(mi.get()); // $ ast MISSING: ir + sink(mi); // $ ir MISSING: ast + sink(mi.get()); // $ ast,ir } void test_myint_method_assignment() @@ -64,7 +64,7 @@ void test_myint_method_assignment() mi.get() = source(); sink(mi); // $ ir MISSING: ast - sink(mi.get()); // $ ast MISSING: ir + sink(mi.get()); // $ ast,ir } void test_myint_overloaded_assignment() @@ -107,7 +107,7 @@ void test_myarray_method_assignment() ma.get(0) = source(); - sink(ma.get(0)); // $ MISSING: ast,ir + sink(ma.get(0)); // $ ir MISSING: ast } void test_myarray_overloaded_assignment() diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 907cccd197b..85fc3526dc7 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -8090,20 +8090,20 @@ | vector.cpp:520:25:520:31 | call to vector | vector.cpp:523:8:523:9 | vs | | | vector.cpp:520:25:520:31 | call to vector | vector.cpp:524:8:524:9 | vs | | | vector.cpp:520:25:520:31 | call to vector | vector.cpp:526:8:526:9 | vs | | -| vector.cpp:520:25:520:31 | call to vector | vector.cpp:532:8:532:9 | vs | | -| vector.cpp:520:25:520:31 | call to vector | vector.cpp:533:2:533:2 | vs | | +| vector.cpp:520:25:520:31 | call to vector | vector.cpp:539:8:539:9 | vs | | +| vector.cpp:520:25:520:31 | call to vector | vector.cpp:540:2:540:2 | vs | | | vector.cpp:520:30:520:30 | 0 | vector.cpp:520:25:520:31 | call to vector | TAINT | | vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:524:8:524:9 | vs | | | vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | | -| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | | -| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | | +| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | | +| vector.cpp:523:8:523:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | | | vector.cpp:523:8:523:9 | vs | vector.cpp:523:10:523:10 | call to operator[] | TAINT | | vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:526:8:526:9 | vs | | -| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | | -| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | | +| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | | +| vector.cpp:524:8:524:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | | | vector.cpp:524:8:524:9 | vs | vector.cpp:524:10:524:10 | call to operator[] | TAINT | -| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:532:8:532:9 | vs | | -| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | | +| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:539:8:539:9 | vs | | +| vector.cpp:526:8:526:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | | | vector.cpp:526:8:526:9 | vs | vector.cpp:526:11:526:15 | call to begin | TAINT | | vector.cpp:526:11:526:15 | call to begin | vector.cpp:526:3:526:17 | ... = ... | | | vector.cpp:526:11:526:15 | call to begin | vector.cpp:527:9:527:10 | it | | @@ -8128,5 +8128,5 @@ | vector.cpp:530:3:530:4 | ref arg it | vector.cpp:531:9:531:10 | it | | | vector.cpp:530:9:530:14 | call to source | vector.cpp:530:3:530:4 | ref arg it | TAINT | | vector.cpp:531:9:531:10 | it | vector.cpp:531:8:531:8 | call to operator* | TAINT | -| vector.cpp:532:8:532:9 | ref arg vs | vector.cpp:533:2:533:2 | vs | | -| vector.cpp:532:8:532:9 | vs | vector.cpp:532:10:532:10 | call to operator[] | TAINT | +| vector.cpp:539:8:539:9 | ref arg vs | vector.cpp:540:2:540:2 | vs | | +| vector.cpp:539:8:539:9 | vs | vector.cpp:539:10:539:10 | call to operator[] | TAINT | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/smart_pointer.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/smart_pointer.cpp index 0771c1b7432..560a02fa4e6 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/smart_pointer.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/smart_pointer.cpp @@ -35,16 +35,16 @@ void test_reverse_taint_shared() { std::shared_ptr p = std::make_shared(); *p = source(); - sink(p); // $ ast MISSING: ir - sink(*p); // $ ast MISSING: ir + sink(p); // $ ast,ir + sink(*p); // $ ast,ir } void test_reverse_taint_unique() { std::unique_ptr p = std::unique_ptr(); *p = source(); - sink(p); // $ ast MISSING: ir - sink(*p); // $ ast MISSING: ir + sink(p); // $ ast,ir + sink(*p); // $ ast,ir } void test_shared_get() { @@ -85,11 +85,11 @@ struct B { void test_operator_arrow(std::unique_ptr p, std::unique_ptr q) { p->x = source(); - sink(p->x); // $ ast MISSING: ir + sink(p->x); // $ ast,ir sink(p->y); q->a1.x = source(); - sink(q->a1.x); // $ ast MISSING: ir + sink(q->a1.x); // $ ast,ir sink(q->a1.y); sink(q->a2.x); } @@ -101,7 +101,7 @@ void taint_x(A* pa) { void reverse_taint_smart_pointer() { std::unique_ptr p = std::unique_ptr(new A); taint_x(p.get()); - sink(p->x); // $ ast MISSING: ir + sink(p->x); // $ ast,ir } struct C { @@ -131,8 +131,8 @@ int nested_shared_ptr_taint(std::shared_ptr p1, std::unique_ptr p1, std::unique_ptr> p2) { taint_x_shared_cref(p1->q); - sink(p1->q->x); // $ ast MISSING: ir + sink(p1->q->x); // $ ast,ir getNumberCRef(*p2); - sink(**p2); // $ ast MISSING: ir + sink(**p2); // $ ast,ir } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp index 235e675c693..7265cb17542 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp @@ -92,7 +92,7 @@ void test_insert_iterator() { insert_iterator_by_trait i1 = c1.begin(); *i1-- = source(); - sink(c1); // $ ast MISSING: ir + sink(c1); // $ ast,ir insert_iterator_by_trait i2 = c2.begin(); *i2-- = 0; @@ -109,12 +109,12 @@ void test_assign_through_iterator() { a = c1.begin(); b = c1.begin(); *a = source(); - sink(a); // $ ast MISSING: ir + sink(a); // $ ast,ir c = c1.begin(); sink(b); // MISSING: ast,ir - sink(c); // $ ast MISSING: ir - sink(c1); // $ ast MISSING: ir + sink(c); // $ ast,ir + sink(c1); // $ ast,ir } void test_nonmember_iterator() { diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp index 0271b8205e4..9806ddb395e 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp @@ -87,11 +87,11 @@ void class_field_test() { sink(mc1.a); sink(mc1.b); // $ ast,ir - sink(mc1.c); // $ ast MISSING: ir + sink(mc1.c); // $ ast,ir sink(mc1.d); // $ ast,ir sink(mc2.a); sink(mc2.b); // $ ast,ir - sink(mc2.c); // $ ast MISSING: ir + sink(mc2.c); // $ ast,ir sink(mc2.d); } @@ -448,9 +448,9 @@ void test_qualifiers() sink(b); sink(b.getMember()); b.member = source(); - sink(b); // $ MISSING: ast,ir + sink(b); // $ ir MISSING: ast sink(b.member); // $ ast,ir - sink(b.getMember()); // $ MISSING: ast,ir + sink(b.getMember()); // $ ir MISSING: ast c = new MyClass2(0); @@ -677,7 +677,7 @@ public: void test_with_const_member(char* source) { C_const_member_function c; memcpy(c.data(), source, 16); - sink(c.data()); // $ ast MISSING: ir + sink(c.data()); // $ ast,ir } void argument_source(void*); @@ -690,7 +690,7 @@ void test_argument_source_field_to_obj() { two_members s; argument_source(s.x); - sink(s); // $ SPURIOUS: ast + sink(s); // $ SPURIOUS: ast,ir sink(s.x); // $ ast,ir sink(s.y); // clean } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.ql b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.ql index d7ae0f88732..fc0b0976348 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/taint.ql +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/taint.ql @@ -82,7 +82,9 @@ module IRTest { TestAllocationConfig() { this = "TestAllocationConfig" } override predicate isSource(DataFlow::Node source) { - source.asConvertedExpr().(FunctionCall).getTarget().getName() = "source" + source.asExpr().(FunctionCall).getTarget().getName() = "source" + or + source.asIndirectExpr().(FunctionCall).getTarget().getName() = "source" or source.asParameter().getName().matches("source%") or @@ -95,12 +97,18 @@ module IRTest { override predicate isSink(DataFlow::Node sink) { exists(FunctionCall call | call.getTarget().getName() = "sink" and - sink.asExpr() = call.getAnArgument() + [sink.asExpr(), sink.asIndirectExpr()] = call.getAnArgument() ) } override predicate isSanitizer(DataFlow::Node barrier) { barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer") } + + override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + // allow arbitrary reads at sinks + this.isSink(node) and + c.(DataFlow::FieldContent).getField().getDeclaringType() = node.getType().getUnspecifiedType() + } } } diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp index 0fa7c5c2154..19824641560 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp @@ -188,7 +188,7 @@ void test_nested_vectors() sink(dd[0].a); sink(dd[0].b); dd[0].a = source(); - sink(dd[0].a); // $ ir MISSING: ast + sink(dd[0].a); // $ MISSING: ast,ir sink(dd[0].b); } @@ -209,7 +209,7 @@ void test_nested_vectors() ff.push_back(mvc); sink(ff[0].vs[0]); ff[0].vs[0] = source(); - sink(ff[0].vs[0]); // $ ir MISSING: ast + sink(ff[0].vs[0]); // $ MISSING: ast,ir } } @@ -339,12 +339,12 @@ void test_vector_output_iterator(int b) { std::vector::iterator i1 = v1.begin(); *i1 = source(); - sink(v1); // $ ast MISSING: ir + sink(v1); // $ ast,ir for(std::vector::iterator it = v2.begin(); it != v2.end(); ++it) { *it = source(); } - sink(v2); // $ ast MISSING: ir + sink(v2); // $ ast,ir for(int& x : v3) { x = source(); @@ -354,42 +354,42 @@ void test_vector_output_iterator(int b) { for(std::vector::iterator it = v4.begin(); it != v4.end(); ++it) { taint_vector_output_iterator(it); } - sink(v4); // $ ast MISSING: ir + sink(v4); // $ ast,ir std::vector::iterator i5 = v5.begin(); *i5 = source(); - sink(v5); // $ ast MISSING: ir + sink(v5); // $ ast,ir *i5 = 1; - sink(v5); // $ ast MISSING: ir + sink(v5); // $ ast,ir std::vector::iterator i6 = v6.begin(); *i6 = source(); - sink(v6); // $ ast MISSING: ir + sink(v6); // $ ast,ir v6 = std::vector(10); - sink(v6); // $ SPURIOUS: ast + sink(v6); // $ SPURIOUS: ast,ir std::vector::iterator i7 = v7.begin(); if(b) { *i7 = source(); - sink(v7); // $ ast MISSING: ir + sink(v7); // $ ast,ir } else { *i7 = 1; sink(v7); } - sink(v7); // $ ast MISSING: ir + sink(v7); // $ ast,ir std::vector::iterator i8 = v8.begin(); *i8 = source(); - sink(v8); // $ ast MISSING: ir + sink(v8); // $ ast,ir *i8 = 1; - sink(v8); // $ SPURIOUS: ast + sink(v8); // $ SPURIOUS: ast,ir std::vector::iterator i9 = v9.begin(); *i9 = source(); taint_vector_output_iterator(i9); - sink(v9); // $ ast=330:10 SPURIOUS: ast=389:8 MISSING: ir + sink(v9); // $ ast=330:10 ir=330:10 ir SPURIOUS: ast=389:8 ir=389:8 std::vector::iterator i10 = v10.begin(); vector_iterator_assign_wrapper(i10, 10); @@ -397,21 +397,21 @@ void test_vector_output_iterator(int b) { std::vector::iterator i11 = v11.begin(); vector_iterator_assign_wrapper(i11, source()); - sink(v11); // $ ast MISSING: ir + sink(v11); // $ ast,ir std::vector::iterator i12 = v12.begin(); *i12++ = 0; *i12 = source(); - sink(v12); // $ ast MISSING: ir + sink(v12); // $ ast,ir std::vector::iterator i13 = v13.begin(); *i13++ = source(); - sink(v13); // $ ast MISSING: ir + sink(v13); // $ ast,ir std::vector::iterator i14 = v14.begin(); i14++; *i14++ = source(); - sink(v14); // $ ast MISSING: ir + sink(v14); // $ ast,ir } void test_vector_inserter(char *source_string) { @@ -419,21 +419,21 @@ void test_vector_inserter(char *source_string) { std::vector out; auto it = out.end(); *it++ = std::string(source_string); - sink(out); // $ ast MISSING: ir + sink(out); // $ ast,ir } { std::vector out; auto it = std::back_inserter(out); *it++ = std::string(source_string); - sink(out); // $ ast MISSING: ir + sink(out); // $ ast,ir } { std::vector out; auto it = std::back_inserter(out); *it++ = source(); - sink(out); // $ ast MISSING: ir + sink(out); // $ ast,ir } { @@ -523,12 +523,19 @@ void test_vector_iterator() { sink(vs[1]); sink(vs[source()]); // $ MISSING: ast,ir - it = vs.begin(); + it = vs.begin(); // (1) sink(*it); it += 1; sink(*it); - it += source(); - sink(*it); // $ ast,ir - sink(vs[1]); + it += source(); // (2) + sink(*it); // $ ast,ir // (3) + // This FP happens because of the following flows: + // 1. There's a write to the iterator at (2) + // 2. This write propagates to `it` on the next line at (3) + // 3. There's a taint step from `it` to `*it` at (3) + // 4. The `*it` is seen as a use of `vs` because of (1). + // 5. There's use-use flow from `*it` at (3) (which is a use of `vs`) to `vs` at (4) + // 6. There's a taint step from vs to vs[1] + sink(vs[1]); // $ SPURIOUS: ir // (4) } } diff --git a/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.expected b/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.expected index 6018624fd04..47b7f055943 100644 --- a/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.expected +++ b/cpp/ql/test/library-tests/declarationEntry/more/declarationEntry.expected @@ -61,14 +61,14 @@ | test.cpp:57:7:57:26 | definition of tmplClassProtoAndDef | | test.cpp:59:19:59:19 | definition of T | | test.cpp:60:6:60:29 | declaration of tmplInstantiatedFunction | -| test.cpp:60:33:60:33 | definition of t | -| test.cpp:60:33:60:33 | definition of t | | test.cpp:61:19:61:19 | definition of T | | test.cpp:62:6:62:6 | definition of tmplInstantiatedFunction | | test.cpp:62:6:62:6 | definition of tmplInstantiatedFunction | | test.cpp:62:6:62:29 | definition of tmplInstantiatedFunction | | test.cpp:62:33:62:33 | declaration of t | | test.cpp:62:33:62:33 | definition of t | +| test.cpp:62:33:62:33 | definition of t | +| test.cpp:62:33:62:33 | definition of t | | test.cpp:64:19:64:19 | definition of T | | test.cpp:65:7:65:27 | declaration of tmplInstantiatedClass | | test.cpp:66:19:66:19 | definition of T | diff --git a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql index bb335a0b30f..bae958e1076 100644 --- a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql @@ -4,12 +4,12 @@ import experimental.semmle.code.cpp.semantic.Semantic import experimental.semmle.code.cpp.semantic.analysis.RangeUtils import experimental.semmle.code.cpp.semantic.analysis.FloatDelta import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis +import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisImpl import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest module ModulusAnalysisInstantiated = - ModulusAnalysis>; + ModulusAnalysis>; class ModulusAnalysisTest extends InlineExpectationsTest { ModulusAnalysisTest() { this = "ModulusAnalysisTest" } diff --git a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp index 38eaeab3b12..58ed4fdf396 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp +++ b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp @@ -119,6 +119,7 @@ int test9(int x, int y) { } range(x); // $ range=>=4 } + range(x); // $ MISSING: range=>=4 return x; } @@ -231,8 +232,8 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=11 range=>=3 int c = -a; - range(c); - range(b+c); // $ range=<=10 range="<=+ ...:a-1" range=">=- ...+1" + range(c); // $ range=<=-3 range=>=-11 + range(b+c); // $ range=<=10 range="<=+ ...:a-1" range=">=- ...+1" range=>=-10 total += b+c; range(total); } @@ -241,8 +242,8 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=11 range=>=0 int c = -a; - range(c); - range(b+c); // $ range=<=11 range="<=+ ...:a+0" range=">=- ...+0" + range(c); // $ range=<=0 range=>=-11 + range(b+c); // $ range=<=11 range="<=+ ...:a+0" range=">=- ...+0" range=>=-11 total += b+c; range(total); } @@ -251,7 +252,7 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=11 range=>=-7 int c = -a; - range(c); + range(c); // $ range=<=7 range=>=-11 range(b+c); total += b+c; range(total); @@ -261,7 +262,7 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=1 range=>=-7 int c = -a; - range(c); + range(c); // $ range=<=7 range=>=-1 range(b+c); total += b+c; range(total); @@ -271,8 +272,8 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=0 range=>=-7 int c = -a; - range(c); - range(b+c); // $ range="<=- ...+0" range=">=+ ...:a+0" range=>=-7 + range(c); // $ range=<=7 range=>=0 + range(b+c); // $ range="<=- ...+0" range=">=+ ...:a+0" range=>=-7 range=<=7 total += b+c; range(total); } @@ -281,8 +282,8 @@ int test_unary(int a) { int b = +a; range(b); // $ range=<=-2 range=>=-7 int c = -a; - range(c); - range(b+c); // $ range="<=- ...-1" range=">=+ ...:a+1" range=>=-6 + range(c); // $ range=<=7 range=>=2 + range(b+c); // $ range="<=- ...-1" range=">=+ ...:a+1" range=>=-6 range=<=6 total += b+c; range(total); } @@ -552,7 +553,7 @@ int test16(int x) { range(x); // $ range=<=-1 range=>=0 return 1; } - range(d); // $ range===3 + range(d); // $ range=<=0 range=>=3 // Unreachable code range(x); // $ range=<=-1 range=>=0 } range(x); // $ range=>=0 @@ -997,3 +998,15 @@ void test_overflow() { range(x + y); // $ range===-2147483393 } } + +void test_negate_unsigned(unsigned u) { + if(10 < u && u < 20) { + range(-u); // underflows + } +} + +void test_negate_signed(int s) { + if(10 < s && s < 20) { + range(-s); // $ range=<=-11 range=>=-19 + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected index 5488cf803e6..a5250dfccc5 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected @@ -1,30 +1,30 @@ -| copy_from_prototype.cpp:3:7:3:7 | a | a::a(a &&) -> void | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:3:7:3:7 | a | a::a(const a &) -> void | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:3:7:3:7 | operator= | a::operator=(a &&) -> a & | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:3:7:3:7 | operator= | a::operator=(const a &) -> a & | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:4:26:4:26 | a | a<>::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a<> | 123 | -| copy_from_prototype.cpp:4:26:4:26 | a | a::a<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:3:7:3:7 | a | | -| copy_from_prototype.cpp:7:7:7:7 | b | b::b() -> void | copy_from_prototype.cpp:7:7:7:7 | b | | -| copy_from_prototype.cpp:7:7:7:7 | b | b::b(b &&) -> void | copy_from_prototype.cpp:7:7:7:7 | b | | -| copy_from_prototype.cpp:7:7:7:7 | b | b::b(const b &) -> void | copy_from_prototype.cpp:7:7:7:7 | b | | -| copy_from_prototype.cpp:7:7:7:7 | operator= | b::operator=(b &&) -> b & | copy_from_prototype.cpp:7:7:7:7 | b | | -| copy_from_prototype.cpp:7:7:7:7 | operator= | b::operator=(const b &) -> b & | copy_from_prototype.cpp:7:7:7:7 | b | | -| copy_from_prototype.cpp:13:7:13:7 | c | c::c(c &&) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:13:7:13:7 | c | c::c(const c &) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(c &&) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(const c &) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | | -| copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | -| copy_from_prototype.cpp:17:7:17:7 | d | d::d(d &&) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | -| copy_from_prototype.cpp:17:7:17:7 | operator= | d::operator=(const d &) -> d & | copy_from_prototype.cpp:17:7:17:7 | d | | -| copy_from_prototype.cpp:17:7:17:7 | operator= | d::operator=(d &&) -> d & | copy_from_prototype.cpp:17:7:17:7 | d | | -| copy_from_prototype.cpp:22:8:22:8 | e | e::e(const e &) -> void | copy_from_prototype.cpp:22:8:22:8 | e | | -| copy_from_prototype.cpp:22:8:22:8 | e | e::e(e &&) -> void | copy_from_prototype.cpp:22:8:22:8 | e | | -| copy_from_prototype.cpp:22:8:22:8 | operator= | e::operator=(const e &) -> e & | copy_from_prototype.cpp:22:8:22:8 | e | | -| copy_from_prototype.cpp:22:8:22:8 | operator= | e::operator=(e &&) -> e & | copy_from_prototype.cpp:22:8:22:8 | e | | -| copy_from_prototype.cpp:23:26:23:26 | e | e::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | -| copy_from_prototype.cpp:26:35:26:43 | e | e::e<(unnamed template parameter)>() -> void | copy_from_prototype.cpp:22:8:22:8 | e | 456 | -| file://:0:0:0:0 | operator= | __va_list_tag::operator=(__va_list_tag &&) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | | -| file://:0:0:0:0 | operator= | __va_list_tag::operator=(const __va_list_tag &) -> __va_list_tag & | file://:0:0:0:0 | __va_list_tag | | +| copy_from_prototype.cpp:3:7:3:7 | a | void a::a(a const&) | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:3:7:3:7 | a | void a::a(a&&) | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:3:7:3:7 | operator= | a& a::operator=(a const&) | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:3:7:3:7 | operator= | a& a::operator=(a&&) | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:4:26:4:26 | a | void a<(unnamed template parameter)>::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a<> | 123 | +| copy_from_prototype.cpp:4:26:4:26 | a | void a::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a | | +| copy_from_prototype.cpp:7:7:7:7 | b | void b::b() | copy_from_prototype.cpp:7:7:7:7 | b | | +| copy_from_prototype.cpp:7:7:7:7 | b | void b::b(b const&) | copy_from_prototype.cpp:7:7:7:7 | b | | +| copy_from_prototype.cpp:7:7:7:7 | b | void b::b(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | | +| copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b const&) | copy_from_prototype.cpp:7:7:7:7 | b | | +| copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | | +| copy_from_prototype.cpp:13:7:13:7 | c | void c::c(c const&) | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:13:7:13:7 | c | void c::c(c&&) | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:13:7:13:7 | operator= | c& c::operator=(c const&) | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:13:7:13:7 | operator= | c& c::operator=(c&&) | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:14:26:14:26 | c | void c::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c | X | +| copy_from_prototype.cpp:14:26:14:26 | c | void c::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c | | +| copy_from_prototype.cpp:17:7:17:7 | d | void d::d() | copy_from_prototype.cpp:17:7:17:7 | d | | +| copy_from_prototype.cpp:17:7:17:7 | d | void d::d(d const&) | copy_from_prototype.cpp:17:7:17:7 | d | | +| copy_from_prototype.cpp:17:7:17:7 | d | void d::d(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | | +| copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d const&) | copy_from_prototype.cpp:17:7:17:7 | d | | +| copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | | +| copy_from_prototype.cpp:22:8:22:8 | e | void e::e(e const&) | copy_from_prototype.cpp:22:8:22:8 | e | | +| copy_from_prototype.cpp:22:8:22:8 | e | void e::e(e&&) | copy_from_prototype.cpp:22:8:22:8 | e | | +| copy_from_prototype.cpp:22:8:22:8 | operator= | e& e::operator=(e const&) | copy_from_prototype.cpp:22:8:22:8 | e | | +| copy_from_prototype.cpp:22:8:22:8 | operator= | e& e::operator=(e&&) | copy_from_prototype.cpp:22:8:22:8 | e | | +| copy_from_prototype.cpp:23:26:23:26 | e | void e::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e | 456 | +| copy_from_prototype.cpp:26:35:26:43 | e | void e::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e | 456 | +| file://:0:0:0:0 | operator= | __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | file://:0:0:0:0 | __va_list_tag | | +| file://:0:0:0:0 | operator= | __va_list_tag& __va_list_tag::operator=(__va_list_tag&&) | file://:0:0:0:0 | __va_list_tag | | diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql index 9e1cc557510..be8ab9565f4 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.ql @@ -1,4 +1,5 @@ import cpp +import semmle.code.cpp.Print from Function f, string e where @@ -8,4 +9,4 @@ where then e = f.getADeclarationEntry().getNoExceptExpr().toString() else e = "" else e = "" -select f, f.getFullSignature(), f.getDeclaringType(), e +select f, getIdentityString(f), f.getDeclaringType(), e diff --git a/cpp/ql/test/library-tests/syntax-zoo/aggregateinitializer.c b/cpp/ql/test/library-tests/syntax-zoo/aggregateinitializer.c index 463bd49e0a0..137feb6157a 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aggregateinitializer.c +++ b/cpp/ql/test/library-tests/syntax-zoo/aggregateinitializer.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int a, b, c, d; int x[] = { a + b, c - d }; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected index ec7962a5035..63b6f72905b 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected @@ -13,70 +13,12 @@ instructionWithoutSuccessor | condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | +| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | +| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | +| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | | vla.c:11:6:11:16 | Chi: vla_typedef | Instruction 'Chi: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors -| allocators.cpp:14:5:14:8 | Chi: main | Instruction 'Chi: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| array_delete.cpp:5:6:5:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| assignexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| conditional_destructors.cpp:29:6:29:7 | Chi: f1 | Instruction 'Chi: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| conditional_destructors.cpp:38:6:38:7 | Chi: f2 | Instruction 'Chi: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| constmemberaccess.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| constructorinitializer.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defconstructornewexpr.cpp:3:6:3:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defdestructordeleteexpr.cpp:3:6:3:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| deleteexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| dostmt.c:8:6:8:18 | Chi: always_true_1 | Instruction 'Chi: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| dostmt.c:16:6:16:18 | Chi: always_true_2 | Instruction 'Chi: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| dostmt.c:25:6:25:18 | Chi: always_true_3 | Instruction 'Chi: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| fieldaccess.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| forstmt.cpp:1:6:1:7 | Chi: f1 | Instruction 'Chi: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| forstmt.cpp:8:6:8:7 | Chi: f2 | Instruction 'Chi: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| ifelsestmt.c:1:6:1:19 | Chi: always_false_1 | Instruction 'Chi: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifelsestmt.c:11:6:11:19 | Chi: always_false_2 | Instruction 'Chi: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifelsestmt.c:19:6:19:18 | Chi: always_true_1 | Instruction 'Chi: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifelsestmt.c:29:6:29:18 | Chi: always_true_2 | Instruction 'Chi: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifelsestmt.c:37:24:37:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| ifstmt.c:1:6:1:19 | Chi: always_false_1 | Instruction 'Chi: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifstmt.c:8:6:8:19 | Chi: always_false_2 | Instruction 'Chi: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifstmt.c:14:6:14:18 | Chi: always_true_1 | Instruction 'Chi: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifstmt.c:21:6:21:18 | Chi: always_true_2 | Instruction 'Chi: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifstmt.c:27:24:27:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| membercallexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| membercallexpr_args.cpp:7:6:7:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| newexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| no_dynamic_init.cpp:9:5:9:8 | Chi: main | Instruction 'Chi: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nonmembercallexpr.c:1:6:1:6 | Chi: g | Instruction 'Chi: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| parameterinitializer.cpp:18:5:18:8 | Chi: main | Instruction 'Chi: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| pmcallexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| revsubscriptexpr.c:1:6:1:6 | Chi: g | Instruction 'Chi: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| staticmembercallexpr.cpp:6:6:6:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| staticmembercallexpr_args.cpp:7:6:7:6 | Chi: f | Instruction 'Chi: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| stream_it.cpp:16:5:16:8 | Chi: main | Instruction 'Chi: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| whilestmt.c:1:6:1:19 | Chi: always_false_1 | Instruction 'Chi: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| whilestmt.c:8:6:8:19 | Chi: always_false_2 | Instruction 'Chi: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| whilestmt.c:15:6:15:18 | Chi: always_true_1 | Instruction 'Chi: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| whilestmt.c:23:6:23:18 | Chi: always_true_2 | Instruction 'Chi: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| whilestmt.c:32:6:32:18 | Chi: always_true_3 | Instruction 'Chi: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | unexplainedLoop unnecessaryPhiInstruction memoryOperandDefinitionIsUnmodeled @@ -93,7 +35,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer -| pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | +| pmcallexpr.cpp:10:2:10:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pmcallexpr.cpp:8:13:8:13 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | nonUniqueIRVariable diff --git a/cpp/ql/test/library-tests/syntax-zoo/allocators.cpp b/cpp/ql/test/library-tests/syntax-zoo/allocators.cpp index 224ea043fd4..7c3ed550e81 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/allocators.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/allocators.cpp @@ -11,7 +11,7 @@ struct Allocators int m_y; }; -int main() +static int f() { auto foo = new(11, 22) Allocators(33, 44); delete foo; diff --git a/cpp/ql/test/library-tests/syntax-zoo/array_delete.cpp b/cpp/ql/test/library-tests/syntax-zoo/array_delete.cpp index d135dc41601..ced151cb613 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/array_delete.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/array_delete.cpp @@ -2,6 +2,6 @@ struct ArrayDelete { ~ArrayDelete(); }; -void f() { +static void f() { delete[] (ArrayDelete*)nullptr; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/assignexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/assignexpr.cpp index b1ceec88282..acfb400e090 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/assignexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/assignexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: int i; }; +} -void f() { +static void f() { C c; int a, b; c.i = a + b; diff --git a/cpp/ql/test/library-tests/syntax-zoo/break_labels.c b/cpp/ql/test/library-tests/syntax-zoo/break_labels.c index dcd6859547e..ca56ae52e61 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/break_labels.c +++ b/cpp/ql/test/library-tests/syntax-zoo/break_labels.c @@ -1,5 +1,5 @@ -int f(int i) { +static int f(int i) { int result = 0; if (i != 0) { result++; diff --git a/cpp/ql/test/library-tests/syntax-zoo/conditional_destructors.cpp b/cpp/ql/test/library-tests/syntax-zoo/conditional_destructors.cpp index be4f555d522..0b49874c03b 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/conditional_destructors.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/conditional_destructors.cpp @@ -26,7 +26,7 @@ class C2 { } }; -void f1(void) { +static void f1(void) { if (C1(1) == C1(2)) { ; } @@ -35,7 +35,7 @@ void f1(void) { } } -void f2(void) { +static void f2(void) { if (C2(1) == C2(2)) { ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/constmemberaccess.cpp b/cpp/ql/test/library-tests/syntax-zoo/constmemberaccess.cpp index 9a75ab5b2e9..8eaa8a2079e 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/constmemberaccess.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/constmemberaccess.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: int x; }; +} -void f() { +static void f() { C *c; int i; i = c->x; diff --git a/cpp/ql/test/library-tests/syntax-zoo/constructorinitializer.cpp b/cpp/ql/test/library-tests/syntax-zoo/constructorinitializer.cpp index ce43dedf6ed..5480912948d 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/constructorinitializer.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/constructorinitializer.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: C(int x, int y); }; +} -void f() { +static void f() { int i, j, k, l; C c(i + j, k - l); } diff --git a/cpp/ql/test/library-tests/syntax-zoo/cpp11.cpp b/cpp/ql/test/library-tests/syntax-zoo/cpp11.cpp index 90c6fa02294..469f9c2a452 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/cpp11.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/cpp11.cpp @@ -114,7 +114,7 @@ namespace synthetic_dtor_calls { } } - void f(int x) { + static void f(int x) { while (x > 0) { C c; if (x == 1) { @@ -138,7 +138,7 @@ namespace synthetic_dtor_calls { // This function is interesting because its extractor CFG has unreachable // calls to `c2.~C()` and `c3.~C()`. It's the calls that would have come from // leaving the block of `c2` by falling off the end, but no path does that. - int g(int x) { + static int g(int x) { do { C c1; if (x > 0) { diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected index 65bed58b2a6..138cc6b161c 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-consistency.expected @@ -8,47 +8,14 @@ uniqueEnclosingCallable | misc.c:210:24:210:24 | 0 | Node should have one enclosing callable but has 0. | | misc.c:210:24:210:28 | ... + ... | Node should have one enclosing callable but has 0. | | misc.c:210:28:210:28 | 1 | Node should have one enclosing callable but has 0. | +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation -| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | -| duff.c:2:12:2:12 | i | Node should have one location but has 4. | -| duff.c:2:12:2:12 | x | Node should have one location but has 4. | | file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | | file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | -| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | -| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | -| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | -| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | missingLocation | Nodes without location: 2 | uniqueNodeToString -| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | -| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | -| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | -| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | -| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | -| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | -| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | -| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | -| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | -| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | -| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | -| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | -| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | missingToString parameterCallable localFlowIsLocal @@ -76,7 +43,7 @@ postWithInFlow | VacuousDestructorCall.cpp:10:22:10:22 | i [inner post update] | PostUpdateNode should not be the target of local flow. | | allocators.cpp:4:18:4:20 | m_x [post update] | PostUpdateNode should not be the target of local flow. | | allocators.cpp:4:24:4:26 | m_y [post update] | PostUpdateNode should not be the target of local flow. | -| assignexpr.cpp:9:4:9:4 | i [post update] | PostUpdateNode should not be the target of local flow. | +| assignexpr.cpp:11:4:11:4 | i [post update] | PostUpdateNode should not be the target of local flow. | | builtin.c:34:23:34:31 | staticint [inner post update] | PostUpdateNode should not be the target of local flow. | | builtin.c:39:37:39:45 | carry_out [inner post update] | PostUpdateNode should not be the target of local flow. | | builtin.c:43:41:43:49 | staticint [inner post update] | PostUpdateNode should not be the target of local flow. | @@ -107,18 +74,18 @@ postWithInFlow | ir.cpp:342:6:342:6 | p [inner post update] | PostUpdateNode should not be the target of local flow. | | ir.cpp:428:8:428:8 | x [post update] | PostUpdateNode should not be the target of local flow. | | ir.cpp:429:8:429:8 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:643:15:643:17 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:11:644:14 | this [inner post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:17:644:19 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:645:9:645:11 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:654:11:654:14 | this [inner post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | base_s [inner post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | middle_s [inner post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | derived_s [inner post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:809:7:809:13 | call to Base | PostUpdateNode should not be the target of local flow. | -| ir.cpp:810:7:810:26 | call to Base | PostUpdateNode should not be the target of local flow. | -| ir.cpp:823:7:823:13 | call to Base | PostUpdateNode should not be the target of local flow. | -| ir.cpp:824:7:824:26 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:644:15:644:17 | m_a [post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:645:11:645:14 | this [inner post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:645:17:645:19 | m_a [post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:646:9:646:11 | m_a [post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:655:11:655:14 | this [inner post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:747:8:747:8 | base_s [inner post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:756:8:756:8 | middle_s [inner post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:765:8:765:8 | derived_s [inner post update] | PostUpdateNode should not be the target of local flow. | +| ir.cpp:811:7:811:13 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:812:7:812:26 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:825:7:825:13 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:826:7:826:26 | call to Base | PostUpdateNode should not be the target of local flow. | | misc.c:130:7:130:7 | i [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:131:9:131:9 | i [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:220:3:220:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 45741cd3fd9..fc71b416281 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -1,1465 +1,9 @@ uniqueEnclosingCallable +uniqueCallEnclosingCallable uniqueType uniqueNodeLocation -| aggregateinitializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| aggregateinitializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| allocators.cpp:14:5:14:8 | Address | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | AliasedDefinition | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | AliasedUse | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Chi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | ChiPartial | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | ChiTotal | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | EnterFunction | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | ExitFunction | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | InitializeNonLocal | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Load | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | Phi | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | ReturnValue | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | SideEffect | Node should have one location but has 4. | -| allocators.cpp:14:5:14:8 | VariableAddress | Node should have one location but has 4. | -| array_delete.cpp:5:6:5:6 | AliasedDefinition | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | AliasedUse | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Chi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | ChiPartial | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | ChiTotal | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | EnterFunction | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | ExitFunction | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | InitializeNonLocal | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | Phi | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | ReturnVoid | Node should have one location but has 14. | -| array_delete.cpp:5:6:5:6 | SideEffect | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| assignexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| break_labels.c:2:5:2:5 | AliasedDefinition | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | AliasedUse | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Chi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | ChiPartial | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | ChiTotal | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | EnterFunction | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | ExitFunction | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | InitializeNonLocal | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Phi | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | ReturnVoid | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | SideEffect | Node should have one location but has 20. | -| break_labels.c:2:5:2:5 | Unreached | Node should have one location but has 20. | -| break_labels.c:2:11:2:11 | Address | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | VariableAddress | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | i | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | -| break_labels.c:2:11:2:11 | x | Node should have one location but has 4. | -| conditional_destructors.cpp:29:6:29:7 | AliasedDefinition | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | AliasedUse | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Chi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | ChiPartial | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | ChiTotal | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | EnterFunction | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | ExitFunction | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | ReturnVoid | Node should have one location but has 2. | -| conditional_destructors.cpp:29:6:29:7 | SideEffect | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | AliasedDefinition | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | AliasedUse | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Chi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | ChiPartial | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | ChiTotal | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | EnterFunction | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | ExitFunction | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Phi | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | ReturnVoid | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | SideEffect | Node should have one location but has 2. | -| conditional_destructors.cpp:38:6:38:7 | Unreached | Node should have one location but has 2. | -| constmemberaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | -| constmemberaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| constmemberaccess.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| constructorinitializer.cpp:3:9:3:9 | i | Node should have one location but has 2. | -| constructorinitializer.cpp:3:9:3:9 | x | Node should have one location but has 2. | -| constructorinitializer.cpp:3:16:3:16 | j | Node should have one location but has 2. | -| constructorinitializer.cpp:3:16:3:16 | y | Node should have one location but has 2. | -| constructorinitializer.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| constructorinitializer.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | ChiPartial | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | ChiTotal | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | -| defconstructornewexpr.cpp:3:6:3:6 | SideEffect | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedDefinition | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | AliasedUse | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Chi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | ChiPartial | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | ChiTotal | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | EnterFunction | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | ExitFunction | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | InitializeNonLocal | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | Phi | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | ReturnVoid | Node should have one location but has 14. | -| defdestructordeleteexpr.cpp:3:6:3:6 | SideEffect | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| deleteexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| dostmt.c:8:6:8:18 | AliasedDefinition | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | AliasedUse | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | Chi | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | ChiPartial | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | ChiTotal | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | EnterFunction | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | ExitFunction | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | InitializeNonLocal | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | ReturnVoid | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | SideEffect | Node should have one location but has 4. | -| dostmt.c:8:6:8:18 | Unreached | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | AliasedDefinition | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | AliasedUse | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | Chi | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | ChiPartial | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | ChiTotal | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | EnterFunction | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | ExitFunction | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | InitializeNonLocal | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | ReturnVoid | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | SideEffect | Node should have one location but has 4. | -| dostmt.c:16:6:16:18 | Unreached | Node should have one location but has 4. | -| dostmt.c:25:6:25:18 | AliasedDefinition | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | Chi | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | ChiPartial | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | ChiTotal | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | EnterFunction | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | InitializeNonLocal | Node should have one location but has 2. | -| dostmt.c:25:6:25:18 | Unreached | Node should have one location but has 2. | -| dostmt.c:32:6:32:11 | AliasedDefinition | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | AliasedUse | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | Chi | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | ChiPartial | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | ChiTotal | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | EnterFunction | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | ExitFunction | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | InitializeNonLocal | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | ReturnVoid | Node should have one location but has 4. | -| dostmt.c:32:6:32:11 | SideEffect | Node should have one location but has 4. | -| duff.c:2:6:2:6 | AliasedDefinition | Node should have one location but has 20. | -| duff.c:2:6:2:6 | AliasedUse | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Chi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | ChiPartial | Node should have one location but has 20. | -| duff.c:2:6:2:6 | ChiTotal | Node should have one location but has 20. | -| duff.c:2:6:2:6 | EnterFunction | Node should have one location but has 20. | -| duff.c:2:6:2:6 | ExitFunction | Node should have one location but has 20. | -| duff.c:2:6:2:6 | InitializeNonLocal | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Phi | Node should have one location but has 20. | -| duff.c:2:6:2:6 | ReturnVoid | Node should have one location but has 20. | -| duff.c:2:6:2:6 | SideEffect | Node should have one location but has 20. | -| duff.c:2:6:2:6 | Unreached | Node should have one location but has 20. | -| duff.c:2:12:2:12 | Address | Node should have one location but has 4. | -| duff.c:2:12:2:12 | VariableAddress | Node should have one location but has 4. | -| duff.c:2:12:2:12 | i | Node should have one location but has 4. | -| duff.c:2:12:2:12 | i | Node should have one location but has 4. | -| duff.c:2:12:2:12 | x | Node should have one location but has 4. | -| duff.c:2:12:2:12 | x | Node should have one location but has 4. | -| dummyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| dummyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| emptyblock.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| enum.c:5:5:5:5 | AliasedDefinition | Node should have one location but has 20. | -| enum.c:5:5:5:5 | AliasedUse | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Chi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | ChiPartial | Node should have one location but has 20. | -| enum.c:5:5:5:5 | ChiTotal | Node should have one location but has 20. | -| enum.c:5:5:5:5 | EnterFunction | Node should have one location but has 20. | -| enum.c:5:5:5:5 | ExitFunction | Node should have one location but has 20. | -| enum.c:5:5:5:5 | InitializeNonLocal | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Phi | Node should have one location but has 20. | -| enum.c:5:5:5:5 | ReturnVoid | Node should have one location but has 20. | -| enum.c:5:5:5:5 | SideEffect | Node should have one location but has 20. | -| enum.c:5:5:5:5 | Unreached | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| exprstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| fieldaccess.cpp:3:7:3:7 | x | Node should have one location but has 2. | -| fieldaccess.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| fieldaccess.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 0) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 1) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 2) | Node should have one location but has 0. | -| file://:0:0:0:0 | (unnamed parameter 3) | Node should have one location but has 0. | -| file://:0:0:0:0 | *(unnamed parameter 2) | Node should have one location but has 0. | -| file://:0:0:0:0 | Address | Node should have one location but has 0. | -| file://:0:0:0:0 | Address | Node should have one location but has 0. | -| file://:0:0:0:0 | Address | Node should have one location but has 0. | -| file://:0:0:0:0 | Address | Node should have one location but has 0. | -| file://:0:0:0:0 | Load | Node should have one location but has 0. | -| file://:0:0:0:0 | Load | Node should have one location but has 0. | -| file://:0:0:0:0 | ReturnIndirection | Node should have one location but has 0. | -| file://:0:0:0:0 | SideEffect | Node should have one location but has 0. | -| file://:0:0:0:0 | VariableAddress | Node should have one location but has 0. | -| forstmt.cpp:1:6:1:7 | AliasedDefinition | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | AliasedUse | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Chi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | ChiPartial | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | ChiTotal | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | EnterFunction | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | ExitFunction | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | InitializeNonLocal | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | ReturnVoid | Node should have one location but has 2. | -| forstmt.cpp:1:6:1:7 | SideEffect | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | AliasedDefinition | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | AliasedUse | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Chi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | ChiPartial | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | ChiTotal | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | EnterFunction | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | ExitFunction | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | InitializeNonLocal | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Phi | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | ReturnVoid | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | SideEffect | Node should have one location but has 2. | -| forstmt.cpp:8:6:8:7 | Unreached | Node should have one location but has 2. | -| ifelsestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | ChiPartial | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | ChiTotal | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | SideEffect | Node should have one location but has 3. | -| ifelsestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | AliasedDefinition | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | AliasedUse | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | Chi | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | ChiPartial | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | ChiTotal | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | EnterFunction | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | ExitFunction | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | InitializeNonLocal | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | ReturnVoid | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | SideEffect | Node should have one location but has 3. | -| ifelsestmt.c:11:6:11:19 | Unreached | Node should have one location but has 3. | -| ifelsestmt.c:19:6:19:18 | AliasedDefinition | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | AliasedUse | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | Chi | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | ChiPartial | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | ChiTotal | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | EnterFunction | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | ExitFunction | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | InitializeNonLocal | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | ReturnVoid | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | SideEffect | Node should have one location but has 4. | -| ifelsestmt.c:19:6:19:18 | Unreached | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | AliasedDefinition | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | AliasedUse | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | Chi | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | ChiPartial | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | ChiTotal | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | EnterFunction | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | ExitFunction | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | InitializeNonLocal | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | ReturnVoid | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | SideEffect | Node should have one location but has 4. | -| ifelsestmt.c:29:6:29:18 | Unreached | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | AliasedDefinition | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | AliasedUse | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | Chi | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | ChiPartial | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | ChiTotal | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | EnterFunction | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | ExitFunction | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | InitializeNonLocal | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | ReturnVoid | Node should have one location but has 4. | -| ifelsestmt.c:37:6:37:11 | SideEffect | Node should have one location but has 4. | -| ifelsestmt.c:37:17:37:17 | Address | Node should have one location but has 2. | -| ifelsestmt.c:37:17:37:17 | VariableAddress | Node should have one location but has 2. | -| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | -| ifelsestmt.c:37:17:37:17 | x | Node should have one location but has 2. | -| ifelsestmt.c:37:24:37:24 | Address | Node should have one location but has 2. | -| ifelsestmt.c:37:24:37:24 | VariableAddress | Node should have one location but has 2. | -| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | -| ifelsestmt.c:37:24:37:24 | y | Node should have one location but has 2. | -| ifstmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | ChiPartial | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | ChiTotal | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | SideEffect | Node should have one location but has 3. | -| ifstmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | ChiPartial | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | ChiTotal | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | SideEffect | Node should have one location but has 3. | -| ifstmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | -| ifstmt.c:14:6:14:18 | AliasedDefinition | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | AliasedUse | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | Chi | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | ChiPartial | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | ChiTotal | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | EnterFunction | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | ExitFunction | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | InitializeNonLocal | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | ReturnVoid | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | SideEffect | Node should have one location but has 4. | -| ifstmt.c:14:6:14:18 | Unreached | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | AliasedDefinition | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | AliasedUse | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | Chi | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | ChiPartial | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | ChiTotal | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | EnterFunction | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | ExitFunction | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | InitializeNonLocal | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | ReturnVoid | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | SideEffect | Node should have one location but has 4. | -| ifstmt.c:21:6:21:18 | Unreached | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | AliasedDefinition | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | AliasedUse | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | Chi | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | ChiPartial | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | ChiTotal | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | EnterFunction | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | ExitFunction | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | InitializeNonLocal | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | ReturnVoid | Node should have one location but has 4. | -| ifstmt.c:27:6:27:11 | SideEffect | Node should have one location but has 4. | -| ifstmt.c:27:17:27:17 | Address | Node should have one location but has 2. | -| ifstmt.c:27:17:27:17 | VariableAddress | Node should have one location but has 2. | -| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | -| ifstmt.c:27:17:27:17 | x | Node should have one location but has 2. | -| ifstmt.c:27:24:27:24 | Address | Node should have one location but has 2. | -| ifstmt.c:27:24:27:24 | VariableAddress | Node should have one location but has 2. | -| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | -| ifstmt.c:27:24:27:24 | y | Node should have one location but has 2. | -| initializer.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| initializer.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| landexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| lorexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| ltrbinopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| membercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| membercallexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| membercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | -| membercallexpr_args.cpp:4:14:4:14 | x | Node should have one location but has 2. | -| membercallexpr_args.cpp:4:21:4:21 | y | Node should have one location but has 2. | -| membercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | ChiPartial | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | ChiTotal | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | -| membercallexpr_args.cpp:7:6:7:6 | SideEffect | Node should have one location but has 14. | -| newexpr.cpp:3:9:3:9 | i | Node should have one location but has 2. | -| newexpr.cpp:3:9:3:9 | x | Node should have one location but has 2. | -| newexpr.cpp:3:16:3:16 | j | Node should have one location but has 2. | -| newexpr.cpp:3:16:3:16 | y | Node should have one location but has 2. | -| newexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| newexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| no_dynamic_init.cpp:9:5:9:8 | Address | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | AliasedDefinition | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | AliasedUse | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Chi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | ChiPartial | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | ChiTotal | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | EnterFunction | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | ExitFunction | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | InitializeNonLocal | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Load | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | Phi | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | ReturnValue | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | SideEffect | Node should have one location but has 4. | -| no_dynamic_init.cpp:9:5:9:8 | VariableAddress | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| nodefaultswitchstmt.c:1:12:1:12 | Address | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | -| nonmembercallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | -| nonmembercallexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 2. | -| nonmembercallexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | ChiPartial | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | ChiTotal | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | SideEffect | Node should have one location but has 20. | -| nonmembercallexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | AliasedDefinition | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | AliasedUse | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Chi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | ChiPartial | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | ChiTotal | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | EnterFunction | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | ExitFunction | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | InitializeNonLocal | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Phi | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | ReturnVoid | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | SideEffect | Node should have one location but has 20. | -| nonmemberfp2callexpr.c:3:6:3:6 | Unreached | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| nonmemberfpcallexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| parameterinitializer.cpp:18:5:18:8 | Address | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | AliasedDefinition | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | AliasedUse | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Chi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | ChiPartial | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | ChiTotal | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | EnterFunction | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | ExitFunction | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | InitializeNonLocal | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Load | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | Phi | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | ReturnValue | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | SideEffect | Node should have one location but has 4. | -| parameterinitializer.cpp:18:5:18:8 | VariableAddress | Node should have one location but has 4. | -| pmcallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| pmcallexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| questionexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| questionexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| revsubscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 2. | -| revsubscriptexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 2. | -| staticmembercallexpr.cpp:6:6:6:6 | AliasedDefinition | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | AliasedUse | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Chi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | ChiPartial | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | ChiTotal | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | EnterFunction | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | ExitFunction | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | InitializeNonLocal | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | ReturnVoid | Node should have one location but has 14. | -| staticmembercallexpr.cpp:6:6:6:6 | SideEffect | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:3:6:3:6 | d | Node should have one location but has 2. | -| staticmembercallexpr_args.cpp:4:21:4:21 | x | Node should have one location but has 2. | -| staticmembercallexpr_args.cpp:4:28:4:28 | y | Node should have one location but has 2. | -| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedDefinition | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | AliasedUse | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Chi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | ChiPartial | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | ChiTotal | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | EnterFunction | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | ExitFunction | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | Phi | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | ReturnVoid | Node should have one location but has 14. | -| staticmembercallexpr_args.cpp:7:6:7:6 | SideEffect | Node should have one location but has 14. | -| stream_it.cpp:16:5:16:8 | Address | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | AliasedDefinition | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | AliasedUse | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Chi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | ChiPartial | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | ChiTotal | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | EnterFunction | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | ExitFunction | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | InitializeNonLocal | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Load | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | Phi | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | ReturnValue | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | SideEffect | Node should have one location but has 4. | -| stream_it.cpp:16:5:16:8 | VariableAddress | Node should have one location but has 4. | -| subscriptexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| subscriptexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| switchstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| switchstmt.c:1:12:1:12 | Address | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | VariableAddress | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | i | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | -| switchstmt.c:1:12:1:12 | x | Node should have one location but has 4. | -| tinyforstmt.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| tinyforstmt.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | AliasedDefinition | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | AliasedUse | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Chi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | ChiPartial | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | ChiTotal | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | EnterFunction | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | ExitFunction | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | InitializeNonLocal | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Phi | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | ReturnVoid | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | SideEffect | Node should have one location but has 20. | -| unaryopexpr.c:1:6:1:6 | Unreached | Node should have one location but has 20. | -| whilestmt.c:1:6:1:19 | AliasedDefinition | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | AliasedUse | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | Chi | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | ChiPartial | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | ChiTotal | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | EnterFunction | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | ExitFunction | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | InitializeNonLocal | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | ReturnVoid | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | SideEffect | Node should have one location but has 3. | -| whilestmt.c:1:6:1:19 | Unreached | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | AliasedDefinition | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | AliasedUse | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | Chi | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | ChiPartial | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | ChiTotal | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | EnterFunction | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | ExitFunction | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | InitializeNonLocal | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | ReturnVoid | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | SideEffect | Node should have one location but has 3. | -| whilestmt.c:8:6:8:19 | Unreached | Node should have one location but has 3. | -| whilestmt.c:15:6:15:18 | AliasedDefinition | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | AliasedUse | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | Chi | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | ChiPartial | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | ChiTotal | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | EnterFunction | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | ExitFunction | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | InitializeNonLocal | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | ReturnVoid | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | SideEffect | Node should have one location but has 4. | -| whilestmt.c:15:6:15:18 | Unreached | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | AliasedDefinition | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | AliasedUse | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | Chi | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | ChiPartial | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | ChiTotal | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | EnterFunction | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | ExitFunction | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | InitializeNonLocal | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | ReturnVoid | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | SideEffect | Node should have one location but has 4. | -| whilestmt.c:23:6:23:18 | Unreached | Node should have one location but has 4. | -| whilestmt.c:32:6:32:18 | AliasedDefinition | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | Chi | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | ChiPartial | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | ChiTotal | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | EnterFunction | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | InitializeNonLocal | Node should have one location but has 2. | -| whilestmt.c:32:6:32:18 | Unreached | Node should have one location but has 2. | -| whilestmt.c:39:6:39:11 | AliasedDefinition | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | AliasedUse | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | Chi | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | ChiPartial | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | ChiTotal | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | EnterFunction | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | ExitFunction | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | InitializeNonLocal | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | ReturnVoid | Node should have one location but has 4. | -| whilestmt.c:39:6:39:11 | SideEffect | Node should have one location but has 4. | missingLocation -| Nodes without location: 34 | uniqueNodeToString -| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | -| break_labels.c:2:11:2:11 | i | Node should have one toString but has 2. | -| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | -| break_labels.c:2:11:2:11 | x | Node should have one toString but has 2. | -| break_labels.c:4:9:4:9 | i | Node should have one toString but has 2. | -| break_labels.c:4:9:4:9 | x | Node should have one toString but has 2. | -| break_labels.c:6:16:6:16 | i | Node should have one toString but has 2. | -| break_labels.c:6:16:6:16 | x | Node should have one toString but has 2. | -| break_labels.c:7:17:7:17 | i | Node should have one toString but has 2. | -| break_labels.c:7:17:7:17 | x | Node should have one toString but has 2. | -| constructorinitializer.cpp:3:9:3:9 | i | Node should have one toString but has 2. | -| constructorinitializer.cpp:3:9:3:9 | x | Node should have one toString but has 2. | -| constructorinitializer.cpp:3:16:3:16 | j | Node should have one toString but has 2. | -| constructorinitializer.cpp:3:16:3:16 | y | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | i | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | -| duff.c:2:12:2:12 | x | Node should have one toString but has 2. | -| duff.c:3:14:3:14 | i | Node should have one toString but has 2. | -| duff.c:3:14:3:14 | x | Node should have one toString but has 2. | -| duff.c:4:13:4:13 | i | Node should have one toString but has 2. | -| duff.c:4:13:4:13 | x | Node should have one toString but has 2. | -| newexpr.cpp:3:9:3:9 | i | Node should have one toString but has 2. | -| newexpr.cpp:3:9:3:9 | x | Node should have one toString but has 2. | -| newexpr.cpp:3:16:3:16 | j | Node should have one toString but has 2. | -| newexpr.cpp:3:16:3:16 | y | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | -| nodefaultswitchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | i | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| switchstmt.c:1:12:1:12 | x | Node should have one toString but has 2. | -| switchstmt.c:2:14:2:14 | i | Node should have one toString but has 2. | -| switchstmt.c:2:14:2:14 | x | Node should have one toString but has 2. | missingToString parameterCallable localFlowIsLocal @@ -1471,1272 +15,39 @@ localCallNodes postIsNotPre postHasUniquePre uniquePostUpdate +| cpp11.cpp:82:17:82:17 | this indirection | Node has multiple PostUpdateNodes. | +| cpp11.cpp:82:17:82:55 | [...](...){...} indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:514:10:514:11 | definition of r2 indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:515:10:515:11 | definition of r3 indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:515:10:515:11 | definition of r3 indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:516:10:516:11 | definition of r4 indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:516:10:516:11 | definition of r4 indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:659:5:659:5 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:659:5:659:5 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:747:8:747:8 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:750:3:750:6 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:759:3:759:8 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:768:3:768:9 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:777:3:777:11 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:786:3:786:11 | this indirection | Node has multiple PostUpdateNodes. | +| ir.cpp:795:3:795:11 | this indirection | Node has multiple PostUpdateNodes. | +| static_init_templates.cpp:240:7:240:7 | this indirection | Node has multiple PostUpdateNodes. | postIsInSameCallable reverseRead argHasPostUpdate postWithInFlow -| FunctionTryStmt.cpp:2:3:2:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| VacuousDestructorCall.cpp:10:21:10:22 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| VacuousDestructorCall.cpp:10:22:10:22 | i [post update] | PostUpdateNode should not be the target of local flow. | -| abortingfunctions.cpp:49:5:49:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aggregateinitializer.c:3:6:3:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| aggregateinitializer.c:3:11:3:27 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| aggregateinitializer.c:3:11:3:27 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:3:30:3:35 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:3:38:3:43 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:18:4:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:18:4:20 | m_x [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:24:4:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:4:24:4:26 | m_y [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:7:56:7:70 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:16:8:16:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:16:14:16:43 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:16:14:16:43 | new [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:16:14:16:43 | new [post update] | PostUpdateNode should not be the target of local flow. | -| allocators.cpp:18:1:18:1 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| assignexpr.cpp:9:4:9:4 | i [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:10:7:10:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:15:10:15:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:16:5:16:5 | s [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:19:10:19:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| bad_asts.cpp:27:11:27:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:3:9:3:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:5:9:5:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:7:17:7:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:8:17:8:22 | result [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:18:9:18:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:20:9:20:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:20:24:20:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| break_labels.c:27:9:27:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:8:3:8:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:12:3:12:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:18:14:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:23:14:37 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:23:14:37 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:23:14:37 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:14:23:14:37 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:15:18:15:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:20:3:20:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:21:3:21:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:22:3:22:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:34:3:34:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:34:22:34:31 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:34:22:34:31 | (volatile void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:34:23:34:31 | staticint [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:39:3:39:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:39:36:39:45 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:39:37:39:45 | carry_out [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:43:40:43:49 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:43:41:43:49 | staticint [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:45:3:45:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:48:2:48:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:51:3:51:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:51:29:51:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:51:30:51:38 | staticint [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:54:3:54:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:54:28:54:38 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:54:29:54:38 | atomic_int [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.c:56:3:56:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:5:5:5:34 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:10:10:10:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:10:24:10:24 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:10:24:10:24 | i [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:14:11:14:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:15:31:15:35 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:15:32:15:35 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| builtin.cpp:15:33:15:35 | ptr [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decl_int.cpp:2:7:2:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decl_int.cpp:3:9:3:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:5:3:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:5:3:9 | m_ptr [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:13:3:22 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:3:13:3:22 | new [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:9:5:9:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:16:6:16:20 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:16:6:16:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:26:10:26:24 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:26:10:26:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:41:9:41:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:41:9:41:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:16:48:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:16:48:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:27:48:31 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:27:48:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:39:48:53 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| condition_decls.cpp:48:39:48:53 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:6:13:6:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:6:13:6:15 | val [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:10:9:10:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:18:13:18:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:18:13:18:15 | val [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:25:9:25:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:30:9:30:13 | call to C1 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:30:9:30:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:30:18:30:22 | call to C1 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:30:18:30:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:33:9:33:13 | call to C1 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:33:9:33:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:33:18:33:22 | call to C1 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:33:18:33:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:39:9:39:13 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:39:9:39:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:39:18:39:22 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:39:18:39:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:42:9:42:13 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:42:9:42:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:42:18:42:22 | call to C2 [post update] | PostUpdateNode should not be the target of local flow. | -| conditional_destructors.cpp:42:18:42:22 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| constmemberaccess.cpp:9:2:9:2 | i [post update] | PostUpdateNode should not be the target of local flow. | -| constructorinitializer.cpp:8:4:8:4 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| constructorinitializer.cpp:8:4:8:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:6:5:8:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:6:5:8:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:6:5:8:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:6:5:8:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:7:7:7:8 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:7:7:7:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:7:7:7:8 | el [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__begin) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__begin) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__begin) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__begin) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:28:21:28:34 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:29:7:29:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:31:5:31:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:36:5:36:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:56:14:56:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:56:14:56:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:60:15:60:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:60:15:60:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:65:10:65:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:65:19:65:45 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:65:20:65:20 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:65:35:65:43 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:77:19:77:21 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:77:19:77:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:11:82:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:11:82:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:17 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:17 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:55 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:17:82:55 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:45:82:48 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:45:82:48 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:51:82:51 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:82:51:82:51 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:88:25:88:30 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:88:25:88:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:88:33:88:38 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:88:33:88:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:99:5:99:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:108:5:108:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:148:13:148:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:150:13:150:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp11.cpp:169:7:169:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:15:5:15:45 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:15:5:15:45 | new [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:10:19:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:10:19:10 | p [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:13:19:13 | 1 [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:13:19:13 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:13:19:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:16:19:16 | 2 [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:16:19:16 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| cpp17.cpp:19:16:19:16 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| defdestructordeleteexpr.cpp:4:5:4:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| defdestructordeleteexpr.cpp:4:9:4:15 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| defdestructordeleteexpr.cpp:4:9:4:15 | new [post update] | PostUpdateNode should not be the target of local flow. | -| deleteexpr.cpp:7:5:7:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| deleteexpr.cpp:7:9:7:15 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| deleteexpr.cpp:7:9:7:15 | new [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:11:7:11:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:16:5:16:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:19:3:19:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:50:9:50:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:50:9:50:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:51:16:51:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:51:22:51:56 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:51:22:51:56 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:51:36:51:38 | call to C [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:51:36:51:38 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| destructors.cpp:52:7:52:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dostmt.c:33:7:33:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| dostmt.c:35:7:35:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff2.c:3:9:3:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff2.c:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff2.c:17:9:17:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff2.c:21:16:21:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff.c:3:9:3:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| duff.c:13:24:13:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ellipsisexceptionhandler.cpp:6:4:6:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ellipsisexceptionhandler.cpp:16:18:16:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| exceptionhandler.cpp:7:2:7:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| exceptionhandler.cpp:14:4:14:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| fieldaccess.cpp:9:2:9:2 | i [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (Base *)... [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (Middle *)... [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| file://:0:0:0:0 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:2:14:2:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:2:29:2:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:9:14:9:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:14:14:14:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:14:27:14:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:19:14:19:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| forstmt.cpp:19:28:19:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| initializer.c:3:6:3:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:2:10:2:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:3:10:3:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:5:17:5:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:6:17:6:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:8:19:8:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:9:19:9:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:11:11:11:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:12:20:12:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:14:9:14:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:15:18:15:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:17:10:17:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:18:19:18:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:20:15:20:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:21:15:21:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:22:24:22:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:23:24:23:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:25:10:25:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:26:10:26:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:28:13:28:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:29:13:29:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:31:14:31:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:32:14:32:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:34:11:34:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:35:11:35:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:36:11:36:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:38:12:38:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:39:12:39:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:40:12:40:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:44:9:44:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:45:11:45:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:46:5:46:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:47:5:47:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:53:5:53:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:54:5:54:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:55:5:55:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:56:5:56:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:57:5:57:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:59:5:59:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:60:5:60:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:61:5:61:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:63:5:63:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:64:5:64:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:66:5:66:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:68:5:68:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:69:5:69:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:70:5:70:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:71:5:71:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:72:5:72:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:74:5:74:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:75:5:75:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:76:5:76:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:78:5:78:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:79:5:79:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:81:5:81:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:82:5:82:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:83:5:83:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:84:5:84:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:90:5:90:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:91:5:91:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:92:5:92:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:93:5:93:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:94:5:94:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:95:5:95:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:101:5:101:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:101:11:101:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:102:5:102:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:102:11:102:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:103:5:103:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:103:9:103:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:104:5:104:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:104:9:104:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:110:5:110:5 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:110:13:110:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:111:5:111:5 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:111:13:111:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:117:5:117:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:118:5:118:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:119:5:119:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:120:5:120:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:122:5:122:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:124:5:124:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:125:5:125:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:126:5:126:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:127:5:127:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:129:5:129:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:130:5:130:5 | z [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:136:5:136:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:137:5:137:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:138:5:138:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:139:5:139:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:140:5:140:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:141:5:141:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:147:5:147:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:147:11:147:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:148:5:148:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:148:11:148:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:149:5:149:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:149:9:149:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:150:5:150:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:150:9:150:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:157:5:157:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:158:5:158:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:159:5:159:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:160:5:160:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:162:5:162:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:164:5:164:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:165:5:165:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:167:5:167:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:168:5:168:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:174:5:174:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:175:5:175:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:177:5:177:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:177:5:177:5 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:177:5:177:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:178:5:178:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:178:7:178:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:178:7:178:7 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:181:5:181:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:182:5:182:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:183:5:183:5 | a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:183:5:183:5 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:183:5:183:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:184:5:184:8 | access to array [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:184:7:184:7 | a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:184:7:184:7 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:188:10:188:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:189:14:189:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:190:13:190:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:196:5:196:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:197:5:197:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:198:5:198:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:199:5:199:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:200:5:200:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:201:5:201:5 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:207:5:207:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:207:11:207:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:208:5:208:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:208:11:208:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:209:5:209:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:209:9:209:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:210:5:210:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:210:9:210:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:215:9:215:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:216:5:216:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:219:11:219:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:220:5:220:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:223:5:223:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:226:10:226:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:227:5:227:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:232:9:232:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:236:5:236:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:244:9:244:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:248:9:248:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:250:9:250:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:255:9:255:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:261:9:261:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:273:14:273:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:279:9:279:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:286:9:286:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:287:13:287:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:293:14:293:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:299:14:299:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:299:22:299:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:305:9:305:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:306:20:306:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:312:14:312:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:312:29:312:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:318:14:318:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:318:29:318:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:326:14:326:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:326:29:326:29 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:334:14:334:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:342:5:342:6 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:342:6:342:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:342:6:342:6 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:343:5:343:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:349:5:349:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:356:9:356:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:365:9:365:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:377:5:377:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:381:5:381:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:390:13:390:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:395:13:395:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:399:13:399:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:401:13:401:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:405:13:405:13 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:423:5:423:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:428:8:428:8 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:429:8:429:8 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:430:10:430:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:436:9:436:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:440:9:440:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:443:9:443:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:450:9:450:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:454:9:454:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:457:9:457:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:464:9:464:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:468:9:468:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:471:9:471:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:477:5:477:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:477:9:477:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:477:9:477:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:478:5:478:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:478:9:478:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:478:9:478:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:479:5:479:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:479:11:479:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:479:11:479:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:483:9:483:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:483:13:483:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:483:13:483:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:489:6:489:14 | ... ? ... : ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:489:6:489:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:489:6:489:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:489:6:489:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:497:10:497:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:498:10:498:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:499:5:499:5 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:500:5:500:5 | q [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:504:16:504:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:504:16:504:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:505:16:505:21 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:505:16:505:21 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:506:16:506:18 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:506:16:506:18 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:508:9:508:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:509:9:509:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:513:14:513:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:513:14:513:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:14:514:26 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:17:514:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:514:17:514:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:17:515:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:17:515:24 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:27:515:34 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:515:27:515:34 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:17:516:21 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:17:516:21 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:24:516:28 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:516:24:516:28 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:520:9:520:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:520:16:520:18 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:9:521:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:16:521:27 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:16:521:27 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:521:16:521:27 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:522:9:522:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:522:16:522:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:522:16:522:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:531:7:531:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:531:11:531:16 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:540:5:540:5 | y [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:545:9:545:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:548:5:548:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:552:5:552:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:563:13:563:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:565:13:565:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:567:13:567:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:572:10:572:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:573:10:573:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:574:10:574:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:576:10:576:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:576:16:576:18 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:577:10:577:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:577:16:577:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:577:16:577:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:578:10:578:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:578:16:578:24 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:578:16:578:24 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:579:10:579:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:579:16:579:21 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:585:32:585:39 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:585:32:585:39 | string [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:591:11:591:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:592:5:592:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:593:5:593:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:594:5:594:7 | pfn [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:616:12:616:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:616:12:616:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:617:12:617:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:617:12:617:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:618:12:618:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:619:12:619:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:619:12:619:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:631:9:631:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:635:9:635:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:639:9:639:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:643:9:643:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:643:15:643:17 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:11:644:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:11:644:14 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:644:17:644:19 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:645:9:645:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:645:9:645:11 | m_a [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:647:9:647:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:648:9:648:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:649:9:649:9 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:653:9:653:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:653:9:653:12 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:654:10:654:14 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:654:11:654:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:654:11:654:14 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:655:9:655:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:655:9:655:30 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:659:9:659:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:660:9:660:14 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:661:9:661:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:662:9:662:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:662:9:662:19 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:663:5:663:5 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:663:5:663:5 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:676:5:676:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:680:5:680:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:686:10:686:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:687:10:687:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:688:19:688:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:693:9:693:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:694:7:694:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:698:8:698:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:699:8:699:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:705:3:705:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:705:10:705:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:705:10:705:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:709:3:709:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:716:5:716:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:716:12:716:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:721:3:721:54 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:721:41:721:47 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:721:41:721:47 | (void *)... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:726:9:726:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:728:7:728:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:733:5:733:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:736:5:736:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:736:5:736:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:745:8:745:8 | base_s [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:748:10:748:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:748:10:748:10 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | middle_s [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:754:8:754:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:3:757:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:12:757:12 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:12:757:12 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:12:757:12 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:757:12:757:12 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | & ... [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | derived_s [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:763:8:763:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:3:766:9 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:13:766:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:13:766:13 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:13:766:13 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:766:13:766:13 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:3:775:11 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:15:775:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:15:775:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:15:775:15 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:775:15:775:15 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:3:784:11 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:15:784:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:15:784:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:15:784:15 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:784:15:784:15 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:3:793:11 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:793:15:793:15 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:800:8:800:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:800:8:800:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:801:10:801:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:801:10:801:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:802:11:802:11 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:802:11:802:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:804:9:804:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:805:11:805:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:806:12:806:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:808:3:808:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:809:3:809:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:809:7:809:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:809:7:809:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:810:3:810:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:810:7:810:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:810:7:810:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:811:3:811:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:812:3:812:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:813:3:813:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:814:3:814:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:816:3:816:3 | m [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:817:3:817:3 | m [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:818:3:818:4 | pm [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:819:3:819:4 | pm [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:820:3:820:4 | pm [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:822:3:822:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:823:3:823:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:823:7:823:13 | call to Base [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:823:7:823:13 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:824:3:824:3 | b [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:824:7:824:26 | call to Base [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:824:7:824:26 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:825:3:825:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:826:3:826:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:827:3:827:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:828:3:828:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:830:3:830:3 | d [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:831:3:831:3 | d [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:832:3:832:4 | pd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:833:3:833:4 | pd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:834:3:834:4 | pd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:836:14:836:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:837:14:837:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:838:3:838:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:839:3:839:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:846:8:846:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:846:8:846:8 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:846:8:846:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:850:19:850:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:850:19:850:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:851:22:851:22 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:851:22:851:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:853:20:853:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:854:23:854:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:857:3:857:4 | pb [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:858:20:858:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:860:3:860:4 | pd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:861:23:861:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:863:9:863:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:864:15:864:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:867:1:867:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:867:1:867:14 | this [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:873:15:873:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:874:3:874:3 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:875:3:875:3 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:876:3:876:3 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:877:10:877:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:878:16:878:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:879:16:879:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:880:3:880:4 | pa [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:884:3:884:3 | p [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:885:3:885:5 | pfn [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:891:22:891:25 | args [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:891:22:891:25 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:893:22:893:26 | args2 [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:893:22:893:26 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:894:10:894:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:894:31:894:34 | args [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:894:31:894:34 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:895:9:895:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:895:30:895:33 | args [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:895:30:895:33 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:905:8:905:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:906:7:906:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:906:11:906:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:943:3:943:11 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:943:3:943:11 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:944:3:944:14 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:944:3:944:14 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:944:3:944:14 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:945:3:945:27 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:945:3:945:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:945:3:945:27 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:947:3:947:25 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:947:3:947:25 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:7:962:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:962:17:962:47 | PointerAdd [post update] | PostUpdateNode should not be the target of local flow. | -| ir.cpp:963:3:963:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:28:5:28:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:29:5:29:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:30:5:30:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:31:5:31:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:32:5:32:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:33:5:33:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:34:5:34:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:35:5:35:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:36:5:36:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:37:5:37:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:39:5:39:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ltrbinopexpr.c:40:5:40:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:10:5:10:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:11:5:11:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:18:5:18:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:19:5:19:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:20:7:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:21:5:21:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:23:9:23:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:25:9:25:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:28:9:28:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:30:9:30:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:33:9:33:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:35:9:35:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:38:9:38:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:40:9:40:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:45:9:45:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:48:9:48:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:51:9:51:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:54:9:54:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:57:9:57:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:60:9:60:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:62:9:62:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:62:24:62:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:64:19:64:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:66:9:66:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:66:18:66:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:93:5:93:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:93:9:93:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:93:9:93:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:94:5:94:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:94:9:94:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:94:9:94:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:123:9:123:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:124:9:124:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:124:25:124:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:126:5:126:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:129:5:129:6 | sp [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:130:7:130:7 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:131:5:131:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:131:9:131:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:132:5:132:5 | j [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:133:5:133:5 | j [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:135:5:135:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:136:5:136:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:137:5:137:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:147:5:147:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:154:23:154:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:154:31:154:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:154:31:154:36 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:154:39:154:44 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:154:39:154:44 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:156:31:159:5 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:156:31:159:5 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:160:31:160:33 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:160:31:160:33 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:165:5:165:5 | i [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:178:17:178:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:179:17:179:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:188:5:188:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:200:24:200:27 | args [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:200:24:200:27 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:208:1:208:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:210:5:210:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:216:3:216:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:220:3:220:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:220:4:220:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:220:4:220:5 | sp [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:220:9:223:3 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:220:9:223:3 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:228:7:228:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:229:7:229:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:230:2:230:3 | p1 [post update] | PostUpdateNode should not be the target of local flow. | -| misc.c:231:2:231:40 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| modeled-functions.cpp:6:19:6:19 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| modeled-functions.cpp:6:19:6:19 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. | -| modeled-functions.cpp:6:22:6:22 | 0 [post update] | PostUpdateNode should not be the target of local flow. | -| modeled-functions.cpp:6:22:6:22 | (unsigned long *)... [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:13:8:13:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:14:8:14:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:28:3:28:8 | result [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:28:18:28:23 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | -| ms_assume.cpp:34:1:34:1 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_except.cpp:7:13:7:13 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_except.cpp:14:13:14:13 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_except.cpp:17:13:17:13 | x [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:11:7:11:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:11:7:11:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:14:11:14:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:14:11:14:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:16:13:16:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:18:11:18:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:18:11:18:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:21:11:21:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:21:11:21:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:24:7:24:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:24:7:24:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:28:7:28:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:28:7:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:31:11:31:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:31:11:31:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:33:13:33:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:35:11:35:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:35:11:35:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:38:11:38:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:38:11:38:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:41:7:41:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:41:7:41:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:48:5:48:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:48:5:48:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ms_try_mix.cpp:51:5:51:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| newexpr.cpp:8:2:8:20 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. | -| newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. | -| no_dynamic_init.cpp:11:3:11:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:19:11:19:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:20:11:20:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:21:11:21:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:26:26:26:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:26:31:26:53 | Call [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. | -| ops.cpp:26:31:26:53 | new [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:8:12:8:21 | (char *)... [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:8:12:8:21 | Got %d\n [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:8:12:8:21 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:25:5:25:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:25:5:25:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:27:3:27:6 | my_c [post update] | PostUpdateNode should not be the target of local flow. | -| parameterinitializer.cpp:30:5:30:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:23:6:23:8 | obj [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:26:5:26:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:27:5:27:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:27:12:27:14 | obj [post update] | PostUpdateNode should not be the target of local flow. | -| pointer_to_member.cpp:29:5:29:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:69:9:69:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:78:9:78:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:87:9:87:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:96:13:96:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:105:13:105:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:114:13:114:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:123:13:123:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:132:13:132:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:165:9:165:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:172:9:172:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:179:9:179:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:186:9:186:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| pruning.c:193:9:193:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| questionexpr.c:3:2:3:2 | x [post update] | PostUpdateNode should not be the target of local flow. | -| questionexpr.c:3:6:3:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| questionexpr.c:3:6:3:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:6:7:6:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:7:13:7:13 | p [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:8:5:8:9 | count [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:10:3:10:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:14:7:14:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:15:13:15:13 | p [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:16:5:16:9 | count [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:18:3:18:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:22:7:22:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:23:13:23:13 | p [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:24:5:24:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:25:5:25:9 | count [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:27:3:27:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:31:7:31:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:32:7:32:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:33:8:33:8 | i [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:33:22:33:22 | i [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:34:5:34:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:36:3:36:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:40:7:40:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:41:7:41:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:42:8:42:8 | i [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:42:22:42:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:43:5:43:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:45:3:45:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:49:7:49:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:50:7:50:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:51:8:51:8 | i [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:51:24:51:24 | i [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:52:5:52:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:54:3:54:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:60:7:60:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:63:3:63:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:69:7:69:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:72:3:72:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:78:7:78:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:82:7:82:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:85:3:85:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:91:7:91:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:93:5:93:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:95:3:95:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:100:3:100:3 | c [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:102:5:102:8 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:102:6:102:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:102:6:102:6 | p [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:102:6:102:8 | ... ++ [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:105:5:105:5 | c [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:107:7:107:10 | * ... [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:107:8:107:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:107:8:107:8 | p [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:107:8:107:10 | ... ++ [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:110:7:110:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:112:3:112:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:119:3:119:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:119:10:119:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:123:14:123:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:126:22:126:27 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:127:6:127:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:130:4:130:12 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:135:17:135:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:136:16:136:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:137:16:137:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:138:7:138:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:139:3:139:42 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:144:7:144:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:145:7:145:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:146:7:146:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:147:7:147:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:148:8:148:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:149:18:149:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:150:3:150:37 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:154:3:154:41 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:154:10:154:40 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:154:10:154:40 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:159:7:159:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:162:9:162:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:163:9:163:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:164:5:164:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:167:9:167:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:168:9:168:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:169:5:169:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:172:9:172:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:173:9:173:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:174:5:174:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:177:9:177:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:178:9:178:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:179:5:179:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:182:9:182:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:183:9:183:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:184:5:184:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:187:9:187:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:188:9:188:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:189:5:189:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:192:3:192:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:198:7:198:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:201:9:201:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:202:5:202:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:205:9:205:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:206:5:206:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:209:9:209:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:210:5:210:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:213:9:213:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:214:5:214:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:217:9:217:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:218:5:218:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:221:3:221:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:226:7:226:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:229:9:229:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:230:5:230:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:233:9:233:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:234:5:234:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:237:9:237:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:238:5:238:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:241:9:241:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:242:5:242:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:245:9:245:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:246:5:246:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:249:3:249:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:254:7:254:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:257:9:257:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:258:5:258:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:261:9:261:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:262:5:262:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:265:9:265:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:266:5:266:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:269:9:269:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:270:5:270:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:273:9:273:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:274:5:274:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:277:3:277:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:282:7:282:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:285:9:285:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:286:5:286:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:289:9:289:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:290:5:290:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:293:9:293:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:294:5:294:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:297:9:297:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:298:5:298:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:301:9:301:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:302:5:302:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:305:3:305:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:310:7:310:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:313:9:313:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:314:5:314:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:317:9:317:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:318:5:318:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:321:9:321:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:322:5:322:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:325:9:325:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:326:5:326:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:329:9:329:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:330:5:330:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:333:3:333:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:337:10:337:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:339:5:339:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:343:5:343:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:345:3:345:3 | d [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:348:7:348:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:351:3:351:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:357:3:357:4 | y1 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:357:8:357:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:357:8:357:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:358:3:358:4 | y2 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:358:8:358:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:358:8:358:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:359:3:359:4 | y3 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:360:3:360:4 | y4 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:361:3:361:4 | y5 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:362:3:362:4 | y6 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:363:3:363:4 | y7 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:364:3:364:4 | y8 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:366:5:366:6 | y3 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:366:10:366:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:366:10:366:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:367:5:367:6 | y4 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:367:10:367:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:367:10:367:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:368:5:368:6 | y5 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:368:10:368:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:368:10:368:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:369:5:369:6 | y6 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:369:10:369:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:369:10:369:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:370:5:370:6 | y7 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:370:10:370:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:370:10:370:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:371:5:371:6 | y8 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:371:10:371:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:371:10:371:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:373:3:373:47 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:379:3:379:4 | y1 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:379:8:379:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:379:8:379:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:380:3:380:4 | y2 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:380:8:380:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:380:8:380:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:381:3:381:4 | y3 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:382:3:382:4 | y4 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:383:3:383:4 | y5 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:385:5:385:6 | y3 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:385:10:385:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:385:10:385:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:386:5:386:6 | y4 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:386:10:386:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:386:10:386:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:387:5:387:6 | y5 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:387:10:387:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:387:10:387:38 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:389:3:389:32 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:394:16:394:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:394:20:394:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:394:20:394:36 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:397:3:397:4 | y1 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:397:11:397:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:398:3:398:4 | y2 [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:398:9:398:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:398:14:398:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| range_analysis.c:399:3:399:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| rethrow_error.cpp:17:3:17:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| returnstmt.c:8:5:8:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| revsubscriptexpr.c:4:2:4:2 | i [post update] | PostUpdateNode should not be the target of local flow. | -| shortforstmt.cpp:35:5:35:5 | x [post update] | PostUpdateNode should not be the target of local flow. | -| statements.cpp:32:39:32:39 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| statements.cpp:48:16:48:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| statements.cpp:48:16:48:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| statements.cpp:48:22:48:22 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| statements.cpp:56:5:56:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:3:2:3:4 | (reference dereference) [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:3:2:3:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:3:2:3:4 | ref [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:18:7:18:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:20:12:20:12 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:20:12:20:12 | a [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:21:2:21:4 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:21:2:21:4 | val [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:22:2:22:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:31:10:31:11 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:31:10:31:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:33:11:33:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:81:5:81:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:81:5:81:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:90:5:90:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:90:5:90:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:98:5:98:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:98:5:98:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:106:5:106:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:106:5:106:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:126:5:126:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:134:5:134:18 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:227:19:227:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:233:24:233:31 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:236:7:236:7 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:236:7:236:7 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:236:7:236:7 | this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:240:7:240:7 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:240:7:240:7 | FieldAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:249:21:249:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:249:21:249:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:250:17:250:19 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:250:17:250:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:251:20:251:23 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| static_init_templates.cpp:251:20:251:23 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:4:5:4:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:8:5:8:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:12:16:12:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:12:16:12:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:12:25:12:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:12:25:12:25 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:18:3:18:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:26:19:26:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| staticlocals.cpp:29:14:29:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stmt_expr.cpp:13:16:13:16 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| stmt_expr.cpp:13:16:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stmt_expr.cpp:27:5:27:7 | ptr [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:4:16:4:30 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:5:14:5:28 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:3:13:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:3:13:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:3:13:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:3:13:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | (__range) [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:11:16:11:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:19:13:19:14 | (reference to) [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:19:13:19:14 | xs [post update] | PostUpdateNode should not be the target of local flow. | -| stream_it.cpp:20:3:20:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| subscriptexpr.c:4:2:4:2 | i [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:5:11:5:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:5:11:5:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:7:5:7:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:9:5:9:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:16:11:16:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:16:11:16:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:19:5:19:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:20:3:20:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:28:11:28:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:28:11:28:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:31:9:31:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| switchbody.c:33:9:33:17 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:28:9:28:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:28:24:28:24 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:36:9:36:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:36:19:36:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:44:9:44:9 | i [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:52:9:52:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:73:9:73:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:93:9:93:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:93:13:93:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:93:13:93:21 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:98:9:98:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:103:9:103:9 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:204:12:204:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:204:12:204:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:220:5:220:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:222:3:222:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:227:5:227:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:229:3:229:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:233:7:233:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| test.c:233:7:233:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | ConvertToNonVirtualBase [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:7:8:7:8 | this [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:13:5:13:16 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:13:5:13:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:21:14:21:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| try_catch.cpp:23:8:23:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| unaryopexpr.c:10:5:10:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| unaryopexpr.c:11:5:11:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| unaryopexpr.c:12:7:12:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| unaryopexpr.c:13:7:13:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| void_bug.cpp:5:3:5:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| whilestmt.c:9:7:9:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| whilestmt.c:11:5:11:8 | done [post update] | PostUpdateNode should not be the target of local flow. | -| whilestmt.c:40:7:40:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | -| whilestmt.c:42:7:42:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:77:19:77:21 | call to Val | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:11:82:14 | call to Val | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:45:82:48 | call to Val | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:82:51:82:51 | call to Val | PostUpdateNode should not be the target of local flow. | +| ir.cpp:811:7:811:13 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:812:7:812:26 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:825:7:825:13 | call to Base | PostUpdateNode should not be the target of local flow. | +| ir.cpp:826:7:826:26 | call to Base | PostUpdateNode should not be the target of local flow. | +| try_catch.cpp:7:8:7:8 | call to exception | PostUpdateNode should not be the target of local flow. | viableImplInCallContextTooLarge uniqueParameterNodeAtPosition -| ir.cpp:724:6:724:13 | TryCatch | 0 | ir.cpp:735:22:735:22 | *s | Parameters with overlapping positions. | -| ir.cpp:724:6:724:13 | TryCatch | 0 | ir.cpp:738:24:738:24 | *e | Parameters with overlapping positions. | +| ir.cpp:726:6:726:13 | TryCatch | 0 indirection | ir.cpp:737:22:737:22 | s indirection | Parameters with overlapping positions. | +| ir.cpp:726:6:726:13 | TryCatch | 0 indirection | ir.cpp:740:24:740:24 | e indirection | Parameters with overlapping positions. | uniqueParameterNodePosition uniqueContentApprox diff --git a/cpp/ql/test/library-tests/syntax-zoo/defconstructornewexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/defconstructornewexpr.cpp index 0a51afb3b83..bb2dd8f9dbf 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/defconstructornewexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/defconstructornewexpr.cpp @@ -1,6 +1,8 @@ +namespace { class C { }; +} -void f() { +static void f() { new C; return; } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/syntax-zoo/defdestructordeleteexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/defdestructordeleteexpr.cpp index 213898543a6..224b8f74401 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/defdestructordeleteexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/defdestructordeleteexpr.cpp @@ -1,6 +1,8 @@ +namespace { class C { }; +} -void f() { +static void f() { C* c = new C(); delete c; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/deleteexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/deleteexpr.cpp index 5e997100e37..42f6982eab3 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/deleteexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/deleteexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: ~C(); }; +} -void f() { +static void f() { C* c = new C(); delete c; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/dostmt.c b/cpp/ql/test/library-tests/syntax-zoo/dostmt.c index 5f1d14488dd..13d6ff323a9 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dostmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/dostmt.c @@ -5,7 +5,7 @@ void always_false() { l2:; } -void always_true_1() { +static void always_true_1() { do { l1:; break; @@ -13,7 +13,7 @@ void always_true_1() { l2:; } -void always_true_2() { +static void always_true_2() { do { l1:; break; @@ -22,14 +22,14 @@ void always_true_2() { l3:; } -void always_true_3() { +static void always_true_3() { do { l1:; } while(1); l2:; } -void normal() { +static void normal() { int i = 0; do { ++i; diff --git a/cpp/ql/test/library-tests/syntax-zoo/duff.c b/cpp/ql/test/library-tests/syntax-zoo/duff.c index a455faa3de8..8559402c380 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/duff.c +++ b/cpp/ql/test/library-tests/syntax-zoo/duff.c @@ -1,5 +1,5 @@ -void f(int i) { +static void f(int i) { int n = (i + 7) / 8; switch (i % 8) { case 0: do { 10; diff --git a/cpp/ql/test/library-tests/syntax-zoo/dummyblock.c b/cpp/ql/test/library-tests/syntax-zoo/dummyblock.c index 1307903ecf5..55557a9abd4 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dummyblock.c +++ b/cpp/ql/test/library-tests/syntax-zoo/dummyblock.c @@ -1,4 +1,4 @@ -void f() { +static void f() { if (1) ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/ellipsisexceptionhandler.cpp b/cpp/ql/test/library-tests/syntax-zoo/ellipsisexceptionhandler.cpp index f94ff416b2a..1f8f2f305b3 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ellipsisexceptionhandler.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/ellipsisexceptionhandler.cpp @@ -1,6 +1,6 @@ namespace eehandler { -void f() { +static void f() { try { try { throw 1; @@ -11,7 +11,7 @@ void f() { } } -void g(bool condition) { +static void g(bool condition) { try { if (condition) throw 1; } catch (...) { diff --git a/cpp/ql/test/library-tests/syntax-zoo/emptyblock.c b/cpp/ql/test/library-tests/syntax-zoo/emptyblock.c index 33ef4b879cd..f1055b1a051 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/emptyblock.c +++ b/cpp/ql/test/library-tests/syntax-zoo/emptyblock.c @@ -1,4 +1,4 @@ -void f() { +static void f() { { } ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/enum.c b/cpp/ql/test/library-tests/syntax-zoo/enum.c index 4e714c7c940..85c048aaffe 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/enum.c +++ b/cpp/ql/test/library-tests/syntax-zoo/enum.c @@ -2,6 +2,6 @@ enum { a = 1 + 1 }; -int f() { +static int f() { return a; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/exceptionhandler.cpp b/cpp/ql/test/library-tests/syntax-zoo/exceptionhandler.cpp index 50235eb4d16..0612f9ebded 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/exceptionhandler.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/exceptionhandler.cpp @@ -3,11 +3,11 @@ namespace ehandler { class C { }; class D { }; -void g() { +static void g() { throw 1; } -void f() { +static void f() { try { try { g(); diff --git a/cpp/ql/test/library-tests/syntax-zoo/exprstmt.c b/cpp/ql/test/library-tests/syntax-zoo/exprstmt.c index a0ce2659424..258450ba4fc 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/exprstmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/exprstmt.c @@ -1,4 +1,4 @@ -void f() { +static void f() { 1; ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/fieldaccess.cpp b/cpp/ql/test/library-tests/syntax-zoo/fieldaccess.cpp index 9a75ab5b2e9..8eaa8a2079e 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/fieldaccess.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/fieldaccess.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: int x; }; +} -void f() { +static void f() { C *c; int i; i = c->x; diff --git a/cpp/ql/test/library-tests/syntax-zoo/forstmt.cpp b/cpp/ql/test/library-tests/syntax-zoo/forstmt.cpp index 917ccb0bbfd..61cb3ed59d7 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/forstmt.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/forstmt.cpp @@ -1,21 +1,21 @@ -void f1() { +static void f1() { for (int i = 0; i < 10; i++) { l1: } ; } -void f2() { +static void f2() { for (int i = 0; false; i++) { // true edge pruned } } -void f3() { +static void f3() { for (int i = 0; true; i++) { // false edge pruned } } -void f4() { +static void f4() { for (int i = 0; i < 0; i++) { // true edge pruned } } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/syntax-zoo/ifelsestmt.c b/cpp/ql/test/library-tests/syntax-zoo/ifelsestmt.c index c21e213c8c7..4f0bc6813c9 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ifelsestmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/ifelsestmt.c @@ -1,4 +1,4 @@ -void always_false_1() { +static void always_false_1() { if(0) { l1:; } @@ -8,7 +8,7 @@ void always_false_1() { l3:; } -void always_false_2() { +static void always_false_2() { if(0) l1:; else @@ -16,7 +16,7 @@ void always_false_2() { l3:; } -void always_true_1() { +static void always_true_1() { if(1) { l1:; } @@ -26,7 +26,7 @@ void always_true_1() { l3:; } -void always_true_2() { +static void always_true_2() { if(1) l1:; else @@ -34,7 +34,7 @@ void always_true_2() { l3:; } -void normal(int x, int y) { +static void normal(int x, int y) { if(x == y) { l1:; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/ifstmt.c b/cpp/ql/test/library-tests/syntax-zoo/ifstmt.c index cf8c969277d..98f7a0064eb 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ifstmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/ifstmt.c @@ -1,30 +1,30 @@ -void always_false_1() { +static void always_false_1() { if(0) { l1:; } l2:; } -void always_false_2() { +static void always_false_2() { if(0) l1:; l2:; } -void always_true_1() { +static void always_true_1() { if(1) { l1:; } l2:; } -void always_true_2() { +static void always_true_2() { if(1) l1:; l2:; } -void normal(int x, int y) { +static void normal(int x, int y) { if(x == y) { l1:; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/initializer.c b/cpp/ql/test/library-tests/syntax-zoo/initializer.c index 5cd9949f4c3..190e8f6a59c 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/initializer.c +++ b/cpp/ql/test/library-tests/syntax-zoo/initializer.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int a, b; int i = a + b; } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/syntax-zoo/ir.cpp b/cpp/ql/test/library-tests/syntax-zoo/ir.cpp index 3ff4c53c17e..cf2a9958ffd 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ir.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/ir.cpp @@ -625,6 +625,7 @@ void CallMethods(String& r, String* p, String s) { s.c_str(); } +namespace { class C { public: static int StaticMemberFunction(int x) { @@ -671,6 +672,7 @@ private: void* m_e; String m_f; }; +} int DerefReference(int& r) { return r; diff --git a/cpp/ql/test/library-tests/syntax-zoo/landexpr.c b/cpp/ql/test/library-tests/syntax-zoo/landexpr.c index 98fa0a23c6d..a06db97b920 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/landexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/landexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int a, b; if (a && b) { } diff --git a/cpp/ql/test/library-tests/syntax-zoo/lorexpr.c b/cpp/ql/test/library-tests/syntax-zoo/lorexpr.c index d03d89760b6..f49446ff903 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/lorexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/lorexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int a, b; if (a || b) { } diff --git a/cpp/ql/test/library-tests/syntax-zoo/ltrbinopexpr.c b/cpp/ql/test/library-tests/syntax-zoo/ltrbinopexpr.c index cf093d36531..c198dcdd5cb 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ltrbinopexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/ltrbinopexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int i, j; int* p, q; diff --git a/cpp/ql/test/library-tests/syntax-zoo/membercallexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/membercallexpr.cpp index 035db2d5856..7840354d9a1 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/membercallexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/membercallexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: void g(); }; +} -void f() { +static void f() { C *c; c->g(); ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/membercallexpr_args.cpp b/cpp/ql/test/library-tests/syntax-zoo/membercallexpr_args.cpp index 5009f913255..103ae028ecc 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/membercallexpr_args.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/membercallexpr_args.cpp @@ -1,10 +1,12 @@ +namespace { class C { public: C* d; void g(int x, int y); }; +} -void f() { +static void f() { int i, j, k, l; C *c; c->d->g(i + j, k - l); diff --git a/cpp/ql/test/library-tests/syntax-zoo/ms_assume.cpp b/cpp/ql/test/library-tests/syntax-zoo/ms_assume.cpp index 615b87c356b..d612a0673a6 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ms_assume.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/ms_assume.cpp @@ -8,7 +8,7 @@ int ignore_return_value(); #define IGNORE_RETURN_VALUE() ignore_return_value() void myIgnoreReturnValue(); -int main(int argc, char *argv[]) +static int f(int argc, char *argv[]) { char *s1 = Xstrdup("Hello, world!"); char *s2 = Xstrdup(0); diff --git a/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp b/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp index e36c74cb61a..28fa24d4c92 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp @@ -1,11 +1,13 @@ // semmle-extractor-options: --microsoft #define EXCEPTION_EXECUTE_HANDLER 1 +namespace { class C { public: C(int x); ~C(); }; +} void ms_except_mix(int b1) { C c101(101); diff --git a/cpp/ql/test/library-tests/syntax-zoo/newexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/newexpr.cpp index 1060bfa898f..39ff739f5ce 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/newexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/newexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: C(int i, int j); }; +} -void f() { +static void f() { int a, b, c, d; new C(a + b, c - d); } diff --git a/cpp/ql/test/library-tests/syntax-zoo/no_dynamic_init.cpp b/cpp/ql/test/library-tests/syntax-zoo/no_dynamic_init.cpp index a129135ac94..4ed59acd679 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/no_dynamic_init.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/no_dynamic_init.cpp @@ -6,7 +6,7 @@ struct Magic { } }; -int main() { +static int f() { static Magic m; return 0; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/nodefaultswitchstmt.c b/cpp/ql/test/library-tests/syntax-zoo/nodefaultswitchstmt.c index bdd18c622e6..b7e5c54d754 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/nodefaultswitchstmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/nodefaultswitchstmt.c @@ -1,4 +1,4 @@ -void f(int x) { +static void f(int x) { switch (x) { case 1: case 2: diff --git a/cpp/ql/test/library-tests/syntax-zoo/nonmembercallexpr.c b/cpp/ql/test/library-tests/syntax-zoo/nonmembercallexpr.c index 4c949924900..842fe7e6cd8 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/nonmembercallexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/nonmembercallexpr.c @@ -1,6 +1,6 @@ -void g() { } +static void g() { } -void f() { +static void f() { g(); ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/nonmemberfp2callexpr.c b/cpp/ql/test/library-tests/syntax-zoo/nonmemberfp2callexpr.c index 9e458f2f50d..a04a1f24aa0 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/nonmemberfp2callexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/nonmemberfp2callexpr.c @@ -1,6 +1,6 @@ void (*g())(); -void f() { +static void f() { g()(); ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/nonmemberfpcallexpr.c b/cpp/ql/test/library-tests/syntax-zoo/nonmemberfpcallexpr.c index 51e06cec04b..d3d3d4be73f 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/nonmemberfpcallexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/nonmemberfpcallexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int (*g)(); g(); ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/parameterinitializer.cpp b/cpp/ql/test/library-tests/syntax-zoo/parameterinitializer.cpp index d132cd810a0..86c5198e029 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/parameterinitializer.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/parameterinitializer.cpp @@ -1,10 +1,10 @@ void printf(char *format, ...); -int g(void) { +static int g(void) { return 5; } -void f(int i = g()) { +static void f(int i = g()) { printf("Got %d\n", i); } @@ -15,7 +15,7 @@ public: void method(int k = g()) {}; }; -int main(void) { +static int h(void) { f(3); f(); f(4); diff --git a/cpp/ql/test/library-tests/syntax-zoo/pmcallexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/pmcallexpr.cpp index 75e143d846a..81234aba261 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/pmcallexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/pmcallexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: void (C::*g)(); }; +} -void f() { +static void f() { C *c, *d; (c->*(d->g))(); ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/questionexpr.c b/cpp/ql/test/library-tests/syntax-zoo/questionexpr.c index aeb257d9a61..778177310e0 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/questionexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/questionexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int a, b, c, d, x; x = a == b ? c + b : d - b; } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected index d68bb1cfde7..a498c7e4b23 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected @@ -20,7 +20,6 @@ instructionWithoutSuccessor | condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:25:6:25:21 | void switch_decl_bind(int) | void switch_decl_bind(int) | | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | -| enum.c:6:9:6:9 | Constant: (int)... | Instruction 'Constant: (int)...' has no successors in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:15:6:15:17 | void if_decl_bind(int) | void if_decl_bind(int) | | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | file://:0:0:0:0 | CompareNE: (bool)... | Instruction 'CompareNE: (bool)...' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | @@ -31,14 +30,14 @@ instructionWithoutSuccessor | misc.c:174:17:174:22 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | misc.c:174:30:174:35 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | misc.c:174:55:174:60 | Store: (char ****)... | Instruction 'Store: (char ****)...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | -| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | +| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | +| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | +| stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | -| vla.c:5:16:5:19 | Load: argc | Instruction 'Load: argc' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | -| vla.c:5:27:5:33 | BufferReadSideEffect: (const char *)... | Instruction 'BufferReadSideEffect: (const char *)...' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | +| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | +| vla.c:5:16:5:19 | Load: argc | Instruction 'Load: argc' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | +| vla.c:5:27:5:33 | BufferReadSideEffect: (const char *)... | Instruction 'BufferReadSideEffect: (const char *)...' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | | vla.c:11:6:11:16 | InitializeNonLocal: vla_typedef | Instruction 'InitializeNonLocal: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | | vla.c:12:33:12:44 | Add: ... + ... | Instruction 'Add: ... + ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | | vla.c:12:50:12:62 | Mul: ... * ... | Instruction 'Mul: ... * ...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | @@ -48,64 +47,6 @@ instructionWithoutSuccessor | vla.c:14:74:14:79 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | | vla.c:14:92:14:94 | Store: (char *)... | Instruction 'Store: (char *)...' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors -| allocators.cpp:14:5:14:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| array_delete.cpp:5:6:5:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| assignexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal: f1 | Instruction 'InitializeNonLocal: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal: f2 | Instruction 'InitializeNonLocal: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| constmemberaccess.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defdestructordeleteexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| deleteexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| dostmt.c:8:6:8:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| dostmt.c:16:6:16:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| dostmt.c:25:6:25:18 | InitializeNonLocal: always_true_3 | Instruction 'InitializeNonLocal: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| forstmt.cpp:1:6:1:7 | InitializeNonLocal: f1 | Instruction 'InitializeNonLocal: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| forstmt.cpp:8:6:8:7 | InitializeNonLocal: f2 | Instruction 'InitializeNonLocal: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| ifelsestmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifelsestmt.c:11:6:11:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifelsestmt.c:19:6:19:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifelsestmt.c:29:6:29:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifelsestmt.c:37:24:37:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| ifstmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifstmt.c:8:6:8:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifstmt.c:14:6:14:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifstmt.c:21:6:21:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifstmt.c:27:24:27:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| membercallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| membercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| newexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| no_dynamic_init.cpp:9:5:9:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nonmembercallexpr.c:1:6:1:6 | InitializeNonLocal: g | Instruction 'InitializeNonLocal: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| parameterinitializer.cpp:18:5:18:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| pmcallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| revsubscriptexpr.c:1:6:1:6 | InitializeNonLocal: g | Instruction 'InitializeNonLocal: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| staticmembercallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| staticmembercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| stream_it.cpp:16:5:16:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| whilestmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| whilestmt.c:8:6:8:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| whilestmt.c:15:6:15:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| whilestmt.c:23:6:23:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| whilestmt.c:32:6:32:18 | InitializeNonLocal: always_true_3 | Instruction 'InitializeNonLocal: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | unexplainedLoop unnecessaryPhiInstruction memoryOperandDefinitionIsUnmodeled @@ -117,13 +58,14 @@ backEdgeCountMismatch useNotDominatedByDefinition | VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor(int, int*) | void CallDestructor(int, int*) | | misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) | +| ms_assume.cpp:11:30:11:33 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ms_assume.cpp:11:12:11:12 | int f(int, char*[]) | int f(int, char*[]) | | ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | static_init_templates.cpp:15:1:15:18 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | static_init_templates.cpp:15:1:15:18 | void MyClass::MyClass() | void MyClass::MyClass() | | try_catch.cpp:21:9:21:9 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) | -| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | +| vla.c:3:31:3:34 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated @@ -131,7 +73,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer -| pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | +| pmcallexpr.cpp:10:2:10:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pmcallexpr.cpp:8:13:8:13 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | nonUniqueIRVariable diff --git a/cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp b/cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp index b3f4653fb73..7c5a89eb9f7 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/staticlocals.cpp @@ -1,6 +1,6 @@ namespace staticlocals { -int g() { +static int g() { return 1; } @@ -8,7 +8,7 @@ int h() { return 1; } -void f() { +static void f() { static int i = g(), j = h(); static int k = g(); ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr.cpp b/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr.cpp index 216b450e0dd..9482fd05032 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr.cpp @@ -1,9 +1,11 @@ +namespace { class C { public: static void g(); }; +} -void f() { +static void f() { C c; c.g(); ; diff --git a/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr_args.cpp b/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr_args.cpp index df553720dab..b5c9aa9e005 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr_args.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/staticmembercallexpr_args.cpp @@ -1,10 +1,12 @@ +namespace { class C { public: C* d; static void g(int x, int y); }; +} -void f() { +static void f() { int i, j, k, l; C c; c.d->g(i + j, k - l); diff --git a/cpp/ql/test/library-tests/syntax-zoo/stmt_expr.cpp b/cpp/ql/test/library-tests/syntax-zoo/stmt_expr.cpp index a3c01ed6f36..27cd85866be 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/stmt_expr.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/stmt_expr.cpp @@ -6,7 +6,7 @@ class C { ~C(); }; -void f(int b) { +static void f(int b) { int i; if (({ @@ -18,7 +18,7 @@ void f(int b) { ; } -void g(int b) { +static void g(int b) { void *ptr; int i; diff --git a/cpp/ql/test/library-tests/syntax-zoo/stream_it.cpp b/cpp/ql/test/library-tests/syntax-zoo/stream_it.cpp index a252d1d98ef..537dd35814f 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/stream_it.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/stream_it.cpp @@ -13,7 +13,7 @@ void stream_it(vector& t) } } -int main() +static int f() { vector xs; stream_it(xs); diff --git a/cpp/ql/test/library-tests/syntax-zoo/subscriptexpr.c b/cpp/ql/test/library-tests/syntax-zoo/subscriptexpr.c index 1a98c810aa7..34a2c0d554e 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/subscriptexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/subscriptexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { double x[5]; int i, a, b; i = x[a + b]; diff --git a/cpp/ql/test/library-tests/syntax-zoo/switchstmt.c b/cpp/ql/test/library-tests/syntax-zoo/switchstmt.c index 32be6e43b68..c2d69cfd0ef 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/switchstmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/switchstmt.c @@ -1,4 +1,4 @@ -void f(int x) { +static void f(int x) { switch (x) { case 1: case 2: diff --git a/cpp/ql/test/library-tests/syntax-zoo/tinyforstmt.c b/cpp/ql/test/library-tests/syntax-zoo/tinyforstmt.c index cbb6465ab7b..4bbefa35c97 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/tinyforstmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/tinyforstmt.c @@ -1,4 +1,4 @@ -void f() { +static void f() { for (;;) { ; } diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected index fe94102942f..4e67089ba0a 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected @@ -13,70 +13,12 @@ instructionWithoutSuccessor | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | -| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | +| ms_try_mix.cpp:35:13:35:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:29:6:29:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | +| ms_try_mix.cpp:53:5:53:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:49:6:49:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:13:21:13 | void stmtexpr::g(int) | void stmtexpr::g(int) | +| vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:12:3:12 | int f(int, char**) | int f(int, char**) | | vla.c:11:6:11:16 | InitializeNonLocal: vla_typedef | Instruction 'InitializeNonLocal: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | ambiguousSuccessors -| allocators.cpp:14:5:14:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| array_delete.cpp:5:6:5:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| assignexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| break_labels.c:2:11:2:11 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| conditional_destructors.cpp:29:6:29:7 | InitializeNonLocal: f1 | Instruction 'InitializeNonLocal: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| conditional_destructors.cpp:38:6:38:7 | InitializeNonLocal: f2 | Instruction 'InitializeNonLocal: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| constmemberaccess.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| constructorinitializer.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defconstructornewexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| defdestructordeleteexpr.cpp:3:6:3:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| deleteexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| dostmt.c:8:6:8:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| dostmt.c:16:6:16:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| dostmt.c:25:6:25:18 | InitializeNonLocal: always_true_3 | Instruction 'InitializeNonLocal: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| duff.c:2:12:2:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| fieldaccess.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| forstmt.cpp:1:6:1:7 | InitializeNonLocal: f1 | Instruction 'InitializeNonLocal: f1' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | void f1() | void f1() | -| forstmt.cpp:8:6:8:7 | InitializeNonLocal: f2 | Instruction 'InitializeNonLocal: f2' has 2 successors of kind 'Goto' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | void f2() | void f2() | -| ifelsestmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifelsestmt.c:11:6:11:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifelsestmt.c:19:6:19:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifelsestmt.c:29:6:29:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifelsestmt.c:37:24:37:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| ifstmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| ifstmt.c:8:6:8:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| ifstmt.c:14:6:14:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| ifstmt.c:21:6:21:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| ifstmt.c:27:24:27:24 | InitializeParameter: y | Instruction 'InitializeParameter: y' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:32:6:32:11 | void normal(int, int) | void normal(int, int) | -| membercallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| membercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| newexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| no_dynamic_init.cpp:9:5:9:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nodefaultswitchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| nonmembercallexpr.c:1:6:1:6 | InitializeNonLocal: g | Instruction 'InitializeNonLocal: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| parameterinitializer.cpp:18:5:18:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| pmcallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| revsubscriptexpr.c:1:6:1:6 | InitializeNonLocal: g | Instruction 'InitializeNonLocal: g' has 2 successors of kind 'Goto' in function '$@'. | nonmembercallexpr.c:1:6:1:6 | void g(); void g())(); void(* g(); void(* g())() | void g(); void g())(); void(* g(); void(* g())() | -| staticmembercallexpr.cpp:6:6:6:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| staticmembercallexpr_args.cpp:7:6:7:6 | InitializeNonLocal: f | Instruction 'InitializeNonLocal: f' has 14 successors of kind 'Goto' in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | -| stream_it.cpp:16:5:16:8 | InitializeNonLocal: main | Instruction 'InitializeNonLocal: main' has 4 successors of kind 'Goto' in function '$@'. | allocators.cpp:14:5:14:8 | int main() | int main() | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: i | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: i' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| switchstmt.c:1:12:1:12 | InitializeParameter: x | Instruction 'InitializeParameter: x' has 19 successors of kind 'Goto' in function '$@'. | aggregateinitializer.c:1:6:1:6 | int f(int); void f(int) | int f(int); void f(int) | -| whilestmt.c:1:6:1:19 | InitializeNonLocal: always_false_1 | Instruction 'InitializeNonLocal: always_false_1' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:1:6:1:19 | void always_false_1() | void always_false_1() | -| whilestmt.c:8:6:8:19 | InitializeNonLocal: always_false_2 | Instruction 'InitializeNonLocal: always_false_2' has 3 successors of kind 'Goto' in function '$@'. | ifelsestmt.c:11:6:11:19 | void always_false_2() | void always_false_2() | -| whilestmt.c:15:6:15:18 | InitializeNonLocal: always_true_1 | Instruction 'InitializeNonLocal: always_true_1' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:8:6:8:18 | void always_true_1() | void always_true_1() | -| whilestmt.c:23:6:23:18 | InitializeNonLocal: always_true_2 | Instruction 'InitializeNonLocal: always_true_2' has 4 successors of kind 'Goto' in function '$@'. | dostmt.c:16:6:16:18 | void always_true_2() | void always_true_2() | -| whilestmt.c:32:6:32:18 | InitializeNonLocal: always_true_3 | Instruction 'InitializeNonLocal: always_true_3' has 2 successors of kind 'Goto' in function '$@'. | dostmt.c:25:6:25:18 | void always_true_3() | void always_true_3() | unexplainedLoop unnecessaryPhiInstruction memoryOperandDefinitionIsUnmodeled @@ -93,7 +35,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer -| pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | +| pmcallexpr.cpp:10:2:10:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pmcallexpr.cpp:8:13:8:13 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | nonUniqueIRVariable diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaryopexpr.c b/cpp/ql/test/library-tests/syntax-zoo/unaryopexpr.c index 625be3434ee..aa843a0aef5 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaryopexpr.c +++ b/cpp/ql/test/library-tests/syntax-zoo/unaryopexpr.c @@ -1,4 +1,4 @@ -void f() { +static void f() { int i; &i; diff --git a/cpp/ql/test/library-tests/syntax-zoo/vla.c b/cpp/ql/test/library-tests/syntax-zoo/vla.c index e4dde809bb0..44387241006 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/vla.c +++ b/cpp/ql/test/library-tests/syntax-zoo/vla.c @@ -1,6 +1,6 @@ int atoi(const char*); -int main(int argc, char** argv) +static int f(int argc, char** argv) { char* matrix[argc][atoi(argv[1])]; return 0; diff --git a/cpp/ql/test/library-tests/syntax-zoo/whilestmt.c b/cpp/ql/test/library-tests/syntax-zoo/whilestmt.c index 9de843ba20a..dde94328bbb 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/whilestmt.c +++ b/cpp/ql/test/library-tests/syntax-zoo/whilestmt.c @@ -1,18 +1,18 @@ -void always_false_1() { +static void always_false_1() { while(0) { l1:; } l2:; } -void always_false_2() { +static void always_false_2() { int done = 1; while(!done) { done = 0; } } -void always_true_1() { +static void always_true_1() { while(1) { l1:; break; @@ -20,7 +20,7 @@ void always_true_1() { l2:; } -void always_true_2() { +static void always_true_2() { while(1) { l1:; break; @@ -29,14 +29,14 @@ void always_true_2() { l3:; } -void always_true_3() { +static void always_true_3() { while(1) { l1:; } l2:; } -void normal() { +static void normal() { int i = 0; while(i < 10) { ++i; diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected index d064fd7c821..629f2569232 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromtemplateinstantiation.expected @@ -112,8 +112,6 @@ | isfromtemplateinstantiation.cpp:93:54:93:55 | { ... } | isfromtemplateinstantiation.cpp:93:7:93:7 | AnotherTemplateClass::myMethod1(MyClassEnum) | | isfromtemplateinstantiation.cpp:93:55:93:55 | return ... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:93:55:93:55 | return ... | isfromtemplateinstantiation.cpp:93:7:93:7 | AnotherTemplateClass::myMethod1(MyClassEnum) | -| isfromtemplateinstantiation.cpp:94:29:94:32 | definition of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | -| isfromtemplateinstantiation.cpp:94:29:94:32 | definition of mce2 | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | | isfromtemplateinstantiation.cpp:94:36:94:51 | MyClassEnumConst | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:94:36:94:51 | MyClassEnumConst | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | @@ -121,6 +119,8 @@ | isfromtemplateinstantiation.cpp:97:52:97:52 | definition of myMethod2 | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | | isfromtemplateinstantiation.cpp:97:74:97:77 | MyClassEnum mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:97:74:97:77 | MyClassEnum mce2 | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | +| isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | +| isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | | isfromtemplateinstantiation.cpp:98:1:99:1 | { ... } | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:98:1:99:1 | { ... } | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass::myMethod2(MyClassEnum) | | isfromtemplateinstantiation.cpp:99:1:99:1 | return ... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | diff --git a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected index 557b0fff793..1e0f26900eb 100644 --- a/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected +++ b/cpp/ql/test/library-tests/templates/isfromtemplateinstantiation/isfromuninstantiatedtemplate.expected @@ -95,9 +95,6 @@ isFromUninstantiatedTemplate | isfromtemplateinstantiation.cpp:94:7:94:15 | declaration of myMethod2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:94:7:94:15 | declaration of myMethod2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | | isfromtemplateinstantiation.cpp:94:7:94:15 | declaration of myMethod2 | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | -| isfromtemplateinstantiation.cpp:94:29:94:32 | declaration of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | -| isfromtemplateinstantiation.cpp:94:29:94:32 | declaration of mce2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | -| isfromtemplateinstantiation.cpp:94:29:94:32 | declaration of mce2 | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | | isfromtemplateinstantiation.cpp:97:25:97:60 | definition of myMethod2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:97:25:97:60 | definition of myMethod2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | | isfromtemplateinstantiation.cpp:97:25:97:60 | definition of myMethod2 | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | @@ -110,6 +107,9 @@ isFromUninstantiatedTemplate | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | +| isfromtemplateinstantiation.cpp:97:74:97:77 | declaration of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | +| isfromtemplateinstantiation.cpp:97:74:97:77 | declaration of mce2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | +| isfromtemplateinstantiation.cpp:97:74:97:77 | declaration of mce2 | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | | isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass | | isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | isfromtemplateinstantiation.cpp:97:25:97:60 | myMethod2 | @@ -433,6 +433,7 @@ isFromUninstantiatedTemplate | isfromtemplateinstantiation.cpp:97:52:97:52 | myMethod2 | I | | Declaration | | | isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | | T | Definition | | | isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | | T | Definition | | +| isfromtemplateinstantiation.cpp:97:74:97:77 | definition of mce2 | I | | Definition | | | isfromtemplateinstantiation.cpp:97:74:97:77 | mce2 | | T | Declaration | | | isfromtemplateinstantiation.cpp:97:74:97:77 | mce2 | I | | Declaration | | | isfromtemplateinstantiation.cpp:98:1:99:1 | { ... } | | T | Stmt | | diff --git a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected index bbedf4ecc3f..a34e79ace7b 100644 --- a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected +++ b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/MissingCheckScanf.expected @@ -19,3 +19,6 @@ | test.cpp:302:8:302:12 | ptr_i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:301:3:301:7 | call to scanf | call to scanf | | test.cpp:310:7:310:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:309:3:309:7 | call to scanf | call to scanf | | test.cpp:404:25:404:25 | u | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:403:6:403:11 | call to sscanf | call to sscanf | +| test.cpp:416:7:416:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:413:7:413:11 | call to scanf | call to scanf | +| test.cpp:423:7:423:7 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:420:7:420:11 | call to scanf | call to scanf | +| test.cpp:430:6:430:6 | i | This variable is read, but may not have been written. It should be guarded by a check that the $@ returns at least 1. | test.cpp:429:2:429:6 | call to scanf | call to scanf | diff --git a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp index 38af4d7efcd..5940ad39529 100644 --- a/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp +++ b/cpp/ql/test/query-tests/Critical/MissingCheckScanf/test.cpp @@ -406,3 +406,26 @@ char *my_string_copy() { *ptr++ = 0; return DST_STRING; } + +void scan_and_write() { + { + int i; + if (scanf("%d", &i) < 1) { + i = 0; + } + use(i); // GOOD [FALSE POSITIVE]: variable is overwritten with a default value when scanf fails + } + { + int i; + if (scanf("%d", &i) != 1) { + i = 0; + } + use(i); // GOOD [FALSE POSITIVE]: variable is overwritten with a default value when scanf fails + } +} + +void scan_and_static_variable() { + static int i; + scanf("%d", &i); + use(i); // GOOD [FALSE POSITIVE]: static variables are always 0-initialized +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected b/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected index 84c5239cb86..3ed9da69446 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Conversion/CastArrayPointerArithmetic/CastArrayPointerArithmetic.expected @@ -1,137 +1,163 @@ edges -| test.cpp:26:29:26:29 | b | test.cpp:26:29:26:29 | b | | test.cpp:26:29:26:29 | b | test.cpp:27:2:27:2 | b | | test.cpp:30:34:30:34 | b | test.cpp:31:2:31:2 | b | -| test.cpp:34:31:34:31 | b | test.cpp:34:31:34:31 | b | | test.cpp:34:31:34:31 | b | test.cpp:35:2:35:2 | b | -| test.cpp:38:35:38:35 | d | test.cpp:38:35:38:35 | d | -| test.cpp:38:35:38:35 | d | test.cpp:39:2:39:2 | d | -| test.cpp:42:40:42:40 | d | test.cpp:43:2:43:2 | d | -| test.cpp:46:37:46:37 | d | test.cpp:46:37:46:37 | d | -| test.cpp:46:37:46:37 | d | test.cpp:47:2:47:2 | d | -| test.cpp:50:31:50:31 | b | test.cpp:51:11:51:11 | b | | test.cpp:57:19:57:19 | d | test.cpp:26:29:26:29 | b | -| test.cpp:57:19:57:19 | d | test.cpp:57:19:57:19 | ref arg d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:58:25:58:25 | d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:59:21:59:21 | d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:61:22:61:22 | d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:62:28:62:28 | d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:63:24:63:24 | d | -| test.cpp:57:19:57:19 | ref arg d | test.cpp:95:21:95:21 | d | +| test.cpp:57:19:57:19 | d | test.cpp:57:19:57:19 | d | +| test.cpp:57:19:57:19 | d | test.cpp:57:19:57:19 | d | +| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d | +| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d | +| test.cpp:57:19:57:19 | d | test.cpp:58:25:58:25 | d | +| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d | +| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d | +| test.cpp:57:19:57:19 | d | test.cpp:59:21:59:21 | d | | test.cpp:58:25:58:25 | d | test.cpp:30:34:30:34 | b | +| test.cpp:58:25:58:25 | d | test.cpp:58:25:58:25 | d | +| test.cpp:58:25:58:25 | d | test.cpp:58:25:58:25 | d | +| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d | +| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d | +| test.cpp:58:25:58:25 | d | test.cpp:59:21:59:21 | d | | test.cpp:59:21:59:21 | d | test.cpp:34:31:34:31 | b | -| test.cpp:59:21:59:21 | d | test.cpp:59:21:59:21 | ref arg d | -| test.cpp:59:21:59:21 | ref arg d | test.cpp:61:22:61:22 | d | -| test.cpp:59:21:59:21 | ref arg d | test.cpp:62:28:62:28 | d | -| test.cpp:59:21:59:21 | ref arg d | test.cpp:63:24:63:24 | d | -| test.cpp:59:21:59:21 | ref arg d | test.cpp:95:21:95:21 | d | -| test.cpp:61:22:61:22 | d | test.cpp:38:35:38:35 | d | -| test.cpp:61:22:61:22 | d | test.cpp:61:22:61:22 | ref arg d | -| test.cpp:61:22:61:22 | ref arg d | test.cpp:62:28:62:28 | d | -| test.cpp:61:22:61:22 | ref arg d | test.cpp:63:24:63:24 | d | -| test.cpp:61:22:61:22 | ref arg d | test.cpp:95:21:95:21 | d | -| test.cpp:62:28:62:28 | d | test.cpp:42:40:42:40 | d | -| test.cpp:63:24:63:24 | d | test.cpp:46:37:46:37 | d | -| test.cpp:63:24:63:24 | d | test.cpp:63:24:63:24 | ref arg d | -| test.cpp:63:24:63:24 | ref arg d | test.cpp:95:21:95:21 | d | +| test.cpp:59:21:59:21 | d | test.cpp:59:21:59:21 | d | +| test.cpp:59:21:59:21 | d | test.cpp:59:21:59:21 | d | | test.cpp:74:19:74:21 | dss | test.cpp:26:29:26:29 | b | -| test.cpp:74:19:74:21 | dss | test.cpp:74:19:74:21 | ref arg dss | -| test.cpp:74:19:74:21 | ref arg dss | test.cpp:75:25:75:27 | dss | -| test.cpp:74:19:74:21 | ref arg dss | test.cpp:76:21:76:23 | dss | -| test.cpp:74:19:74:21 | ref arg dss | test.cpp:96:21:96:23 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:74:19:74:21 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:74:19:74:21 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:75:25:75:27 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss | +| test.cpp:74:19:74:21 | dss | test.cpp:76:21:76:23 | dss | | test.cpp:75:25:75:27 | dss | test.cpp:30:34:30:34 | b | +| test.cpp:75:25:75:27 | dss | test.cpp:75:25:75:27 | dss | +| test.cpp:75:25:75:27 | dss | test.cpp:75:25:75:27 | dss | +| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss | +| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss | +| test.cpp:75:25:75:27 | dss | test.cpp:76:21:76:23 | dss | | test.cpp:76:21:76:23 | dss | test.cpp:34:31:34:31 | b | -| test.cpp:76:21:76:23 | dss | test.cpp:76:21:76:23 | ref arg dss | -| test.cpp:76:21:76:23 | ref arg dss | test.cpp:96:21:96:23 | dss | +| test.cpp:76:21:76:23 | dss | test.cpp:76:21:76:23 | dss | +| test.cpp:76:21:76:23 | dss | test.cpp:76:21:76:23 | dss | | test.cpp:86:19:86:20 | d2 | test.cpp:26:29:26:29 | b | -| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | ref arg d2 | -| test.cpp:86:19:86:20 | ref arg d2 | test.cpp:87:25:87:26 | d2 | -| test.cpp:86:19:86:20 | ref arg d2 | test.cpp:88:21:88:22 | d2 | -| test.cpp:86:19:86:20 | ref arg d2 | test.cpp:90:22:90:23 | d2 | -| test.cpp:86:19:86:20 | ref arg d2 | test.cpp:91:28:91:29 | d2 | -| test.cpp:86:19:86:20 | ref arg d2 | test.cpp:92:24:92:25 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:86:19:86:20 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:86:19:86:20 | d2 | test.cpp:88:21:88:22 | d2 | | test.cpp:87:25:87:26 | d2 | test.cpp:30:34:30:34 | b | +| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:87:25:87:26 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:87:25:87:26 | d2 | test.cpp:88:21:88:22 | d2 | | test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b | -| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | ref arg d2 | -| test.cpp:88:21:88:22 | ref arg d2 | test.cpp:90:22:90:23 | d2 | -| test.cpp:88:21:88:22 | ref arg d2 | test.cpp:91:28:91:29 | d2 | -| test.cpp:88:21:88:22 | ref arg d2 | test.cpp:92:24:92:25 | d2 | -| test.cpp:90:22:90:23 | d2 | test.cpp:38:35:38:35 | d | -| test.cpp:90:22:90:23 | d2 | test.cpp:90:22:90:23 | ref arg d2 | -| test.cpp:90:22:90:23 | ref arg d2 | test.cpp:91:28:91:29 | d2 | -| test.cpp:90:22:90:23 | ref arg d2 | test.cpp:92:24:92:25 | d2 | -| test.cpp:91:28:91:29 | d2 | test.cpp:42:40:42:40 | d | -| test.cpp:92:24:92:25 | d2 | test.cpp:46:37:46:37 | d | -| test.cpp:95:21:95:21 | d | test.cpp:50:31:50:31 | b | -| test.cpp:96:21:96:23 | dss | test.cpp:50:31:50:31 | b | +| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 | +| test.cpp:88:21:88:22 | d2 | test.cpp:88:21:88:22 | d2 | nodes | test.cpp:26:29:26:29 | b | semmle.label | b | -| test.cpp:26:29:26:29 | b | semmle.label | b | | test.cpp:27:2:27:2 | b | semmle.label | b | | test.cpp:30:34:30:34 | b | semmle.label | b | | test.cpp:31:2:31:2 | b | semmle.label | b | | test.cpp:34:31:34:31 | b | semmle.label | b | -| test.cpp:34:31:34:31 | b | semmle.label | b | | test.cpp:35:2:35:2 | b | semmle.label | b | -| test.cpp:38:35:38:35 | d | semmle.label | d | -| test.cpp:38:35:38:35 | d | semmle.label | d | -| test.cpp:39:2:39:2 | d | semmle.label | d | -| test.cpp:42:40:42:40 | d | semmle.label | d | -| test.cpp:43:2:43:2 | d | semmle.label | d | -| test.cpp:46:37:46:37 | d | semmle.label | d | -| test.cpp:46:37:46:37 | d | semmle.label | d | -| test.cpp:47:2:47:2 | d | semmle.label | d | -| test.cpp:50:31:50:31 | b | semmle.label | b | -| test.cpp:51:11:51:11 | b | semmle.label | b | | test.cpp:57:19:57:19 | d | semmle.label | d | -| test.cpp:57:19:57:19 | ref arg d | semmle.label | ref arg d | +| test.cpp:57:19:57:19 | d | semmle.label | d | +| test.cpp:57:19:57:19 | d | semmle.label | d | +| test.cpp:58:25:58:25 | d | semmle.label | d | +| test.cpp:58:25:58:25 | d | semmle.label | d | | test.cpp:58:25:58:25 | d | semmle.label | d | | test.cpp:59:21:59:21 | d | semmle.label | d | -| test.cpp:59:21:59:21 | ref arg d | semmle.label | ref arg d | -| test.cpp:61:22:61:22 | d | semmle.label | d | -| test.cpp:61:22:61:22 | ref arg d | semmle.label | ref arg d | -| test.cpp:62:28:62:28 | d | semmle.label | d | -| test.cpp:63:24:63:24 | d | semmle.label | d | -| test.cpp:63:24:63:24 | ref arg d | semmle.label | ref arg d | +| test.cpp:59:21:59:21 | d | semmle.label | d | +| test.cpp:59:21:59:21 | d | semmle.label | d | | test.cpp:74:19:74:21 | dss | semmle.label | dss | -| test.cpp:74:19:74:21 | ref arg dss | semmle.label | ref arg dss | +| test.cpp:74:19:74:21 | dss | semmle.label | dss | +| test.cpp:74:19:74:21 | dss | semmle.label | dss | +| test.cpp:75:25:75:27 | dss | semmle.label | dss | +| test.cpp:75:25:75:27 | dss | semmle.label | dss | | test.cpp:75:25:75:27 | dss | semmle.label | dss | | test.cpp:76:21:76:23 | dss | semmle.label | dss | -| test.cpp:76:21:76:23 | ref arg dss | semmle.label | ref arg dss | +| test.cpp:76:21:76:23 | dss | semmle.label | dss | +| test.cpp:76:21:76:23 | dss | semmle.label | dss | | test.cpp:86:19:86:20 | d2 | semmle.label | d2 | -| test.cpp:86:19:86:20 | ref arg d2 | semmle.label | ref arg d2 | +| test.cpp:86:19:86:20 | d2 | semmle.label | d2 | +| test.cpp:86:19:86:20 | d2 | semmle.label | d2 | +| test.cpp:86:19:86:20 | d2 | semmle.label | d2 | +| test.cpp:87:25:87:26 | d2 | semmle.label | d2 | +| test.cpp:87:25:87:26 | d2 | semmle.label | d2 | +| test.cpp:87:25:87:26 | d2 | semmle.label | d2 | | test.cpp:87:25:87:26 | d2 | semmle.label | d2 | | test.cpp:88:21:88:22 | d2 | semmle.label | d2 | -| test.cpp:88:21:88:22 | ref arg d2 | semmle.label | ref arg d2 | -| test.cpp:90:22:90:23 | d2 | semmle.label | d2 | -| test.cpp:90:22:90:23 | ref arg d2 | semmle.label | ref arg d2 | -| test.cpp:91:28:91:29 | d2 | semmle.label | d2 | -| test.cpp:92:24:92:25 | d2 | semmle.label | d2 | -| test.cpp:95:21:95:21 | d | semmle.label | d | -| test.cpp:96:21:96:23 | dss | semmle.label | dss | +| test.cpp:88:21:88:22 | d2 | semmle.label | d2 | +| test.cpp:88:21:88:22 | d2 | semmle.label | d2 | +| test.cpp:88:21:88:22 | d2 | semmle.label | d2 | subpaths -| test.cpp:57:19:57:19 | d | test.cpp:26:29:26:29 | b | test.cpp:26:29:26:29 | b | test.cpp:57:19:57:19 | ref arg d | -| test.cpp:59:21:59:21 | d | test.cpp:34:31:34:31 | b | test.cpp:34:31:34:31 | b | test.cpp:59:21:59:21 | ref arg d | -| test.cpp:61:22:61:22 | d | test.cpp:38:35:38:35 | d | test.cpp:38:35:38:35 | d | test.cpp:61:22:61:22 | ref arg d | -| test.cpp:63:24:63:24 | d | test.cpp:46:37:46:37 | d | test.cpp:46:37:46:37 | d | test.cpp:63:24:63:24 | ref arg d | -| test.cpp:74:19:74:21 | dss | test.cpp:26:29:26:29 | b | test.cpp:26:29:26:29 | b | test.cpp:74:19:74:21 | ref arg dss | -| test.cpp:76:21:76:23 | dss | test.cpp:34:31:34:31 | b | test.cpp:34:31:34:31 | b | test.cpp:76:21:76:23 | ref arg dss | -| test.cpp:86:19:86:20 | d2 | test.cpp:26:29:26:29 | b | test.cpp:26:29:26:29 | b | test.cpp:86:19:86:20 | ref arg d2 | -| test.cpp:88:21:88:22 | d2 | test.cpp:34:31:34:31 | b | test.cpp:34:31:34:31 | b | test.cpp:88:21:88:22 | ref arg d2 | -| test.cpp:90:22:90:23 | d2 | test.cpp:38:35:38:35 | d | test.cpp:38:35:38:35 | d | test.cpp:90:22:90:23 | ref arg d2 | #select | test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:57:19:57:19 | d | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:27:2:27:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:27:2:27:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:27:2:27:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | | test.cpp:31:2:31:2 | b | test.cpp:57:19:57:19 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | | test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:58:25:58:25 | d | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:31:2:31:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | | test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | | test.cpp:31:2:31:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | | test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:31:2:31:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:31:2:31:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | | test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:57:19:57:19 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:57:19:57:19 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:58:25:58:25 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:58:25:58:25 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast | | test.cpp:35:2:35:2 | b | test.cpp:59:21:59:21 | d | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:59:21:59:21 | d | this cast | | test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:74:19:74:21 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:74:19:74:21 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:75:25:75:27 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:75:25:75:27 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast | | test.cpp:35:2:35:2 | b | test.cpp:76:21:76:23 | dss | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:76:21:76:23 | dss | this cast | | test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:86:19:86:20 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:86:19:86:20 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:87:25:87:26 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:87:25:87:26 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast | +| test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast | | test.cpp:35:2:35:2 | b | test.cpp:88:21:88:22 | d2 | test.cpp:35:2:35:2 | b | This pointer arithmetic may be done with the wrong type because of $@. | test.cpp:88:21:88:22 | d2 | this cast | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected index 68b4069e5b4..0ea73248a7d 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/NonConstantFormat.expected @@ -3,7 +3,6 @@ | nested.cpp:21:23:21:26 | fmt0 | The format string argument to snprintf should be constant to prevent security issues and other potential errors. | | nested.cpp:79:32:79:38 | call to get_fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. | | nested.cpp:87:18:87:20 | fmt | The format string argument to diagnostic should be constant to prevent security issues and other potential errors. | -| test.cpp:51:10:51:21 | call to make_message | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:57:12:57:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:60:12:60:21 | call to const_wash | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:61:12:61:26 | ... + ... | The format string argument to printf should be constant to prevent security issues and other potential errors. | @@ -17,6 +16,8 @@ | test.cpp:82:12:82:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:88:12:88:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:93:12:93:18 | ++ ... | The format string argument to printf should be constant to prevent security issues and other potential errors. | +| test.cpp:100:12:100:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:110:12:110:24 | new[] | The format string argument to printf should be constant to prevent security issues and other potential errors. | +| test.cpp:115:12:115:16 | hello | The format string argument to printf should be constant to prevent security issues and other potential errors. | | test.cpp:130:20:130:26 | access to array | The format string argument to sprintf should be constant to prevent security issues and other potential errors. | | test.cpp:157:12:157:15 | data | The format string argument to printf should be constant to prevent security issues and other potential errors. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp index 6c867b6c50a..75c02296d7e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Format/NonConstantFormat/test.cpp @@ -48,7 +48,7 @@ int main(int argc, char **argv) { printf(choose_message(argc - 1), argc - 1); // GOOD printf(messages[1]); // GOOD printf(message); // GOOD - printf(make_message(argc - 1)); // BAD + printf(make_message(argc - 1)); // BAD [NOT DETECTED] printf("Hello, World\n"); // GOOD printf(_("Hello, World\n")); // GOOD { @@ -97,7 +97,7 @@ int main(int argc, char **argv) { const char *hello = "Hello, World\n"; const char **p = &hello; (*p)++; - printf(hello); // BAD [NOT DETECTED] + printf(hello); // BAD } { // Same as above block but through a C++ reference @@ -112,7 +112,7 @@ int main(int argc, char **argv) { { const char *hello = "Hello, World\n"; const char *const *p = &hello; // harmless reference to const pointer - printf(hello); // GOOD + printf(hello); // GOOD [FALSE POSITIVE] hello++; // modification comes after use and so does no harm } printf(argc > 2 ? "More than one\n" : _("Only one\n")); // GOOD diff --git a/cpp/ql/test/query-tests/Likely Bugs/Leap Year/Adding365DaysPerYear/Adding365daysPerYear.expected b/cpp/ql/test/query-tests/Likely Bugs/Leap Year/Adding365DaysPerYear/Adding365daysPerYear.expected index ea892843c49..898b0c32c5d 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Leap Year/Adding365DaysPerYear/Adding365daysPerYear.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Leap Year/Adding365DaysPerYear/Adding365daysPerYear.expected @@ -1,5 +1,9 @@ -| test.cpp:173:2:173:52 | ... = ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | -| test.cpp:174:2:174:46 | ... = ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | -| test.cpp:193:2:193:24 | ... = ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:193:2:193:24 | ... = ... | ... = ... | -| test.cpp:217:2:217:52 | ... = ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:2:214:47 | ... += ... | ... += ... | -| test.cpp:218:2:218:46 | ... = ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:2:214:47 | ... += ... | ... += ... | +| test.cpp:173:29:173:51 | ... & ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | +| test.cpp:173:29:173:51 | ... & ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:16:170:47 | ... * ... | ... * ... | +| test.cpp:174:30:174:45 | ... >> ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:2:170:47 | ... += ... | ... += ... | +| test.cpp:174:30:174:45 | ... >> ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:170:16:170:47 | ... * ... | ... * ... | +| test.cpp:193:15:193:24 | ... / ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:193:15:193:24 | ... / ... | ... / ... | +| test.cpp:217:29:217:51 | ... & ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:2:214:47 | ... += ... | ... += ... | +| test.cpp:217:29:217:51 | ... & ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:16:214:47 | ... * ... | ... * ... | +| test.cpp:218:30:218:45 | ... >> ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:2:214:47 | ... += ... | ... += ... | +| test.cpp:218:30:218:45 | ... >> ... | An arithmetic operation $@ that uses a constant value of 365 ends up modifying this date/time, without considering leap year scenarios. | test.cpp:214:16:214:47 | ... * ... | ... * ... | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/NtohlArrayNoBound/NtohlArrayNoBound.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/NtohlArrayNoBound/NtohlArrayNoBound.expected index b649a12674c..5d11cd38e61 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/NtohlArrayNoBound/NtohlArrayNoBound.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/NtohlArrayNoBound/NtohlArrayNoBound.expected @@ -1,8 +1,17 @@ | test.cpp:12:25:12:29 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:29 | call to ntohl | call to ntohl | +| test.cpp:12:25:12:34 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:29 | call to ntohl | call to ntohl | +| test.cpp:12:25:12:34 | call to ntohl | Unchecked use of data from network function $@. | test.cpp:12:25:12:34 | call to ntohl | call to ntohl | | test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl | | test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl | | test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl | | test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl | | test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@. | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@. | test.cpp:10:16:10:25 | call to ntohl | call to ntohl | | test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@. | test.cpp:85:10:85:14 | call to ntohl | call to ntohl | +| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@. | test.cpp:85:10:85:19 | call to ntohl | call to ntohl | | test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@. | test.cpp:99:8:99:12 | call to ntohl | call to ntohl | +| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@. | test.cpp:99:8:99:17 | call to ntohl | call to ntohl | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/TlsSettingsMisconfiguration.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/TlsSettingsMisconfiguration.expected index b2191d5b544..021bf2094b8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/TlsSettingsMisconfiguration.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/TlsSettingsMisconfiguration.expected @@ -1,19 +1,40 @@ +| test2.cpp:7:32:7:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:6:40:6:72 | sslv23 | sslv23 | test2.cpp:7:32:7:33 | call to context | no_sslv3 has not been set | +| test2.cpp:7:32:7:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:6:40:6:72 | sslv23 | sslv23 | test2.cpp:7:32:7:33 | call to context | no_tlsv1 has not been set | +| test2.cpp:7:32:7:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:6:40:6:72 | sslv23 | sslv23 | test2.cpp:7:32:7:33 | call to context | no_tlsv1_1 has not been set | | test2.cpp:15:32:15:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_sslv3 has not been set | +| test2.cpp:15:32:15:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_tlsv1 has not been set | +| test2.cpp:15:32:15:33 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_tlsv1_1 has not been set | | test2.cpp:23:32:23:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_sslv3 has not been set | | test2.cpp:23:32:23:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1 has not been set | | test2.cpp:23:32:23:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1_1 has not been set | | test2.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | | test2.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | | test2.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:38:35:38:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:38:65:38:97 | sslv23 | sslv23 | test2.cpp:38:35:38:98 | call to context | no_sslv3 has not been set | +| test2.cpp:38:35:38:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:38:65:38:97 | sslv23 | sslv23 | test2.cpp:38:35:38:98 | call to context | no_tlsv1 has not been set | +| test2.cpp:38:35:38:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:38:65:38:97 | sslv23 | sslv23 | test2.cpp:38:35:38:98 | call to context | no_tlsv1_1 has not been set | | test2.cpp:45:35:45:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_sslv3 has not been set | +| test2.cpp:45:35:45:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_tlsv1 has not been set | +| test2.cpp:45:35:45:98 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_tlsv1_1 has not been set | | test2.cpp:52:32:52:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set | | test2.cpp:52:32:52:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set | | test2.cpp:52:32:52:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set | +| test3.cpp:7:32:7:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test3.cpp:7:32:7:61 | tls | tls | test3.cpp:7:32:7:62 | call to context | no_tlsv1 has not been set | | test3.cpp:7:32:7:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test3.cpp:7:32:7:61 | tls | tls | test3.cpp:7:32:7:62 | call to context | no_tlsv1_1 has not been set | +| test3.cpp:15:32:15:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test3.cpp:15:32:15:61 | tls | tls | test3.cpp:15:32:15:62 | call to context | no_tlsv1 has not been set | +| test3.cpp:15:32:15:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test3.cpp:15:32:15:61 | tls | tls | test3.cpp:15:32:15:62 | call to context | no_tlsv1_1 has not been set | +| test.cpp:11:32:11:69 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:11:32:11:68 | tls_client | tls_client | test.cpp:11:32:11:69 | call to context | no_tlsv1 has not been set | +| test.cpp:11:32:11:69 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:11:32:11:68 | tls_client | tls_client | test.cpp:11:32:11:69 | call to context | no_tlsv1_1 has not been set | +| test.cpp:17:32:17:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:17:32:17:64 | sslv23 | sslv23 | test.cpp:17:32:17:65 | call to context | no_sslv3 has not been set | +| test.cpp:17:32:17:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:17:32:17:64 | sslv23 | sslv23 | test.cpp:17:32:17:65 | call to context | no_tlsv1 has not been set | +| test.cpp:17:32:17:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:17:32:17:64 | sslv23 | sslv23 | test.cpp:17:32:17:65 | call to context | no_tlsv1_1 has not been set | | test.cpp:25:32:25:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set | +| test.cpp:25:32:25:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_tlsv1 has not been set | +| test.cpp:25:32:25:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_tlsv1_1 has not been set | | test.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | | test.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | | test.cpp:31:32:31:65 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | | test.cpp:36:32:36:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:36:32:36:61 | tls | tls | test.cpp:36:32:36:62 | call to context | no_tlsv1 has not been set | | test.cpp:36:32:36:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:36:32:36:61 | tls | tls | test.cpp:36:32:36:62 | call to context | no_tlsv1_1 has not been set | -| test.cpp:41:32:41:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:41:32:41:61 | tls | tls | test.cpp:43:6:43:16 | call to set_options | no_tlsv1_2 was set | +| test.cpp:41:32:41:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:41:32:41:61 | tls | tls | test.cpp:41:32:41:62 | call to context | no_tlsv1 has not been set | +| test.cpp:41:32:41:62 | call to context | This usage of 'boost::asio::ssl::context::context' with protocol $@ is not configured correctly: The option $@. | test.cpp:41:32:41:61 | tls | tls | test.cpp:41:32:41:62 | call to context | no_tlsv1_1 has not been set | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test.cpp index a2f6532e99d..3e04e15fc89 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test.cpp @@ -8,13 +8,13 @@ void SetOptionsNoOldTls(boost::asio::ssl::context& ctx) void TestProperConfiguration_inter_CorrectUsage01() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::tls_client); + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls_client); // GOOD [FALSE POSITIVE] SetOptionsNoOldTls(ctx); } void TestProperConfiguration_inter_CorrectUsage02() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // GOOD [FALSE POSITIVE] ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); @@ -22,23 +22,23 @@ void TestProperConfiguration_inter_CorrectUsage02() void TestProperConfiguration_inter_IncorrectUsage01() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BUG - missing disable SSLv3 + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BAD - missing disable SSLv3 SetOptionsNoOldTls(ctx); } void TestProperConfiguration_IncorrectUsage01() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BUG + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); // BAD } void TestProperConfiguration_IncorrectUsage02() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BUG + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BAD } void TestProperConfiguration_IncorrectUsage03() { - boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BUG + boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); // BAD SetOptionsNoOldTls(ctx); ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_2 ); // BUG - disabling TLS 1.2 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test2.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test2.cpp index 5679cee8b0f..40f8acf17ea 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test2.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test2.cpp @@ -2,7 +2,7 @@ void good1() { - // GOOD + // GOOD [FALSE POSITIVE] boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; boost::asio::ssl::context ctx(m); ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); @@ -34,7 +34,7 @@ void bad2() void good3() { - // GOOD + // GOOD [FALSE POSITIVE] boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp index c9932b31618..ebbd0417f3e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/test3.cpp @@ -13,7 +13,7 @@ void useTLS_bad() void useTLS_good() { boost::asio::ssl::context ctx(boost::asio::ssl::context::tls); - ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); // GOOD [FALSE POSITIVE] // ... } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 97f44e15e79..63c7aec1d0f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -1,19 +1,32 @@ edges | test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection | -| test.c:8:27:8:30 | argv | test.c:32:11:32:18 | fileName indirection | +| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | +| test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | +| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | +| test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | +| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | +| test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | nodes | test.c:8:27:8:30 | argv | semmle.label | argv | +| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection | +| test.c:8:27:8:30 | argv indirection | semmle.label | argv indirection | | test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection | | test.c:32:11:32:18 | fileName indirection | semmle.label | fileName indirection | | test.c:37:17:37:24 | scanf output argument | semmle.label | scanf output argument | | test.c:38:11:38:18 | fileName indirection | semmle.label | fileName indirection | | test.c:43:17:43:24 | scanf output argument | semmle.label | scanf output argument | | test.c:44:11:44:18 | fileName indirection | semmle.label | fileName indirection | +| test.c:57:10:57:16 | access to array indirection | semmle.label | access to array indirection | subpaths #select | test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv | user input (a command-line argument) | -| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv | user input (a command-line argument) | +| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | +| test.c:17:11:17:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:17:11:17:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | +| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | +| test.c:32:11:32:18 | fileName | test.c:8:27:8:30 | argv indirection | test.c:32:11:32:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | | test.c:38:11:38:18 | fileName | test.c:37:17:37:24 | scanf output argument | test.c:38:11:38:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:37:17:37:24 | scanf output argument | user input (value read by scanf) | | test.c:44:11:44:18 | fileName | test.c:43:17:43:24 | scanf output argument | test.c:44:11:44:18 | fileName indirection | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:43:17:43:24 | scanf output argument | user input (value read by scanf) | +| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | +| test.c:57:10:57:16 | access to array | test.c:8:27:8:30 | argv indirection | test.c:57:10:57:16 | access to array indirection | This argument to a file access function is derived from $@ and then passed to read(fileName), which calls fopen(filename). | test.c:8:27:8:30 | argv indirection | user input (a command-line argument) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/test.c b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/test.c index a11fd73edd7..824db8f16ad 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/test.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/test.c @@ -54,7 +54,7 @@ int main(int argc, char** argv) { { void read(const char *fileName); - read(argv[1]); // BAD [NOT DETECTED] + read(argv[1]); // BAD } } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-078/SAMATE/ExecTainted/ExecTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-078/SAMATE/ExecTainted/ExecTainted.expected index 48ec662a7fe..3bcfdb6e4ae 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-078/SAMATE/ExecTainted/ExecTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-078/SAMATE/ExecTainted/ExecTainted.expected @@ -1,16 +1,29 @@ edges -| tests.cpp:26:15:26:23 | ReturnValue | tests.cpp:51:12:51:20 | call to badSource | -| tests.cpp:33:34:33:39 | call to getenv | tests.cpp:38:39:38:49 | environment indirection | -| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | ReturnValue | +| tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection | +| tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection | +| tests.cpp:26:32:26:35 | data indirection | tests.cpp:38:25:38:36 | strncat output argument | +| tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:38:39:38:49 | environment indirection | +| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection | +| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:26:15:26:23 | badSource indirection | +| tests.cpp:38:25:38:36 | strncat output argument | tests.cpp:51:22:51:25 | badSource output argument | | tests.cpp:38:39:38:49 | environment indirection | tests.cpp:38:25:38:36 | strncat output argument | -| tests.cpp:51:12:51:20 | call to badSource | tests.cpp:53:16:53:19 | data indirection | +| tests.cpp:51:12:51:20 | call to badSource indirection | tests.cpp:53:16:53:19 | data indirection | +| tests.cpp:51:22:51:25 | badSource output argument | tests.cpp:51:22:51:25 | data indirection | +| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection | +| tests.cpp:51:22:51:25 | data indirection | tests.cpp:51:12:51:20 | call to badSource indirection | nodes -| tests.cpp:26:15:26:23 | ReturnValue | semmle.label | ReturnValue | -| tests.cpp:33:34:33:39 | call to getenv | semmle.label | call to getenv | +| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection | +| tests.cpp:26:15:26:23 | badSource indirection | semmle.label | badSource indirection | +| tests.cpp:26:32:26:35 | data indirection | semmle.label | data indirection | +| tests.cpp:33:34:33:39 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument | | tests.cpp:38:25:38:36 | strncat output argument | semmle.label | strncat output argument | | tests.cpp:38:39:38:49 | environment indirection | semmle.label | environment indirection | -| tests.cpp:51:12:51:20 | call to badSource | semmle.label | call to badSource | +| tests.cpp:51:12:51:20 | call to badSource indirection | semmle.label | call to badSource indirection | +| tests.cpp:51:22:51:25 | badSource output argument | semmle.label | badSource output argument | +| tests.cpp:51:22:51:25 | data indirection | semmle.label | data indirection | | tests.cpp:53:16:53:19 | data indirection | semmle.label | data indirection | subpaths +| tests.cpp:51:22:51:25 | data indirection | tests.cpp:26:32:26:35 | data indirection | tests.cpp:26:15:26:23 | badSource indirection | tests.cpp:51:12:51:20 | call to badSource indirection | #select -| tests.cpp:53:16:53:19 | data | tests.cpp:33:34:33:39 | call to getenv | tests.cpp:53:16:53:19 | data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | tests.cpp:33:34:33:39 | call to getenv | user input (an environment variable) | tests.cpp:38:25:38:36 | strncat output argument | strncat output argument | +| tests.cpp:53:16:53:19 | data | tests.cpp:33:34:33:39 | call to getenv indirection | tests.cpp:53:16:53:19 | data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | tests.cpp:33:34:33:39 | call to getenv indirection | user input (an environment variable) | tests.cpp:38:25:38:36 | strncat output argument | strncat output argument | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected index 7df605d6b1c..f038f287bfc 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected @@ -1,8 +1,9 @@ edges -| test.cpp:15:27:15:30 | argv | test.cpp:22:45:22:52 | userName indirection | +| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection | +| test.cpp:15:27:15:30 | argv indirection | test.cpp:22:45:22:52 | userName indirection | | test.cpp:22:13:22:20 | sprintf output argument | test.cpp:23:12:23:19 | command1 indirection | | test.cpp:22:45:22:52 | userName indirection | test.cpp:22:13:22:20 | sprintf output argument | -| test.cpp:47:21:47:26 | call to getenv | test.cpp:50:35:50:43 | envCflags indirection | +| test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:50:35:50:43 | envCflags indirection | | test.cpp:50:11:50:17 | sprintf output argument | test.cpp:51:10:51:16 | command indirection | | test.cpp:50:35:50:43 | envCflags indirection | test.cpp:50:11:50:17 | sprintf output argument | | test.cpp:62:9:62:16 | fread output argument | test.cpp:64:20:64:27 | filename indirection | @@ -15,14 +16,19 @@ edges | test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | path indirection | | test.cpp:93:17:93:24 | filename indirection | test.cpp:93:11:93:14 | strncat output argument | | test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | path indirection | +| test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:107:33:107:36 | path indirection | | test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection | | test.cpp:107:33:107:36 | path indirection | test.cpp:107:31:107:31 | call to operator+ | | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | path indirection | -| test.cpp:114:17:114:17 | Call | test.cpp:114:25:114:29 | call to c_str indirection | -| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | Call | +| test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:19:114:22 | path indirection | +| test.cpp:114:10:114:23 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection | +| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection | +| test.cpp:114:19:114:22 | path indirection | test.cpp:114:10:114:23 | call to operator+ | +| test.cpp:114:19:114:22 | path indirection | test.cpp:114:17:114:17 | call to operator+ | | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | path indirection | -| test.cpp:120:17:120:17 | Call | test.cpp:120:10:120:30 | call to data indirection | -| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | Call | +| test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:19:120:22 | path indirection | +| test.cpp:120:17:120:17 | call to operator+ | test.cpp:120:10:120:30 | call to data indirection | +| test.cpp:120:19:120:22 | path indirection | test.cpp:120:17:120:17 | call to operator+ | | test.cpp:140:9:140:11 | fread output argument | test.cpp:142:31:142:33 | str indirection | | test.cpp:142:11:142:17 | sprintf output argument | test.cpp:143:10:143:16 | command indirection | | test.cpp:142:31:142:33 | str indirection | test.cpp:142:11:142:17 | sprintf output argument | @@ -35,50 +41,32 @@ edges | test.cpp:178:22:178:26 | flags indirection | test.cpp:178:13:178:19 | strncat output argument | | test.cpp:180:13:180:19 | strncat output argument | test.cpp:183:32:183:38 | command indirection | | test.cpp:180:22:180:29 | filename indirection | test.cpp:180:13:180:19 | strncat output argument | -| test.cpp:186:47:186:54 | *filename | test.cpp:187:18:187:25 | filename indirection | -| test.cpp:186:47:186:54 | *filename | test.cpp:188:20:188:24 | flags indirection | -| test.cpp:186:47:186:54 | filename | test.cpp:187:18:187:25 | filename indirection | -| test.cpp:186:47:186:54 | filename | test.cpp:188:20:188:24 | flags indirection | -| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | +| test.cpp:186:47:186:54 | filename indirection | test.cpp:187:18:187:25 | filename indirection | +| test.cpp:186:47:186:54 | filename indirection | test.cpp:188:20:188:24 | flags indirection | +| test.cpp:187:11:187:15 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument | | test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument | -| test.cpp:187:18:187:25 | filename indirection | test.cpp:187:11:187:15 | strncat output argument | -| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | -| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | command [post update] | +| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument | +| test.cpp:188:11:188:17 | strncat output argument | test.cpp:188:11:188:17 | strncat output argument | | test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument | -| test.cpp:188:20:188:24 | flags indirection | test.cpp:188:11:188:17 | strncat output argument | -| test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename | | test.cpp:194:9:194:16 | fread output argument | test.cpp:196:26:196:33 | filename indirection | -| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection | -| test.cpp:196:10:196:16 | command [post update] | test.cpp:198:32:198:38 | command indirection | -| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | -| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | command [post update] | +| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | command indirection | +| test.cpp:196:10:196:16 | concat output argument | test.cpp:198:32:198:38 | command indirection | +| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | +| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | concat output argument | +| test.cpp:196:26:196:33 | filename indirection | test.cpp:196:10:196:16 | concat output argument | | test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection | | test.cpp:218:9:218:16 | fread output argument | test.cpp:220:19:220:26 | filename indirection | | test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection | | test.cpp:220:10:220:16 | strncat output argument | test.cpp:222:32:222:38 | command indirection | | test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument | | test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument | -| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument | -| test.cpp:220:19:220:26 | filename indirection | test.cpp:220:10:220:16 | strncat output argument | nodes -| test.cpp:15:27:15:30 | argv | semmle.label | argv | +| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection | +| test.cpp:15:27:15:30 | argv indirection | semmle.label | argv indirection | | test.cpp:22:13:22:20 | sprintf output argument | semmle.label | sprintf output argument | | test.cpp:22:45:22:52 | userName indirection | semmle.label | userName indirection | | test.cpp:23:12:23:19 | command1 indirection | semmle.label | command1 indirection | -| test.cpp:47:21:47:26 | call to getenv | semmle.label | call to getenv | +| test.cpp:47:21:47:26 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:50:11:50:17 | sprintf output argument | semmle.label | sprintf output argument | | test.cpp:50:35:50:43 | envCflags indirection | semmle.label | envCflags indirection | | test.cpp:51:10:51:16 | command indirection | semmle.label | command indirection | @@ -95,16 +83,21 @@ nodes | test.cpp:93:17:93:24 | filename indirection | semmle.label | filename indirection | | test.cpp:94:45:94:48 | path indirection | semmle.label | path indirection | | test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:106:20:106:38 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ | | test.cpp:107:33:107:36 | path indirection | semmle.label | path indirection | | test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection | | test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv | -| test.cpp:114:17:114:17 | Call | semmle.label | Call | +| test.cpp:113:20:113:38 | call to getenv indirection | semmle.label | call to getenv indirection | +| test.cpp:114:10:114:23 | call to operator+ | semmle.label | call to operator+ | +| test.cpp:114:17:114:17 | call to operator+ | semmle.label | call to operator+ | | test.cpp:114:19:114:22 | path indirection | semmle.label | path indirection | | test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection | +| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection | | test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:119:20:119:38 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection | -| test.cpp:120:17:120:17 | Call | semmle.label | Call | +| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ | | test.cpp:120:19:120:22 | path indirection | semmle.label | path indirection | | test.cpp:140:9:140:11 | fread output argument | semmle.label | fread output argument | | test.cpp:142:11:142:17 | sprintf output argument | semmle.label | sprintf output argument | @@ -120,28 +113,15 @@ nodes | test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection | | test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection | | test.cpp:183:32:183:38 | command indirection | semmle.label | command indirection | -| test.cpp:186:47:186:54 | *filename | semmle.label | *filename | -| test.cpp:186:47:186:54 | filename | semmle.label | filename | -| test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument | +| test.cpp:186:47:186:54 | filename indirection | semmle.label | filename indirection | | test.cpp:187:11:187:15 | strncat output argument | semmle.label | strncat output argument | | test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection | -| test.cpp:187:18:187:25 | filename indirection | semmle.label | filename indirection | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | -| test.cpp:188:11:188:17 | command [post update] | semmle.label | command [post update] | | test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument | | test.cpp:188:11:188:17 | strncat output argument | semmle.label | strncat output argument | | test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection | -| test.cpp:188:20:188:24 | flags indirection | semmle.label | flags indirection | | test.cpp:194:9:194:16 | fread output argument | semmle.label | fread output argument | -| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] | -| test.cpp:196:10:196:16 | command [post update] | semmle.label | command [post update] | -| test.cpp:196:26:196:33 | filename | semmle.label | filename | +| test.cpp:196:10:196:16 | concat output argument | semmle.label | concat output argument | +| test.cpp:196:10:196:16 | concat output argument | semmle.label | concat output argument | | test.cpp:196:26:196:33 | filename indirection | semmle.label | filename indirection | | test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection | | test.cpp:198:32:198:38 | command indirection | semmle.label | command indirection | @@ -151,24 +131,25 @@ nodes | test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection | | test.cpp:220:19:220:26 | filename indirection | semmle.label | filename indirection | | test.cpp:222:32:222:38 | command indirection | semmle.label | command indirection | +| test.cpp:222:32:222:38 | command indirection | semmle.label | command indirection | subpaths -| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename | test.cpp:186:47:186:54 | filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | -| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | *filename | test.cpp:188:11:188:17 | command [post update] | test.cpp:196:10:196:16 | command [post update] | +| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument | +| test.cpp:196:26:196:33 | filename indirection | test.cpp:186:47:186:54 | filename indirection | test.cpp:188:11:188:17 | strncat output argument | test.cpp:196:10:196:16 | concat output argument | #select -| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument | -| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument | +| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument | +| test.cpp:23:12:23:19 | command1 | test.cpp:15:27:15:30 | argv indirection | test.cpp:23:12:23:19 | command1 indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:15:27:15:30 | argv indirection | user input (a command-line argument) | test.cpp:22:13:22:20 | sprintf output argument | sprintf output argument | +| test.cpp:51:10:51:16 | command | test.cpp:47:21:47:26 | call to getenv indirection | test.cpp:51:10:51:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:47:21:47:26 | call to getenv indirection | user input (an environment variable) | test.cpp:50:11:50:17 | sprintf output argument | sprintf output argument | | test.cpp:65:10:65:16 | command | test.cpp:62:9:62:16 | fread output argument | test.cpp:65:10:65:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:62:9:62:16 | fread output argument | user input (string read by fread) | test.cpp:64:11:64:17 | strncat output argument | strncat output argument | | test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument | | test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | path indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument | | test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ | -| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | Call | Call | -| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | Call | Call | +| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ | +| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ | +| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ | +| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:10:114:23 | call to operator+ | call to operator+ | +| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ | +| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ | +| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv indirection | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ | | test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument | | test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument | | test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | command indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:178:13:178:19 | strncat output argument | strncat output argument | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index 54caba5b521..1db291ffd88 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -1,48 +1,28 @@ edges -| search.c:14:24:14:28 | *query | search.c:17:8:17:12 | (const char *)... | -| search.c:14:24:14:28 | *query | search.c:17:8:17:12 | query | -| search.c:14:24:14:28 | *query | search.c:17:8:17:12 | query indirection | -| search.c:14:24:14:28 | query | search.c:17:8:17:12 | (const char *)... | | search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | | search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | -| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query indirection | -| search.c:22:24:22:28 | *query | search.c:23:39:23:43 | query | -| search.c:22:24:22:28 | *query | search.c:23:39:23:43 | query | -| search.c:22:24:22:28 | *query | search.c:23:39:23:43 | query indirection | +| search.c:14:24:14:28 | query | search.c:17:8:17:12 | query | | search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | | search.c:22:24:22:28 | query | search.c:23:39:23:43 | query | -| search.c:22:24:22:28 | query | search.c:23:39:23:43 | query indirection | | search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query | | search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query | -| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection | -| search.c:51:21:51:26 | call to getenv | search.c:55:17:55:25 | raw_query indirection | | search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query | | search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query | -| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection | -| search.c:51:21:51:26 | call to getenv | search.c:57:17:57:25 | raw_query indirection | | search.c:55:17:55:25 | raw_query | search.c:14:24:14:28 | query | -| search.c:55:17:55:25 | raw_query indirection | search.c:14:24:14:28 | *query | | search.c:57:17:57:25 | raw_query | search.c:22:24:22:28 | query | -| search.c:57:17:57:25 | raw_query indirection | search.c:22:24:22:28 | *query | subpaths nodes -| search.c:14:24:14:28 | *query | semmle.label | *query | | search.c:14:24:14:28 | query | semmle.label | query | -| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | | search.c:17:8:17:12 | query | semmle.label | query | | search.c:17:8:17:12 | query | semmle.label | query | -| search.c:17:8:17:12 | query indirection | semmle.label | query indirection | -| search.c:22:24:22:28 | *query | semmle.label | *query | +| search.c:17:8:17:12 | query | semmle.label | query | | search.c:22:24:22:28 | query | semmle.label | query | | search.c:23:39:23:43 | query | semmle.label | query | | search.c:23:39:23:43 | query | semmle.label | query | -| search.c:23:39:23:43 | query indirection | semmle.label | query indirection | | search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv | | search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv | | search.c:55:17:55:25 | raw_query | semmle.label | raw_query | -| search.c:55:17:55:25 | raw_query indirection | semmle.label | raw_query indirection | | search.c:57:17:57:25 | raw_query | semmle.label | raw_query | -| search.c:57:17:57:25 | raw_query indirection | semmle.label | raw_query indirection | #select | search.c:17:8:17:12 | query | search.c:51:21:51:26 | call to getenv | search.c:17:8:17:12 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data | | search.c:23:39:23:43 | query | search.c:51:21:51:26 | call to getenv | search.c:23:39:23:43 | query | Cross-site scripting vulnerability due to $@. | search.c:51:21:51:26 | call to getenv | this query data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected index 369abfe39f3..4e7cfa96fa7 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected @@ -1,31 +1,25 @@ edges -| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... | -| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | (const char *)... | | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | -| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection | -| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 indirection | -| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... | -| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | (const char *)... | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | +| test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | +| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | +| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | -| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection | -| test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array indirection | subpaths nodes | test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:15:20:15:23 | argv | semmle.label | argv | -| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | | test.c:21:18:21:23 | query1 | semmle.label | query1 | -| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection | +| test.c:21:18:21:23 | query1 | semmle.label | query1 | | test.cpp:43:27:43:30 | argv | semmle.label | argv | | test.cpp:43:27:43:30 | argv | semmle.label | argv | -| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... | | test.cpp:43:27:43:33 | access to array | semmle.label | access to array | | test.cpp:43:27:43:33 | access to array | semmle.label | access to array | -| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection | +| test.cpp:43:27:43:33 | access to array | semmle.label | access to array | #select | test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:15:20:15:23 | argv | user input (argv) | | test.cpp:43:27:43:33 | access to array | test.cpp:43:27:43:30 | argv | test.cpp:43:27:43:33 | access to array | This argument to a SQL query function is derived from $@ and then passed to pqxx::work::exec1((unnamed parameter 0)). | test.cpp:43:27:43:30 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index e940d554fa9..5e0638a0afe 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -1,25 +1,23 @@ edges -| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | (LPCSTR)... | -| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | data | -| test.cpp:37:73:37:76 | *data | test.cpp:43:32:43:35 | data indirection | -| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | (LPCSTR)... | | test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data | | test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data | -| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data indirection | +| test.cpp:37:73:37:76 | data | test.cpp:43:32:43:35 | data | +| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data | +| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data | +| test.cpp:37:73:37:76 | data indirection | test.cpp:43:32:43:35 | data | | test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data | | test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data | | test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection | | test.cpp:64:30:64:35 | call to getenv | test.cpp:73:24:73:27 | data indirection | | test.cpp:73:24:73:27 | data | test.cpp:37:73:37:76 | data | -| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | *data | +| test.cpp:73:24:73:27 | data indirection | test.cpp:37:73:37:76 | data indirection | subpaths nodes -| test.cpp:37:73:37:76 | *data | semmle.label | *data | | test.cpp:37:73:37:76 | data | semmle.label | data | -| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... | +| test.cpp:37:73:37:76 | data indirection | semmle.label | data indirection | +| test.cpp:43:32:43:35 | data | semmle.label | data | | test.cpp:43:32:43:35 | data | semmle.label | data | | test.cpp:43:32:43:35 | data | semmle.label | data | -| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection | | test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv | | test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv | | test.cpp:73:24:73:27 | data | semmle.label | data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index 3e371efddd5..29c14620b3e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -1,131 +1,108 @@ edges -| test.cpp:24:30:24:36 | *command | test.cpp:26:10:26:16 | command | -| test.cpp:24:30:24:36 | *command | test.cpp:26:10:26:16 | command | -| test.cpp:24:30:24:36 | *command | test.cpp:26:10:26:16 | command indirection | | test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command | | test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command | -| test.cpp:24:30:24:36 | command | test.cpp:26:10:26:16 | command indirection | -| test.cpp:29:30:29:36 | *command | test.cpp:31:10:31:16 | command | -| test.cpp:29:30:29:36 | *command | test.cpp:31:10:31:16 | command | -| test.cpp:29:30:29:36 | *command | test.cpp:31:10:31:16 | command indirection | | test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command | | test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command | -| test.cpp:29:30:29:36 | command | test.cpp:31:10:31:16 | command indirection | -| test.cpp:42:18:42:23 | call to getenv | test.cpp:42:18:42:34 | call to getenv | -| test.cpp:42:18:42:23 | call to getenv | test.cpp:42:18:42:34 | call to getenv indirection | -| test.cpp:42:18:42:34 | (const char *)... | test.cpp:42:18:42:34 | call to getenv | -| test.cpp:42:18:42:34 | (const char *)... | test.cpp:42:18:42:34 | call to getenv indirection | +| test.cpp:42:18:42:23 | call to getenv | test.cpp:24:30:24:36 | command | | test.cpp:42:18:42:34 | call to getenv | test.cpp:24:30:24:36 | command | -| test.cpp:42:18:42:34 | call to getenv indirection | test.cpp:24:30:24:36 | *command | -| test.cpp:43:18:43:23 | call to getenv | test.cpp:43:18:43:34 | call to getenv | -| test.cpp:43:18:43:23 | call to getenv | test.cpp:43:18:43:34 | call to getenv indirection | -| test.cpp:43:18:43:34 | (const char *)... | test.cpp:43:18:43:34 | call to getenv | -| test.cpp:43:18:43:34 | (const char *)... | test.cpp:43:18:43:34 | call to getenv indirection | +| test.cpp:43:18:43:23 | call to getenv | test.cpp:29:30:29:36 | command | | test.cpp:43:18:43:34 | call to getenv | test.cpp:29:30:29:36 | command | -| test.cpp:43:18:43:34 | call to getenv indirection | test.cpp:29:30:29:36 | *command | -| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | (const char *)... | | test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | -| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer indirection | -| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | (const char *)... | +| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | +| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | +| test.cpp:56:12:56:17 | buffer | test.cpp:62:10:62:15 | buffer | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | +| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | | test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data | -| test.cpp:56:12:56:17 | buffer | test.cpp:63:10:63:13 | data indirection | -| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (const char *)... | -| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | (reference dereference) | | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | | test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | -| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref indirection | -| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | (const char *)... | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | +| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | | test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 | -| test.cpp:56:12:56:17 | buffer | test.cpp:65:10:65:14 | data2 indirection | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | (const char *)... | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer indirection | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | (const char *)... | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:62:10:62:15 | buffer | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:63:10:63:13 | data indirection | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (const char *)... | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | (reference dereference) | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref indirection | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | (const char *)... | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:64:10:64:16 | dataref | +| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 | | test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 | -| test.cpp:56:12:56:17 | fgets output argument | test.cpp:65:10:65:14 | data2 indirection | -| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | (const char *)... | | test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | -| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer indirection | -| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | (const char *)... | +| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | +| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | +| test.cpp:76:12:76:17 | buffer | test.cpp:78:10:78:15 | buffer | +| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer | | test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer | -| test.cpp:76:12:76:17 | fgets output argument | test.cpp:78:10:78:15 | buffer indirection | -| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | (const char *)... | | test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | -| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer indirection | -| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | (const char *)... | +| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | +| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | +| test.cpp:98:17:98:22 | buffer | test.cpp:99:15:99:20 | buffer | +| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer | | test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer | -| test.cpp:98:17:98:22 | recv output argument | test.cpp:99:15:99:20 | buffer indirection | -| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | (const char *)... | | test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | -| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer indirection | -| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | (const char *)... | +| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | +| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | +| test.cpp:106:17:106:22 | buffer | test.cpp:107:15:107:20 | buffer | +| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer | | test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer | -| test.cpp:106:17:106:22 | recv output argument | test.cpp:107:15:107:20 | buffer indirection | subpaths nodes -| test.cpp:24:30:24:36 | *command | semmle.label | *command | | test.cpp:24:30:24:36 | command | semmle.label | command | | test.cpp:26:10:26:16 | command | semmle.label | command | | test.cpp:26:10:26:16 | command | semmle.label | command | -| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection | -| test.cpp:29:30:29:36 | *command | semmle.label | *command | | test.cpp:29:30:29:36 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | -| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection | | test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... | | test.cpp:42:18:42:34 | call to getenv | semmle.label | call to getenv | -| test.cpp:42:18:42:34 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:43:18:43:23 | call to getenv | semmle.label | call to getenv | -| test.cpp:43:18:43:34 | (const char *)... | semmle.label | (const char *)... | | test.cpp:43:18:43:34 | call to getenv | semmle.label | call to getenv | -| test.cpp:43:18:43:34 | call to getenv indirection | semmle.label | call to getenv indirection | +| test.cpp:56:12:56:17 | buffer | semmle.label | buffer | | test.cpp:56:12:56:17 | buffer | semmle.label | buffer | | test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument | -| test.cpp:62:10:62:15 | (const char *)... | semmle.label | (const char *)... | | test.cpp:62:10:62:15 | buffer | semmle.label | buffer | -| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | -| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:62:10:62:15 | buffer | semmle.label | buffer | +| test.cpp:63:10:63:13 | data | semmle.label | data | | test.cpp:63:10:63:13 | data | semmle.label | data | | test.cpp:63:10:63:13 | data | semmle.label | data | -| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | -| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) | | test.cpp:64:10:64:16 | dataref | semmle.label | dataref | | test.cpp:64:10:64:16 | dataref | semmle.label | dataref | -| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | -| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | +| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | | test.cpp:65:10:65:14 | data2 | semmle.label | data2 | | test.cpp:65:10:65:14 | data2 | semmle.label | data2 | -| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | +| test.cpp:65:10:65:14 | data2 | semmle.label | data2 | +| test.cpp:76:12:76:17 | buffer | semmle.label | buffer | | test.cpp:76:12:76:17 | buffer | semmle.label | buffer | | test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument | -| test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... | | test.cpp:78:10:78:15 | buffer | semmle.label | buffer | -| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:78:10:78:15 | buffer | semmle.label | buffer | +| test.cpp:98:17:98:22 | buffer | semmle.label | buffer | | test.cpp:98:17:98:22 | buffer | semmle.label | buffer | | test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument | -| test.cpp:99:15:99:20 | (const char *)... | semmle.label | (const char *)... | | test.cpp:99:15:99:20 | buffer | semmle.label | buffer | -| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:99:15:99:20 | buffer | semmle.label | buffer | +| test.cpp:106:17:106:22 | buffer | semmle.label | buffer | | test.cpp:106:17:106:22 | buffer | semmle.label | buffer | | test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument | -| test.cpp:107:15:107:20 | (const char *)... | semmle.label | (const char *)... | | test.cpp:107:15:107:20 | buffer | semmle.label | buffer | -| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:107:15:107:20 | buffer | semmle.label | buffer | #select | test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv | | test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/OverflowBuffer.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/OverflowBuffer.expected index 73f1b74db56..770fcd0e3a3 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/OverflowBuffer.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/OverflowBuffer.expected @@ -3,17 +3,11 @@ | tests.cpp:171:9:171:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | destination buffer | | tests.cpp:172:9:172:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:164:20:164:25 | call to malloc | array | | tests.cpp:192:9:192:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | destination buffer | -| tests.cpp:192:9:192:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:185:12:185:24 | dataBadBuffer | destination buffer | | tests.cpp:193:9:193:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:181:10:181:22 | dataBadBuffer | array | -| tests.cpp:193:9:193:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:185:12:185:24 | dataBadBuffer | array | | tests.cpp:212:9:212:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | destination buffer | -| tests.cpp:212:9:212:14 | call to memcpy | This 'memcpy' operation accesses 100 bytes but the $@ is only 50 bytes. | tests.cpp:205:12:205:24 | dataBadBuffer | destination buffer | | tests.cpp:213:9:213:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:201:36:201:41 | call to alloca | array | -| tests.cpp:213:9:213:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:205:12:205:24 | dataBadBuffer | array | | tests.cpp:237:9:237:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:221:36:221:41 | call to alloca | array | -| tests.cpp:237:9:237:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:225:12:225:24 | dataBadBuffer | array | | tests.cpp:261:9:261:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:245:10:245:22 | dataBadBuffer | array | -| tests.cpp:261:9:261:19 | access to array | This array indexing operation accesses byte offset 99 but the $@ is only 50 bytes. | tests.cpp:249:12:249:24 | dataBadBuffer | array | | tests.cpp:384:9:384:14 | call to memcpy | This 'memcpy' operation accesses 40 bytes but the $@ is only 10 bytes. | tests.cpp:380:19:380:24 | call to alloca | destination buffer | | tests.cpp:434:9:434:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:422:12:422:26 | new[] | array | | tests.cpp:453:9:453:19 | access to array | This array indexing operation accesses byte offset 399 but the $@ is only 200 bytes. | tests.cpp:445:12:445:26 | new[] | array | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/tests.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/tests.cpp index 1c7f9ad60f5..b33b00507b2 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/tests.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/SAMATE/tests.cpp @@ -664,7 +664,7 @@ void CWE121_Stack_Based_Buffer_Overflow__CWE193_char_declare_cpy_12_bad() } { char source[10+1] = SRC_STRING; - /* POTENTIAL FLAW: data may not have enough space to hold source */ // [NOT DETECTED] + /* POTENTIAL FLAW: data may not have enough space to hold source */ strcpy(data, source); printLine(data); } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowBuffer.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowBuffer.expected index 795d83587c3..8006b5b61a0 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowBuffer.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowBuffer.expected @@ -7,7 +7,6 @@ | tests.cpp:224:3:224:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:215:19:215:30 | new[] | destination buffer | | tests.cpp:226:3:226:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:218:13:218:18 | call to malloc | destination buffer | | tests.cpp:228:3:228:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:218:13:218:18 | call to malloc | destination buffer | -| tests.cpp:228:3:228:8 | call to memset | This 'memset' operation accesses 33 bytes but the $@ is only 32 bytes. | tests.cpp:219:13:219:19 | buffer3 | destination buffer | | tests.cpp:231:3:231:8 | call to memcmp | This 'memcmp' operation may access 33 bytes but the $@ is only 32 bytes. | tests.cpp:214:8:214:14 | buffer1 | first buffer | | tests.cpp:231:3:231:8 | call to memcmp | This 'memcmp' operation may access 33 bytes but the $@ is only 32 bytes. | tests.cpp:215:19:215:30 | new[] | second buffer | | tests.cpp:244:2:244:8 | call to memmove | This 'memmove' operation accesses 6 bytes but the $@ is only 5 bytes. | tests.cpp:208:25:208:39 | {...} | source buffer | @@ -21,12 +20,8 @@ | tests.cpp:312:2:312:7 | call to memset | This 'memset' operation accesses 17 bytes but the $@ is only 16 bytes. | tests.cpp:298:7:298:12 | buffer | destination buffer | | tests.cpp:314:2:314:7 | call to memset | This 'memset' operation accesses 8 bytes but the $@ is only 4 bytes. | tests.cpp:299:6:299:10 | field | destination buffer | | tests.cpp:327:3:327:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer | -| tests.cpp:327:3:327:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:322:22:322:27 | & ... | destination buffer | | tests.cpp:329:3:329:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer | -| tests.cpp:329:3:329:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:322:22:322:27 | & ... | destination buffer | -| tests.cpp:329:3:329:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:324:12:324:17 | myPtr1 | destination buffer | | tests.cpp:336:3:336:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:301:10:301:14 | myVar | destination buffer | -| tests.cpp:336:3:336:8 | call to memset | This 'memset' operation accesses 21 bytes but the $@ is only 20 bytes. | tests.cpp:333:27:333:32 | & ... | destination buffer | | tests.cpp:346:2:346:14 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:342:7:342:15 | charArray | array | | tests.cpp:349:2:349:14 | access to array | This array indexing operation accesses byte offset 10 but the $@ is only 10 bytes. | tests.cpp:342:7:342:15 | charArray | array | | tests.cpp:350:17:350:29 | access to array | This array indexing operation accesses byte offset 10 but the $@ is only 10 bytes. | tests.cpp:342:7:342:15 | charArray | array | @@ -45,11 +40,8 @@ | tests.cpp:459:3:459:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array | | tests.cpp:461:3:461:11 | access to array | This array indexing operation accesses byte offset 639 but the $@ is only 400 bytes. | tests.cpp:450:7:450:11 | multi | array | | tests.cpp:476:2:476:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array | -| tests.cpp:476:2:476:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:470:13:470:18 | buffer | array | | tests.cpp:477:2:477:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array | -| tests.cpp:477:2:477:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:471:13:471:18 | buffer | array | | tests.cpp:481:2:481:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:469:7:469:12 | buffer | array | -| tests.cpp:481:2:481:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:472:13:472:18 | buffer | array | | tests.cpp:487:2:487:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:473:21:473:26 | call to malloc | array | | tests.cpp:491:2:491:7 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:474:21:474:26 | call to malloc | array | | tests.cpp:519:3:519:8 | call to memset | This 'memset' operation accesses 20 bytes but the $@ is only 10 bytes. | tests.cpp:502:15:502:20 | call to malloc | destination buffer | @@ -58,20 +50,13 @@ | tests.cpp:546:6:546:10 | call to fread | This 'fread' operation may access 400 bytes but the $@ is only 100 bytes. | tests.cpp:532:7:532:16 | charBuffer | destination buffer | | tests.cpp:569:6:569:15 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array | | tests.cpp:577:7:577:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array | -| tests.cpp:577:7:577:13 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:571:8:571:13 | buffer | array | -| tests.cpp:579:6:579:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:565:7:565:12 | buffer | array | -| tests.cpp:579:6:579:12 | access to array | This array indexing operation accesses a negative index -1 on the $@. | tests.cpp:571:8:571:13 | buffer | array | | tests_restrict.c:12:2:12:7 | call to memcpy | This 'memcpy' operation accesses 2 bytes but the $@ is only 1 byte. | tests_restrict.c:7:6:7:13 | smallbuf | source buffer | | unions.cpp:26:2:26:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:21:10:21:11 | mu | destination buffer | | unions.cpp:27:2:27:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer | -| unions.cpp:27:2:27:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:27:14:27:18 | small | destination buffer | | unions.cpp:29:2:29:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer | -| unions.cpp:29:2:29:7 | call to memset | This 'memset' operation accesses 100 bytes but the $@ is only 10 bytes. | unions.cpp:29:14:29:18 | small | destination buffer | | unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 10 bytes. | unions.cpp:15:7:15:11 | small | destination buffer | -| unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 10 bytes. | unions.cpp:30:14:30:18 | small | destination buffer | | unions.cpp:30:2:30:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:15:7:15:11 | small | destination buffer | | unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:16:7:16:11 | large | destination buffer | -| unions.cpp:34:2:34:7 | call to memset | This 'memset' operation accesses 200 bytes but the $@ is only 100 bytes. | unions.cpp:34:14:34:18 | large | destination buffer | | var_size_struct.cpp:71:3:71:8 | call to memset | This 'memset' operation accesses 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer | | var_size_struct.cpp:73:3:73:9 | call to strncpy | This 'strncpy' operation may access 1025 bytes but the $@ is only 1024 bytes. | var_size_struct.cpp:63:8:63:11 | data | destination buffer | | var_size_struct.cpp:87:3:87:19 | access to array | This array indexing operation accesses byte offset 67 but the $@ is only 64 bytes. | var_size_struct.cpp:78:7:78:14 | elements | array | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowDestination.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowDestination.expected index 6a183de8d21..19de8c61578 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowDestination.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/OverflowDestination.expected @@ -1,52 +1,49 @@ edges -| main.cpp:6:27:6:30 | argv | main.cpp:7:33:7:36 | argv | -| main.cpp:6:27:6:30 | argv | main.cpp:7:33:7:36 | argv indirection | -| main.cpp:7:33:7:36 | argv | overflowdestination.cpp:23:45:23:48 | argv | -| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | *argv | -| overflowdestination.cpp:23:45:23:48 | *argv | overflowdestination.cpp:30:17:30:20 | (const char *)... | -| overflowdestination.cpp:23:45:23:48 | argv | overflowdestination.cpp:30:17:30:20 | (const char *)... | -| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | (const void *)... | -| overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | ReturnIndirection | -| overflowdestination.cpp:50:52:50:54 | src | overflowdestination.cpp:53:15:53:17 | (const void *)... | -| overflowdestination.cpp:57:52:57:54 | *src | overflowdestination.cpp:64:16:64:19 | (const void *)... | -| overflowdestination.cpp:57:52:57:54 | src | overflowdestination.cpp:64:16:64:19 | (const void *)... | -| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src | +| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection | +| main.cpp:6:27:6:30 | argv indirection | main.cpp:7:33:7:36 | argv indirection | +| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection | +| main.cpp:7:33:7:36 | argv indirection | overflowdestination.cpp:23:45:23:48 | argv indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | +| overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | +| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection | +| overflowdestination.cpp:50:52:50:54 | src indirection | overflowdestination.cpp:53:15:53:17 | src indirection | +| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection | +| overflowdestination.cpp:57:52:57:54 | src indirection | overflowdestination.cpp:64:16:64:19 | src2 indirection | | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:75:30:75:32 | src indirection | -| overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src | | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:76:30:76:32 | src indirection | -| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src | -| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | overflowdestination.cpp:76:30:76:32 | src indirection | -| overflowdestination.cpp:75:30:75:32 | src | overflowdestination.cpp:50:52:50:54 | src | -| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | *src | -| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | -| overflowdestination.cpp:76:30:76:32 | src | overflowdestination.cpp:57:52:57:54 | src | -| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | *src | +| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | src indirection | +| overflowdestination.cpp:76:30:76:32 | src indirection | overflowdestination.cpp:57:52:57:54 | src indirection | nodes -| main.cpp:6:27:6:30 | argv | semmle.label | argv | -| main.cpp:7:33:7:36 | argv | semmle.label | argv | +| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection | +| main.cpp:6:27:6:30 | argv indirection | semmle.label | argv indirection | | main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection | -| overflowdestination.cpp:23:45:23:48 | *argv | semmle.label | *argv | -| overflowdestination.cpp:23:45:23:48 | argv | semmle.label | argv | -| overflowdestination.cpp:30:17:30:20 | (const char *)... | semmle.label | (const char *)... | +| main.cpp:7:33:7:36 | argv indirection | semmle.label | argv indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection | +| overflowdestination.cpp:23:45:23:48 | argv indirection | semmle.label | argv indirection | +| overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection | +| overflowdestination.cpp:30:17:30:20 | arg1 indirection | semmle.label | arg1 indirection | | overflowdestination.cpp:43:8:43:10 | fgets output argument | semmle.label | fgets output argument | -| overflowdestination.cpp:46:15:46:17 | (const void *)... | semmle.label | (const void *)... | -| overflowdestination.cpp:50:52:50:54 | *src | semmle.label | *src | -| overflowdestination.cpp:50:52:50:54 | ReturnIndirection | semmle.label | ReturnIndirection | -| overflowdestination.cpp:50:52:50:54 | src | semmle.label | src | -| overflowdestination.cpp:53:15:53:17 | (const void *)... | semmle.label | (const void *)... | -| overflowdestination.cpp:57:52:57:54 | *src | semmle.label | *src | -| overflowdestination.cpp:57:52:57:54 | src | semmle.label | src | -| overflowdestination.cpp:64:16:64:19 | (const void *)... | semmle.label | (const void *)... | +| overflowdestination.cpp:46:15:46:17 | src indirection | semmle.label | src indirection | +| overflowdestination.cpp:50:52:50:54 | src indirection | semmle.label | src indirection | +| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection | +| overflowdestination.cpp:53:15:53:17 | src indirection | semmle.label | src indirection | +| overflowdestination.cpp:57:52:57:54 | src indirection | semmle.label | src indirection | +| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection | +| overflowdestination.cpp:64:16:64:19 | src2 indirection | semmle.label | src2 indirection | | overflowdestination.cpp:73:8:73:10 | fgets output argument | semmle.label | fgets output argument | -| overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | semmle.label | overflowdest_test2 output argument | -| overflowdestination.cpp:75:30:75:32 | src | semmle.label | src | | overflowdestination.cpp:75:30:75:32 | src indirection | semmle.label | src indirection | -| overflowdestination.cpp:76:30:76:32 | src | semmle.label | src | | overflowdestination.cpp:76:30:76:32 | src indirection | semmle.label | src indirection | subpaths -| overflowdestination.cpp:75:30:75:32 | src indirection | overflowdestination.cpp:50:52:50:54 | *src | overflowdestination.cpp:50:52:50:54 | ReturnIndirection | overflowdestination.cpp:75:30:75:32 | overflowdest_test2 output argument | #select -| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv | overflowdestination.cpp:30:17:30:20 | (const char *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | -| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | -| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | -| overflowdestination.cpp:64:2:64:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:64:16:64:19 | (const void *)... | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:30:2:30:8 | call to strncpy | main.cpp:6:27:6:30 | argv indirection | overflowdestination.cpp:30:17:30:20 | arg1 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:46:2:46:7 | call to memcpy | overflowdestination.cpp:43:8:43:10 | fgets output argument | overflowdestination.cpp:46:15:46:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:53:2:53:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:53:15:53:17 | src indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:64:2:64:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:64:16:64:19 | src2 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | +| overflowdestination.cpp:64:2:64:7 | call to memcpy | overflowdestination.cpp:73:8:73:10 | fgets output argument | overflowdestination.cpp:64:16:64:19 | src2 indirection | To avoid overflow, this operation should be bounded by destination-buffer size, not source-buffer size. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp index 42c06043927..6dbbcdd4b3e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-119/semmle/tests/tests.cpp @@ -576,7 +576,7 @@ void test21(bool cond) } else { if (ptr[-1] == 0) { return; } // BAD: accesses buffer[-1] } - if (ptr[-1] == 0) { return; } // BAD: accesses buffer[-1] or buffer[0] + if (ptr[-1] == 0) { return; } // BAD: accesses buffer[-1] or buffer[0] [NOT DETECTED] ptr = buffer; for (i = 0; i < 2; i++) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected index 170593664f2..e4e9618378d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected @@ -1,51 +1,42 @@ edges -| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | -| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | (const char *)... | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | -| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array indirection | -| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array indirection | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | +| tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | -| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array indirection | -| tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array indirection | -| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | -| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | (const char *)... | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | | tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | -| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array indirection | -| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array indirection | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | +| tests.c:34:10:34:13 | argv | tests.c:34:10:34:16 | access to array | subpaths nodes | tests.c:28:22:28:25 | argv | semmle.label | argv | | tests.c:28:22:28:25 | argv | semmle.label | argv | -| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | | tests.c:28:22:28:28 | access to array | semmle.label | access to array | | tests.c:28:22:28:28 | access to array | semmle.label | access to array | -| tests.c:28:22:28:28 | access to array indirection | semmle.label | access to array indirection | +| tests.c:28:22:28:28 | access to array | semmle.label | access to array | | tests.c:29:28:29:31 | argv | semmle.label | argv | | tests.c:29:28:29:31 | argv | semmle.label | argv | | tests.c:29:28:29:34 | access to array | semmle.label | access to array | | tests.c:29:28:29:34 | access to array | semmle.label | access to array | -| tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection | -| tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | -| tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | +| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | | tests.c:34:10:34:13 | argv | semmle.label | argv | | tests.c:34:10:34:13 | argv | semmle.label | argv | -| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | | tests.c:34:10:34:16 | access to array | semmle.label | access to array | | tests.c:34:10:34:16 | access to array | semmle.label | access to array | -| tests.c:34:10:34:16 | access to array indirection | semmle.label | access to array indirection | +| tests.c:34:10:34:16 | access to array | semmle.label | access to array | #select | tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | | tests.c:29:3:29:9 | call to sprintf | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/VeryLikelyOverrunWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/VeryLikelyOverrunWrite.expected index de37e8985dd..c20cf040504 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/VeryLikelyOverrunWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/VeryLikelyOverrunWrite.expected @@ -19,5 +19,4 @@ | unions.c:26:2:26:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. | | unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 15 bytes. | | unions.c:27:2:27:7 | call to strcpy | This 'call to strcpy' operation requires 21 bytes but the destination is only 16 bytes. | -| unions.c:32:2:32:7 | call to strcpy | This 'call to strcpy' operation requires 31 bytes but the destination is only 25 bytes. | | var_size_struct.cpp:22:3:22:8 | call to strcpy | This 'call to strcpy' operation requires 10 bytes but the destination is only 9 bytes. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/unions.c b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/unions.c index b31adf5e6b4..68c9aff9c2b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/unions.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/unions.c @@ -29,5 +29,5 @@ void unions_test(MyUnion *mu) mu->ptr = buffer; strcpy(mu->ptr, "1234567890"); // GOOD strcpy(mu->ptr, "12345678901234567890"); // GOOD - strcpy(mu->ptr, "123456789012345678901234567890"); // BAD + strcpy(mu->ptr, "123456789012345678901234567890"); // BAD [NOT DETECTED] } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-129/semmle/ImproperArrayIndexValidation/ImproperArrayIndexValidation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-129/semmle/ImproperArrayIndexValidation/ImproperArrayIndexValidation.expected index 721db6b35f1..b20b8a48afa 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-129/semmle/ImproperArrayIndexValidation/ImproperArrayIndexValidation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-129/semmle/ImproperArrayIndexValidation/ImproperArrayIndexValidation.expected @@ -2,6 +2,12 @@ edges | test1.c:7:26:7:29 | argv | test1.c:9:9:9:9 | i | | test1.c:7:26:7:29 | argv | test1.c:11:9:11:9 | i | | test1.c:7:26:7:29 | argv | test1.c:13:9:13:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i | +| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i | | test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i | | test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i | | test1.c:13:9:13:9 | i | test1.c:48:16:48:16 | i | @@ -10,6 +16,8 @@ edges | test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j | nodes | test1.c:7:26:7:29 | argv | semmle.label | argv | +| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection | +| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection | | test1.c:9:9:9:9 | i | semmle.label | i | | test1.c:11:9:11:9 | i | semmle.label | i | | test1.c:13:9:13:9 | i | semmle.label | i | @@ -22,5 +30,11 @@ nodes subpaths #select | test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument | +| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | +| test1.c:18:16:18:16 | i | test1.c:7:26:7:29 | argv indirection | test1.c:18:16:18:16 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | | test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument | +| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | +| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | | test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument | +| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | +| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected index aa09038581e..61790cfe831 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected @@ -1,45 +1,36 @@ edges | char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | | char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | -| char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | -| char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | -| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data | | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data | -| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | -| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | +| char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data | +| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data | | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data | | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data | -| char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | -| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | -| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | -| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | -| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | +| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | +| char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | char_environment_fprintf_01_bad.c:36:21:36:24 | data | subpaths nodes | char_connect_socket_w32_vsnprintf_01_bad.c:94:46:94:69 | recv output argument | semmle.label | recv output argument | | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | semmle.label | ... + ... | | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data | | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data | -| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection | | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | semmle.label | ... + ... | | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | semmle.label | fgets output argument | -| char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | semmle.label | (const char *)... | | char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | | char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | -| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection | +| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv | -| char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | semmle.label | (const char *)... | | char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | | char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | -| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection | +| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | #select | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | The value of this argument may come from $@ and is being used as a formatting argument to badVaSink(data), which calls vsnprintf(format). | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | recv | | char_console_fprintf_01_bad.c:49:21:49:24 | data | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | char_console_fprintf_01_bad.c:49:21:49:24 | data | The value of this argument may come from $@ and is being used as a formatting argument to fprintf(format). | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | fgets | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.c b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.c index e90fba6530a..e60756e76bf 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.c +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.c @@ -150,14 +150,14 @@ int main(int argc, char **argv) { printf(i8); printWrapper(i8); - // BAD: i9 value comes from argv + // BAD: i9 value comes from argv [NOT DETECTED] char i9buf[32]; char *i9 = i9buf; memcpy(1 ? ++i9 : 0, argv[1], 1); printf(i9); printWrapper(i9); - // BAD: i91 value comes from argv + // BAD: i91 value comes from argv [NOT DETECTED] char i91buf[64]; char *i91 = &i91buf[0]; memcpy(0 ? 0 : i91, argv[1] + 1, 1); @@ -169,7 +169,7 @@ int main(int argc, char **argv) { printf((char *) i10); printWrapper((char *) i10); - // BAD: b value comes from argv + // BAD: b value comes from argv [NOT DETECTED] { char b[64]; char *bp = &b[0]; @@ -184,7 +184,7 @@ int main(int argc, char **argv) { printWrapper(bp); } - // BAD: b value comes from argv + // BAD: b value comes from argv [NOT DETECTED] { char b[64]; char *bp = &b[0]; diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 96467f96caa..c422484ea7d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -1,441 +1,226 @@ edges -| argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | -| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | -| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | (const char *)... | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | -| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array indirection | -| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array indirection | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | +| argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | -| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array indirection | -| argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | (const char *)... | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 indirection | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:101:9:101:10 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:102:15:102:16 | i1 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | (const char *)... | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 indirection | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | +| argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 indirection | -| argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 indirection | -| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:9:25:9:31 | *correct | -| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:102:15:102:16 | printWrapper output argument | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:144:9:144:10 | (const char *)... | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:144:9:144:10 | i7 | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:144:9:144:10 | i7 | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:144:9:144:10 | i7 indirection | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:145:15:145:16 | i7 | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:145:15:145:16 | i7 | -| argvLocal.c:102:15:102:16 | printWrapper output argument | argvLocal.c:145:15:145:16 | i7 indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | (const char *)... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array indirection | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:106:9:106:13 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:107:15:107:19 | access to array indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | (const char *)... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... indirection | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | +| argvLocal.c:105:14:105:17 | argv | argvLocal.c:110:9:110:11 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | | argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... indirection | -| argvLocal.c:105:14:105:17 | argv | argvLocal.c:111:15:111:17 | * ... indirection | -| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:9:25:9:31 | *correct | -| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:107:15:107:19 | printWrapper output argument | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:110:9:110:11 | (const char *)... | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:110:9:110:11 | * ... | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:110:9:110:11 | * ... | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:110:9:110:11 | * ... indirection | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:111:15:111:17 | * ... | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:111:15:111:17 | * ... | -| argvLocal.c:107:15:107:19 | printWrapper output argument | argvLocal.c:111:15:111:17 | * ... indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | array to pointer conversion | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:116:9:116:10 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:117:15:117:16 | i3 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:121:9:121:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:122:15:122:16 | i4 indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:10 | i4 | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | (const char *)... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ indirection | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | +| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection | -| argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... indirection | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 | | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:17:136:18 | i4 | -| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:9:25:9:31 | *correct | -| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:117:15:117:16 | printWrapper output argument | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | (const char *)... | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:121:9:121:10 | i4 indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:122:15:122:16 | i4 indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:10 | i4 | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | argvLocal.c:136:17:136:18 | i4 | -| argvLocal.c:122:15:122:16 | i4 indirection | argvLocal.c:9:25:9:31 | *correct | -| argvLocal.c:122:15:122:16 | i4 indirection | argvLocal.c:122:15:122:16 | printWrapper output argument | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:10 | i4 | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | (const char *)... | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:135:9:135:12 | ... ++ indirection | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:15:136:18 | -- ... indirection | -| argvLocal.c:122:15:122:16 | printWrapper output argument | argvLocal.c:136:17:136:18 | i4 | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | array to pointer conversion | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:127:9:127:10 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:128:15:128:16 | i5 indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | (const char *)... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... indirection | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:131:9:131:14 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... indirection | -| argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... indirection | -| argvLocal.c:128:15:128:16 | i5 indirection | argvLocal.c:9:25:9:31 | *correct | -| argvLocal.c:128:15:128:16 | i5 indirection | argvLocal.c:128:15:128:16 | printWrapper output argument | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | (const char *)... | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:131:9:131:14 | ... + ... indirection | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... | -| argvLocal.c:128:15:128:16 | printWrapper output argument | argvLocal.c:132:15:132:20 | ... + ... indirection | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | (const char *)... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | +| argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | +| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 indirection | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 indirection | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 indirection | -| argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 indirection | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | (const char *)... | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 indirection | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 indirection | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 indirection | -| argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 indirection | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | (const char *)... | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 indirection | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 indirection | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 indirection | -| argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 indirection | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | (const char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 indirection | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 indirection | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:9:169:20 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | (char *)... | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 indirection | -| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 indirection | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 | +| argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:15:170:26 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | (const char *)... | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | (const char *)... | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp indirection | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp indirection | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp indirection | -| argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp indirection | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | (const char *)... | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | (const char *)... | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp indirection | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp indirection | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp indirection | -| argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp indirection | subpaths -| argvLocal.c:102:15:102:16 | i1 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:102:15:102:16 | printWrapper output argument | -| argvLocal.c:107:15:107:19 | access to array indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:107:15:107:19 | printWrapper output argument | -| argvLocal.c:117:15:117:16 | i3 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:117:15:117:16 | printWrapper output argument | -| argvLocal.c:122:15:122:16 | i4 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:122:15:122:16 | printWrapper output argument | -| argvLocal.c:128:15:128:16 | i5 indirection | argvLocal.c:9:25:9:31 | *correct | argvLocal.c:9:25:9:31 | ReturnIndirection | argvLocal.c:128:15:128:16 | printWrapper output argument | nodes -| argvLocal.c:9:25:9:31 | *correct | semmle.label | *correct | -| argvLocal.c:9:25:9:31 | ReturnIndirection | semmle.label | ReturnIndirection | | argvLocal.c:95:9:95:12 | argv | semmle.label | argv | | argvLocal.c:95:9:95:12 | argv | semmle.label | argv | -| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | -| argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection | +| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:18 | argv | semmle.label | argv | | argvLocal.c:96:15:96:18 | argv | semmle.label | argv | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | -| argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:100:7:100:10 | argv | semmle.label | argv | | argvLocal.c:100:7:100:10 | argv | semmle.label | argv | -| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | | argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | -| argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection | +| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | -| argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection | -| argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection | -| argvLocal.c:102:15:102:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:105:14:105:17 | argv | semmle.label | argv | | argvLocal.c:105:14:105:17 | argv | semmle.label | argv | -| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | | argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | -| argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection | +| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | | argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | | argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | -| argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection | -| argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection | -| argvLocal.c:107:15:107:19 | printWrapper output argument | semmle.label | printWrapper output argument | -| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | | argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | -| argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection | +| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | -| argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection | | argvLocal.c:115:13:115:16 | argv | semmle.label | argv | | argvLocal.c:115:13:115:16 | argv | semmle.label | argv | -| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | -| argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection | -| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | +| argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 | | argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 | -| argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection | -| argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection | -| argvLocal.c:117:15:117:16 | printWrapper output argument | semmle.label | printWrapper output argument | -| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | -| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection | +| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | -| argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection | -| argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection | -| argvLocal.c:122:15:122:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:126:10:126:13 | argv | semmle.label | argv | | argvLocal.c:126:10:126:13 | argv | semmle.label | argv | -| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | -| argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection | -| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | +| argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | +| argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 | | argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 | -| argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection | -| argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection | -| argvLocal.c:128:15:128:16 | printWrapper output argument | semmle.label | printWrapper output argument | -| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection | +| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | +| argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | | argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | | argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection | | argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 | -| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | | argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | -| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection | +| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | +| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | -| argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection | | argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 | -| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | +| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:139:9:139:26 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:140:15:140:32 | ... ? ... : ... | semmle.label | ... ? ... : ... | +| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | | argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | | argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | -| argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | -| argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:149:11:149:14 | argv | semmle.label | argv | | argvLocal.c:149:11:149:14 | argv | semmle.label | argv | -| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | | argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | -| argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection | +| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | -| argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection | -| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | -| argvLocal.c:156:23:156:26 | argv | semmle.label | argv | -| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 | -| argvLocal.c:157:9:157:10 | i9 indirection | semmle.label | i9 indirection | -| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | -| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | -| argvLocal.c:158:15:158:16 | i9 indirection | semmle.label | i9 indirection | -| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | -| argvLocal.c:163:22:163:25 | argv | semmle.label | argv | -| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 | -| argvLocal.c:164:9:164:11 | i91 indirection | semmle.label | i91 indirection | -| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | -| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | -| argvLocal.c:165:15:165:17 | i91 indirection | semmle.label | i91 indirection | | argvLocal.c:168:18:168:21 | argv | semmle.label | argv | | argvLocal.c:168:18:168:21 | argv | semmle.label | argv | -| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | -| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:169:9:169:20 | i10 indirection | semmle.label | i10 indirection | +| argvLocal.c:169:9:169:20 | i10 | semmle.label | i10 | +| argvLocal.c:169:9:169:20 | i10 | semmle.label | i10 | | argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | | argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | -| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | -| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection | +| argvLocal.c:170:15:170:26 | i10 | semmle.label | i10 | | argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | | argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | -| argvLocal.c:182:13:182:16 | argv | semmle.label | argv | -| argvLocal.c:182:13:182:16 | argv | semmle.label | argv | -| argvLocal.c:183:10:183:11 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:183:10:183:11 | bp | semmle.label | bp | -| argvLocal.c:183:10:183:11 | bp indirection | semmle.label | bp indirection | -| argvLocal.c:184:16:184:17 | bp | semmle.label | bp | -| argvLocal.c:184:16:184:17 | bp | semmle.label | bp | -| argvLocal.c:184:16:184:17 | bp indirection | semmle.label | bp indirection | -| argvLocal.c:197:13:197:16 | argv | semmle.label | argv | -| argvLocal.c:197:13:197:16 | argv | semmle.label | argv | -| argvLocal.c:198:10:198:11 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:198:10:198:11 | bp | semmle.label | bp | -| argvLocal.c:198:10:198:11 | bp indirection | semmle.label | bp indirection | -| argvLocal.c:199:16:199:17 | bp | semmle.label | bp | -| argvLocal.c:199:16:199:17 | bp | semmle.label | bp | -| argvLocal.c:199:16:199:17 | bp indirection | semmle.label | bp indirection | #select | argvLocal.c:95:9:95:15 | access to array | argvLocal.c:95:9:95:12 | argv | argvLocal.c:95:9:95:15 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:95:9:95:12 | argv | argv | | argvLocal.c:96:15:96:21 | access to array | argvLocal.c:96:15:96:18 | argv | argvLocal.c:96:15:96:21 | access to array | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:96:15:96:18 | argv | argv | @@ -455,17 +240,11 @@ nodes | argvLocal.c:132:15:132:20 | ... + ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:132:15:132:20 | ... + ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:126:10:126:13 | argv | argv | | argvLocal.c:135:9:135:12 | ... ++ | argvLocal.c:115:13:115:16 | argv | argvLocal.c:135:9:135:12 | ... ++ | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:115:13:115:16 | argv | argv | | argvLocal.c:136:15:136:18 | -- ... | argvLocal.c:115:13:115:16 | argv | argvLocal.c:136:15:136:18 | -- ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:115:13:115:16 | argv | argv | +| argvLocal.c:139:9:139:26 | ... ? ... : ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:139:9:139:26 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:126:10:126:13 | argv | argv | +| argvLocal.c:140:15:140:32 | ... ? ... : ... | argvLocal.c:126:10:126:13 | argv | argvLocal.c:140:15:140:32 | ... ? ... : ... | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:126:10:126:13 | argv | argv | | argvLocal.c:144:9:144:10 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:144:9:144:10 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:100:7:100:10 | argv | argv | | argvLocal.c:145:15:145:16 | i7 | argvLocal.c:100:7:100:10 | argv | argvLocal.c:145:15:145:16 | i7 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:100:7:100:10 | argv | argv | | argvLocal.c:150:9:150:10 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:150:9:150:10 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:149:11:149:14 | argv | argv | | argvLocal.c:151:15:151:16 | i8 | argvLocal.c:149:11:149:14 | argv | argvLocal.c:151:15:151:16 | i8 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:149:11:149:14 | argv | argv | -| argvLocal.c:157:9:157:10 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:157:9:157:10 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:158:15:158:16 | i9 | argvLocal.c:156:23:156:26 | argv | argvLocal.c:158:15:158:16 | i9 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:156:23:156:26 | argv | argv | -| argvLocal.c:164:9:164:11 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:164:9:164:11 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:163:22:163:25 | argv | argv | -| argvLocal.c:165:15:165:17 | i91 | argvLocal.c:163:22:163:25 | argv | argvLocal.c:165:15:165:17 | i91 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:163:22:163:25 | argv | argv | | argvLocal.c:169:18:169:20 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:169:18:169:20 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:168:18:168:21 | argv | argv | | argvLocal.c:170:24:170:26 | i10 | argvLocal.c:168:18:168:21 | argv | argvLocal.c:170:24:170:26 | i10 | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:168:18:168:21 | argv | argv | -| argvLocal.c:183:10:183:11 | bp | argvLocal.c:182:13:182:16 | argv | argvLocal.c:183:10:183:11 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:182:13:182:16 | argv | argv | -| argvLocal.c:184:16:184:17 | bp | argvLocal.c:182:13:182:16 | argv | argvLocal.c:184:16:184:17 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:182:13:182:16 | argv | argv | -| argvLocal.c:198:10:198:11 | bp | argvLocal.c:197:13:197:16 | argv | argvLocal.c:198:10:198:11 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | argvLocal.c:197:13:197:16 | argv | argv | -| argvLocal.c:199:16:199:17 | bp | argvLocal.c:197:13:197:16 | argv | argvLocal.c:199:16:199:17 | bp | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(correct), which calls printf(format). | argvLocal.c:197:13:197:16 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected index 8f63ffb72d8..6a4d7c8d7a9 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/consts/NonConstantFormat.expected @@ -8,6 +8,7 @@ | consts.cpp:112:9:112:10 | v6 | The format string argument to printf should be constant to prevent security issues and other potential errors. | | consts.cpp:116:9:116:13 | access to array | The format string argument to printf should be constant to prevent security issues and other potential errors. | | consts.cpp:121:9:121:10 | v8 | The format string argument to printf should be constant to prevent security issues and other potential errors. | +| consts.cpp:126:9:126:27 | call to nonConstFuncToArray | The format string argument to printf should be constant to prevent security issues and other potential errors. | | consts.cpp:130:9:130:10 | v9 | The format string argument to printf should be constant to prevent security issues and other potential errors. | | consts.cpp:135:9:135:11 | v10 | The format string argument to printf should be constant to prevent security issues and other potential errors. | | consts.cpp:140:9:140:11 | v11 | The format string argument to printf should be constant to prevent security issues and other potential errors. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index ce144369695..c7896725492 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -1,140 +1,101 @@ edges -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:17:9:17:10 | (const char *)... | -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:17:9:17:10 | i1 | -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:17:9:17:10 | i1 indirection | -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:58:9:58:10 | (const char *)... | -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:58:9:58:10 | e1 | -| funcsLocal.c:16:8:16:9 | (void *)... | funcsLocal.c:58:9:58:10 | e1 indirection | -| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | (const char *)... | | funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 | -| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 indirection | -| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 | | funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 | -| funcsLocal.c:16:8:16:9 | fread output argument | funcsLocal.c:58:9:58:10 | e1 indirection | -| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | (const char *)... | | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | -| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 indirection | -| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | (const char *)... | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | +| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | -| funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 indirection | -| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | (const char *)... | | funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 | -| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 indirection | -| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | (const char *)... | +| funcsLocal.c:26:8:26:9 | fgets output argument | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | +| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | -| funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 indirection | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | (const char *)... | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 indirection | -| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 indirection | -| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | (const char *)... | -| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:19:31:21 | fgets output argument | funcsLocal.c:32:9:32:10 | i4 indirection | -| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | (const char *)... | -| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | -| funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 indirection | -| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | (const char *)... | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | +| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 | | funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 | -| funcsLocal.c:36:7:36:8 | gets output argument | funcsLocal.c:37:9:37:10 | i5 indirection | -| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | (const char *)... | | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | -| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 indirection | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | (const char *)... | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | +| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 indirection | -| funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 indirection | -| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | (const char *)... | -| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:18:41:20 | gets output argument | funcsLocal.c:42:9:42:10 | i6 indirection | -| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | (const char *)... | -| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | -| funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 indirection | -| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | (const char *)... | -| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | (const char *)... | | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | -| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... indirection | -| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... indirection | -| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | (const char *)... | +| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | +| funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | +| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... | | funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... | | funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... | -| funcsLocal.c:46:7:46:9 | gets output argument | funcsLocal.c:47:9:47:11 | * ... indirection | -| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | (const char *)... | -| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | (const char *)... | | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | -| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... indirection | -| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... indirection | +| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | +| funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | subpaths nodes -| funcsLocal.c:16:8:16:9 | (void *)... | semmle.label | (void *)... | | funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument | | funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | -| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | +| funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | | funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | -| funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection | | funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument | | funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | -| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | +| funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | | funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | -| funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | -| funcsLocal.c:31:19:31:21 | fgets output argument | semmle.label | fgets output argument | -| funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 | -| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | -| funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection | +| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | -| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | +| funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | | funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | -| funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | -| funcsLocal.c:41:18:41:20 | gets output argument | semmle.label | gets output argument | -| funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 | -| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | -| funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection | +| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | | funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... | | funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... | | funcsLocal.c:46:7:46:9 | gets output argument | semmle.label | gets output argument | -| funcsLocal.c:47:9:47:11 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | | funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | -| funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection | +| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | | funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets | | funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets | -| funcsLocal.c:53:9:53:11 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | | funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | -| funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection | -| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... | +| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | +| funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | | funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | -| funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection | #select | funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread | | funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:26:8:26:9 | i3 | fgets | | funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:13:31:17 | call to fgets | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:31:13:31:17 | call to fgets | fgets | -| funcsLocal.c:32:9:32:10 | i4 | funcsLocal.c:31:19:31:21 | i41 | funcsLocal.c:32:9:32:10 | i4 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:31:19:31:21 | i41 | fgets | | funcsLocal.c:37:9:37:10 | i5 | funcsLocal.c:36:7:36:8 | i5 | funcsLocal.c:37:9:37:10 | i5 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:36:7:36:8 | i5 | gets | | funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:13:41:16 | call to gets | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:41:13:41:16 | call to gets | gets | -| funcsLocal.c:42:9:42:10 | i6 | funcsLocal.c:41:18:41:20 | i61 | funcsLocal.c:42:9:42:10 | i6 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:41:18:41:20 | i61 | gets | | funcsLocal.c:47:9:47:11 | * ... | funcsLocal.c:46:7:46:9 | * ... | funcsLocal.c:47:9:47:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:46:7:46:9 | * ... | gets | | funcsLocal.c:53:9:53:11 | * ... | funcsLocal.c:52:8:52:11 | call to gets | funcsLocal.c:53:9:53:11 | * ... | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:52:8:52:11 | call to gets | gets | | funcsLocal.c:58:9:58:10 | e1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:58:9:58:10 | e1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected index 90743a71178..33015407b83 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected @@ -4,122 +4,42 @@ edges | globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:8:7:8:10 | copy | globalVars.c:33:15:33:18 | copy | | globalVars.c:8:7:8:10 | copy | globalVars.c:35:11:35:14 | copy | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:11:22:11:25 | *argv | globalVars.c:12:2:12:15 | Store | -| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store | -| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy | -| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store | -| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 | -| globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | +| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy | +| globalVars.c:15:21:15:23 | val | globalVars.c:9:7:9:11 | copy2 | +| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | | globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection | -| globalVars.c:24:11:24:14 | argv indirection | globalVars.c:11:22:11:25 | *argv | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy indirection | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection | -| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy | -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str | -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:30:15:30:18 | printWrapper output argument | -| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:11:35:14 | copy | -| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy | | globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val | -| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:41:15:41:19 | printWrapper output argument | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | subpaths -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:30:15:30:18 | printWrapper output argument | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:41:15:41:19 | printWrapper output argument | nodes | globalVars.c:8:7:8:10 | copy | semmle.label | copy | | globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 | -| globalVars.c:11:22:11:25 | *argv | semmle.label | *argv | | globalVars.c:11:22:11:25 | argv | semmle.label | argv | -| globalVars.c:12:2:12:15 | Store | semmle.label | Store | | globalVars.c:15:21:15:23 | val | semmle.label | val | -| globalVars.c:16:2:16:12 | Store | semmle.label | Store | -| globalVars.c:19:25:19:27 | *str | semmle.label | *str | -| globalVars.c:19:25:19:27 | ReturnIndirection | semmle.label | ReturnIndirection | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | -| globalVars.c:24:11:24:14 | argv | semmle.label | argv | -| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection | -| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | -| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | -| globalVars.c:30:15:30:18 | copy | semmle.label | copy | -| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection | -| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection | -| globalVars.c:30:15:30:18 | printWrapper output argument | semmle.label | printWrapper output argument | -| globalVars.c:33:15:33:18 | copy | semmle.label | copy | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | -| globalVars.c:35:11:35:14 | copy | semmle.label | copy | -| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | -| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | -| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | -| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument | -| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 | -| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | -| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | #select | globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv | | globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 90743a71178..c79d2e7e934 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -17,109 +17,58 @@ edges | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:11:22:11:25 | *argv | globalVars.c:12:2:12:15 | Store | -| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | Store | -| globalVars.c:12:2:12:15 | Store | globalVars.c:8:7:8:10 | copy | -| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | Store | -| globalVars.c:16:2:16:12 | Store | globalVars.c:9:7:9:11 | copy2 | -| globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | +| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy | +| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | ... = ... | +| globalVars.c:12:2:12:15 | ... = ... | globalVars.c:8:7:8:10 | copy | +| globalVars.c:15:21:15:23 | val | globalVars.c:9:7:9:11 | copy2 | +| globalVars.c:15:21:15:23 | val | globalVars.c:16:2:16:12 | ... = ... | +| globalVars.c:16:2:16:12 | ... = ... | globalVars.c:9:7:9:11 | copy2 | +| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | | globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection | -| globalVars.c:24:11:24:14 | argv | globalVars.c:24:11:24:14 | argv indirection | -| globalVars.c:24:11:24:14 | argv indirection | globalVars.c:11:22:11:25 | *argv | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | (const char *)... | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy | -| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy indirection | | globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | | globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection | -| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy indirection | | globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy | -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str | -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:30:15:30:18 | printWrapper output argument | -| globalVars.c:30:15:30:18 | printWrapper output argument | globalVars.c:35:11:35:14 | copy | | globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy | | globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val | | globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | (const char *)... | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 | -| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 indirection | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:41:15:41:19 | printWrapper output argument | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:41:15:41:19 | printWrapper output argument | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | | globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | | globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | (const char *)... | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 | -| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 indirection | subpaths -| globalVars.c:30:15:30:18 | copy indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:30:15:30:18 | printWrapper output argument | -| globalVars.c:41:15:41:19 | copy2 indirection | globalVars.c:19:25:19:27 | *str | globalVars.c:19:25:19:27 | ReturnIndirection | globalVars.c:41:15:41:19 | printWrapper output argument | nodes | globalVars.c:8:7:8:10 | copy | semmle.label | copy | | globalVars.c:9:7:9:11 | copy2 | semmle.label | copy2 | -| globalVars.c:11:22:11:25 | *argv | semmle.label | *argv | | globalVars.c:11:22:11:25 | argv | semmle.label | argv | -| globalVars.c:12:2:12:15 | Store | semmle.label | Store | +| globalVars.c:12:2:12:15 | ... = ... | semmle.label | ... = ... | | globalVars.c:15:21:15:23 | val | semmle.label | val | -| globalVars.c:16:2:16:12 | Store | semmle.label | Store | -| globalVars.c:19:25:19:27 | *str | semmle.label | *str | -| globalVars.c:19:25:19:27 | ReturnIndirection | semmle.label | ReturnIndirection | +| globalVars.c:16:2:16:12 | ... = ... | semmle.label | ... = ... | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv | semmle.label | argv | -| globalVars.c:24:11:24:14 | argv | semmle.label | argv | -| globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection | -| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | -| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | -| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection | -| globalVars.c:30:15:30:18 | copy indirection | semmle.label | copy indirection | -| globalVars.c:30:15:30:18 | printWrapper output argument | semmle.label | printWrapper output argument | | globalVars.c:33:15:33:18 | copy | semmle.label | copy | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | -| globalVars.c:35:11:35:14 | copy | semmle.label | copy | -| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | -| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | -| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:41:15:41:19 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument | | globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 | -| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | -| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | #select | globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv | | globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected index cc1fde25ef5..cac090d1c93 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected @@ -1,160 +1,127 @@ edges -| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | -| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | (const char *)... | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | -| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 indirection | -| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 indirection | -| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | -| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | (const char *)... | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | +| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | -| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 indirection | -| ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 indirection | -| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | -| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | (const char *)... | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | | ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | -| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 indirection | -| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 indirection | -| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | -| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | (const char *)... | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:74:8:74:11 | argv | ifs.c:75:9:75:10 | i1 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | +| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | | ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 | -| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 indirection | -| ifs.c:80:8:80:11 | argv | ifs.c:81:9:81:10 | i2 indirection | -| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | -| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | (const char *)... | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | | ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | -| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 indirection | -| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 indirection | -| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | -| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | (const char *)... | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:86:8:86:11 | argv | ifs.c:87:9:87:10 | i3 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | +| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | | ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 | -| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 indirection | -| ifs.c:92:8:92:11 | argv | ifs.c:93:9:93:10 | i4 indirection | -| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | -| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | (const char *)... | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | | ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | -| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 indirection | -| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 indirection | -| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | -| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | (const char *)... | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:98:8:98:11 | argv | ifs.c:99:9:99:10 | i5 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | +| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | | ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 | -| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 indirection | -| ifs.c:105:8:105:11 | argv | ifs.c:106:9:106:10 | i6 indirection | -| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | -| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | (const char *)... | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | | ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | -| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 indirection | -| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 indirection | -| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | -| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | (const char *)... | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:111:8:111:11 | argv | ifs.c:112:9:112:10 | i7 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | +| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | | ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 | -| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 indirection | -| ifs.c:117:8:117:11 | argv | ifs.c:118:9:118:10 | i8 indirection | -| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | -| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | (const char *)... | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | | ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | -| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 indirection | -| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 indirection | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | +| ifs.c:123:8:123:11 | argv | ifs.c:124:9:124:10 | i9 | subpaths nodes | ifs.c:61:8:61:11 | argv | semmle.label | argv | | ifs.c:61:8:61:11 | argv | semmle.label | argv | -| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | -| ifs.c:62:9:62:10 | c7 indirection | semmle.label | c7 indirection | +| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:68:8:68:11 | argv | semmle.label | argv | | ifs.c:68:8:68:11 | argv | semmle.label | argv | -| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | -| ifs.c:69:9:69:10 | c8 indirection | semmle.label | c8 indirection | +| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:74:8:74:11 | argv | semmle.label | argv | | ifs.c:74:8:74:11 | argv | semmle.label | argv | -| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | -| ifs.c:75:9:75:10 | i1 indirection | semmle.label | i1 indirection | +| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:80:8:80:11 | argv | semmle.label | argv | | ifs.c:80:8:80:11 | argv | semmle.label | argv | -| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | -| ifs.c:81:9:81:10 | i2 indirection | semmle.label | i2 indirection | +| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:86:8:86:11 | argv | semmle.label | argv | | ifs.c:86:8:86:11 | argv | semmle.label | argv | -| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | -| ifs.c:87:9:87:10 | i3 indirection | semmle.label | i3 indirection | +| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:92:8:92:11 | argv | semmle.label | argv | | ifs.c:92:8:92:11 | argv | semmle.label | argv | -| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | -| ifs.c:93:9:93:10 | i4 indirection | semmle.label | i4 indirection | +| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:98:8:98:11 | argv | semmle.label | argv | | ifs.c:98:8:98:11 | argv | semmle.label | argv | -| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | -| ifs.c:99:9:99:10 | i5 indirection | semmle.label | i5 indirection | +| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:105:8:105:11 | argv | semmle.label | argv | | ifs.c:105:8:105:11 | argv | semmle.label | argv | -| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | -| ifs.c:106:9:106:10 | i6 indirection | semmle.label | i6 indirection | +| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:111:8:111:11 | argv | semmle.label | argv | | ifs.c:111:8:111:11 | argv | semmle.label | argv | -| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | -| ifs.c:112:9:112:10 | i7 indirection | semmle.label | i7 indirection | +| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:117:8:117:11 | argv | semmle.label | argv | | ifs.c:117:8:117:11 | argv | semmle.label | argv | -| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | -| ifs.c:118:9:118:10 | i8 indirection | semmle.label | i8 indirection | +| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:123:8:123:11 | argv | semmle.label | argv | | ifs.c:123:8:123:11 | argv | semmle.label | argv | -| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:124:9:124:10 | i9 | semmle.label | i9 | | ifs.c:124:9:124:10 | i9 | semmle.label | i9 | -| ifs.c:124:9:124:10 | i9 indirection | semmle.label | i9 indirection | +| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | #select | ifs.c:62:9:62:10 | c7 | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | ifs.c:61:8:61:11 | argv | argv | | ifs.c:69:9:69:10 | c8 | ifs.c:68:8:68:11 | argv | ifs.c:69:9:69:10 | c8 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | ifs.c:68:8:68:11 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected index 3834d769463..2c14a5968ad 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticUncontrolled.expected @@ -1,22 +1,22 @@ edges -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | -| examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | +| examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | @@ -24,12 +24,12 @@ edges | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | nodes -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:22:26:22:33 | (unsigned int)... | semmle.label | (unsigned int)... | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | +| examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | | examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | | examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | | examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | @@ -37,12 +37,12 @@ nodes | examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | | examples.cpp:22:26:22:33 | call to rand | semmle.label | call to rand | | examples.cpp:25:31:25:34 | data | semmle.label | data | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | -| examples.cpp:35:26:35:33 | (unsigned int)... | semmle.label | (unsigned int)... | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | +| examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | | examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | | examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | | examples.cpp:35:26:35:33 | call to rand | semmle.label | call to rand | @@ -52,24 +52,24 @@ nodes | examples.cpp:38:9:38:12 | data | semmle.label | data | subpaths #select -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | (unsigned int)... | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | | examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | -| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | (unsigned int)... | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:25:31:25:34 | data | examples.cpp:22:26:22:33 | call to rand | examples.cpp:25:31:25:34 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:22:26:22:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | +| examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | | examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | | examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | | examples.cpp:38:9:38:12 | data | examples.cpp:35:26:35:33 | call to rand | examples.cpp:38:9:38:12 | data | This arithmetic expression depends on an $@, potentially causing an underflow. | examples.cpp:35:26:35:33 | call to rand | uncontrolled value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected index 011f8f73819..0363a0909a5 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/ArithmeticUncontrolled/ArithmeticUncontrolled.expected @@ -10,23 +10,21 @@ edges | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | -| test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | -| test.cpp:6:5:6:12 | ReturnValue | test.cpp:24:11:24:18 | call to get_rand | -| test.cpp:8:9:8:12 | call to rand | test.cpp:6:5:6:12 | ReturnValue | -| test.cpp:13:2:13:6 | * ... [post update] | test.cpp:30:13:30:14 | & ... [post update] | -| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:6 | * ... [post update] | -| test.cpp:13:10:13:13 | call to rand | test.cpp:30:13:30:14 | & ... [post update] | -| test.cpp:18:2:18:5 | (reference dereference) [post update] | test.cpp:36:13:36:13 | r [post update] | -| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:5 | (reference dereference) [post update] | -| test.cpp:18:9:18:12 | call to rand | test.cpp:36:13:36:13 | r [post update] | +| test.c:155:22:155:27 | call to rand | test.c:157:9:157:9 | r | +| test.cpp:6:5:6:12 | get_rand indirection | test.cpp:24:11:24:18 | call to get_rand | +| test.cpp:8:9:8:12 | call to rand | test.cpp:6:5:6:12 | get_rand indirection | +| test.cpp:11:21:11:24 | dest | test.cpp:30:13:30:14 | get_rand2 output argument | +| test.cpp:13:10:13:13 | call to rand | test.cpp:11:21:11:24 | dest | +| test.cpp:16:21:16:24 | dest | test.cpp:36:13:36:13 | get_rand3 output argument | +| test.cpp:18:9:18:12 | call to rand | test.cpp:16:21:16:24 | dest | | test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r | -| test.cpp:30:13:30:14 | & ... [post update] | test.cpp:31:7:31:7 | r | -| test.cpp:36:13:36:13 | r [post update] | test.cpp:37:7:37:7 | r | +| test.cpp:30:13:30:14 | get_rand2 output argument | test.cpp:31:7:31:7 | r | +| test.cpp:36:13:36:13 | get_rand3 output argument | test.cpp:37:7:37:7 | r | | test.cpp:86:10:86:13 | call to rand | test.cpp:90:10:90:10 | x | | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | -| test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | +| test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | y | | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | @@ -55,19 +53,19 @@ nodes | test.c:137:13:137:16 | call to rand | semmle.label | call to rand | | test.c:139:10:139:10 | r | semmle.label | r | | test.c:155:22:155:25 | call to rand | semmle.label | call to rand | -| test.c:155:22:155:27 | (unsigned int)... | semmle.label | (unsigned int)... | +| test.c:155:22:155:27 | call to rand | semmle.label | call to rand | | test.c:157:9:157:9 | r | semmle.label | r | -| test.cpp:6:5:6:12 | ReturnValue | semmle.label | ReturnValue | +| test.cpp:6:5:6:12 | get_rand indirection | semmle.label | get_rand indirection | | test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand | -| test.cpp:13:2:13:6 | * ... [post update] | semmle.label | * ... [post update] | +| test.cpp:11:21:11:24 | dest | semmle.label | dest | | test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand | -| test.cpp:18:2:18:5 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] | +| test.cpp:16:21:16:24 | dest | semmle.label | dest | | test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand | | test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand | | test.cpp:25:7:25:7 | r | semmle.label | r | -| test.cpp:30:13:30:14 | & ... [post update] | semmle.label | & ... [post update] | +| test.cpp:30:13:30:14 | get_rand2 output argument | semmle.label | get_rand2 output argument | | test.cpp:31:7:31:7 | r | semmle.label | r | -| test.cpp:36:13:36:13 | r [post update] | semmle.label | r [post update] | +| test.cpp:36:13:36:13 | get_rand3 output argument | semmle.label | get_rand3 output argument | | test.cpp:37:7:37:7 | r | semmle.label | r | | test.cpp:86:10:86:13 | call to rand | semmle.label | call to rand | | test.cpp:90:10:90:10 | x | semmle.label | x | @@ -78,7 +76,7 @@ nodes | test.cpp:151:10:151:13 | call to rand | semmle.label | call to rand | | test.cpp:154:10:154:10 | b | semmle.label | b | | test.cpp:169:11:169:14 | call to rand | semmle.label | call to rand | -| test.cpp:171:11:171:16 | (int)... | semmle.label | (int)... | +| test.cpp:171:11:171:16 | y | semmle.label | y | | test.cpp:171:16:171:16 | y | semmle.label | y | | test.cpp:189:10:189:13 | call to rand | semmle.label | call to rand | | test.cpp:190:10:190:13 | call to rand | semmle.label | call to rand | @@ -103,7 +101,7 @@ subpaths | test.c:133:5:133:5 | r | test.c:131:13:131:16 | call to rand | test.c:133:5:133:5 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:131:13:131:16 | call to rand | uncontrolled value | | test.c:139:10:139:10 | r | test.c:137:13:137:16 | call to rand | test.c:139:10:139:10 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.c:137:13:137:16 | call to rand | uncontrolled value | | test.c:157:9:157:9 | r | test.c:155:22:155:25 | call to rand | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | -| test.c:157:9:157:9 | r | test.c:155:22:155:27 | (unsigned int)... | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | +| test.c:157:9:157:9 | r | test.c:155:22:155:27 | call to rand | test.c:157:9:157:9 | r | This arithmetic expression depends on an $@, potentially causing an underflow. | test.c:155:22:155:25 | call to rand | uncontrolled value | | test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | uncontrolled value | | test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | uncontrolled value | | test.cpp:37:7:37:7 | r | test.cpp:18:9:18:12 | call to rand | test.cpp:37:7:37:7 | r | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:18:9:18:12 | call to rand | uncontrolled value | @@ -111,7 +109,7 @@ subpaths | test.cpp:102:10:102:10 | x | test.cpp:98:10:98:13 | call to rand | test.cpp:102:10:102:10 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:98:10:98:13 | call to rand | uncontrolled value | | test.cpp:146:9:146:9 | y | test.cpp:137:10:137:13 | call to rand | test.cpp:146:9:146:9 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:137:10:137:13 | call to rand | uncontrolled value | | test.cpp:154:10:154:10 | b | test.cpp:151:10:151:13 | call to rand | test.cpp:154:10:154:10 | b | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:151:10:151:13 | call to rand | uncontrolled value | -| test.cpp:171:11:171:16 | (int)... | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | (int)... | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | +| test.cpp:171:11:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:11:171:16 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | | test.cpp:171:16:171:16 | y | test.cpp:169:11:169:14 | call to rand | test.cpp:171:16:171:16 | y | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:169:11:169:14 | call to rand | uncontrolled value | | test.cpp:196:7:196:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:196:7:196:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | | test.cpp:198:7:198:7 | x | test.cpp:189:10:189:13 | call to rand | test.cpp:198:7:198:7 | x | This arithmetic expression depends on an $@, potentially causing an overflow. | test.cpp:189:10:189:13 | call to rand | uncontrolled value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected index c28b2221eab..0646c054fbc 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/TaintedAllocationSize/TaintedAllocationSize.expected @@ -5,28 +5,51 @@ edges | test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size | | test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size | | test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | +| test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | +| test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | +| test.cpp:133:19:133:32 | call to getenv indirection | test.cpp:135:10:135:27 | ... * ... | | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | -| test.cpp:209:8:209:23 | ReturnValue | test.cpp:241:9:241:24 | call to get_tainted_size | -| test.cpp:211:14:211:19 | call to getenv | test.cpp:209:8:209:23 | ReturnValue | +| test.cpp:148:20:148:33 | call to getenv indirection | test.cpp:152:11:152:28 | ... * ... | +| test.cpp:209:8:209:23 | get_tainted_size indirection | test.cpp:241:9:241:24 | call to get_tainted_size | +| test.cpp:211:14:211:19 | call to getenv | test.cpp:209:8:209:23 | get_tainted_size indirection | +| test.cpp:211:14:211:27 | call to getenv indirection | test.cpp:209:8:209:23 | get_tainted_size indirection | | test.cpp:230:21:230:21 | s | test.cpp:231:21:231:21 | s | | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | | test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size | | test.cpp:237:24:237:29 | call to getenv | test.cpp:247:10:247:19 | local_size | +| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:239:9:239:18 | local_size | +| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:245:11:245:20 | local_size | +| test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:247:10:247:19 | local_size | | test.cpp:247:10:247:19 | local_size | test.cpp:230:21:230:21 | s | -| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:289:17:289:20 | size [post update] | -| test.cpp:251:2:251:9 | (reference dereference) [post update] | test.cpp:305:18:305:21 | size [post update] | -| test.cpp:251:18:251:23 | call to getenv | test.cpp:251:2:251:9 | (reference dereference) [post update] | -| test.cpp:251:18:251:23 | call to getenv | test.cpp:289:17:289:20 | size [post update] | -| test.cpp:251:18:251:23 | call to getenv | test.cpp:305:18:305:21 | size [post update] | +| test.cpp:250:20:250:27 | out_size | test.cpp:289:17:289:20 | get_size output argument | +| test.cpp:250:20:250:27 | out_size | test.cpp:305:18:305:21 | get_size output argument | +| test.cpp:251:18:251:23 | call to getenv | test.cpp:250:20:250:27 | out_size | +| test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:250:20:250:27 | out_size | | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | -| test.cpp:289:17:289:20 | size [post update] | test.cpp:291:11:291:28 | ... * ... | -| test.cpp:305:18:305:21 | size [post update] | test.cpp:308:10:308:27 | ... * ... | +| test.cpp:259:20:259:33 | call to getenv indirection | test.cpp:263:11:263:29 | ... * ... | +| test.cpp:289:17:289:20 | get_size output argument | test.cpp:291:11:291:28 | ... * ... | +| test.cpp:305:18:305:21 | get_size output argument | test.cpp:308:10:308:27 | ... * ... | | test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size | | test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size | +| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size | +| test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size | nodes | test.cpp:39:27:39:30 | argv | semmle.label | argv | +| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection | +| test.cpp:39:27:39:30 | argv indirection | semmle.label | argv indirection | | test.cpp:43:38:43:44 | tainted | semmle.label | tainted | | test.cpp:44:38:44:63 | ... * ... | semmle.label | ... * ... | | test.cpp:46:38:46:63 | ... + ... | semmle.label | ... + ... | @@ -34,48 +57,80 @@ nodes | test.cpp:50:26:50:29 | size | semmle.label | size | | test.cpp:53:35:53:60 | ... * ... | semmle.label | ... * ... | | test.cpp:124:18:124:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:124:18:124:31 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:128:24:128:41 | ... * ... | semmle.label | ... * ... | | test.cpp:133:19:133:24 | call to getenv | semmle.label | call to getenv | +| test.cpp:133:19:133:32 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:135:10:135:27 | ... * ... | semmle.label | ... * ... | | test.cpp:148:20:148:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:148:20:148:33 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:152:11:152:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:209:8:209:23 | ReturnValue | semmle.label | ReturnValue | +| test.cpp:209:8:209:23 | get_tainted_size indirection | semmle.label | get_tainted_size indirection | | test.cpp:211:14:211:19 | call to getenv | semmle.label | call to getenv | +| test.cpp:211:14:211:27 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:230:21:230:21 | s | semmle.label | s | | test.cpp:231:21:231:21 | s | semmle.label | s | | test.cpp:237:24:237:29 | call to getenv | semmle.label | call to getenv | +| test.cpp:237:24:237:37 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:239:9:239:18 | local_size | semmle.label | local_size | | test.cpp:241:9:241:24 | call to get_tainted_size | semmle.label | call to get_tainted_size | | test.cpp:245:11:245:20 | local_size | semmle.label | local_size | | test.cpp:247:10:247:19 | local_size | semmle.label | local_size | -| test.cpp:251:2:251:9 | (reference dereference) [post update] | semmle.label | (reference dereference) [post update] | +| test.cpp:250:20:250:27 | out_size | semmle.label | out_size | | test.cpp:251:18:251:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:251:18:251:31 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:259:20:259:25 | call to getenv | semmle.label | call to getenv | +| test.cpp:259:20:259:33 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:263:11:263:29 | ... * ... | semmle.label | ... * ... | -| test.cpp:289:17:289:20 | size [post update] | semmle.label | size [post update] | +| test.cpp:289:17:289:20 | get_size output argument | semmle.label | get_size output argument | | test.cpp:291:11:291:28 | ... * ... | semmle.label | ... * ... | -| test.cpp:305:18:305:21 | size [post update] | semmle.label | size [post update] | +| test.cpp:305:18:305:21 | get_size output argument | semmle.label | get_size output argument | | test.cpp:308:10:308:27 | ... * ... | semmle.label | ... * ... | | test.cpp:353:18:353:23 | call to getenv | semmle.label | call to getenv | +| test.cpp:353:18:353:31 | call to getenv indirection | semmle.label | call to getenv indirection | | test.cpp:355:35:355:38 | size | semmle.label | size | | test.cpp:356:35:356:38 | size | semmle.label | size | subpaths #select | test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:43:31:43:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:43:38:43:44 | tainted | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:44:31:44:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:44:38:44:63 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:46:31:46:36 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:46:38:46:63 | ... + ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:49:25:49:30 | call to malloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:49:32:49:35 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:50:17:50:30 | new[] | test.cpp:39:27:39:30 | argv indirection | test.cpp:50:26:50:29 | size | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv | user input (a command-line argument) | +| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | +| test.cpp:53:21:53:27 | call to realloc | test.cpp:39:27:39:30 | argv indirection | test.cpp:53:35:53:60 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:39:27:39:30 | argv indirection | user input (a command-line argument) | | test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:23 | call to getenv | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:23 | call to getenv | user input (an environment variable) | +| test.cpp:128:17:128:22 | call to malloc | test.cpp:124:18:124:31 | call to getenv indirection | test.cpp:128:24:128:41 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:124:18:124:31 | call to getenv indirection | user input (an environment variable) | | test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:24 | call to getenv | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:133:19:133:24 | call to getenv | user input (an environment variable) | +| test.cpp:135:3:135:8 | call to malloc | test.cpp:133:19:133:32 | call to getenv indirection | test.cpp:135:10:135:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:133:19:133:32 | call to getenv indirection | user input (an environment variable) | | test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:25 | call to getenv | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:148:20:148:25 | call to getenv | user input (an environment variable) | +| test.cpp:152:4:152:9 | call to malloc | test.cpp:148:20:148:33 | call to getenv indirection | test.cpp:152:11:152:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:148:20:148:33 | call to getenv indirection | user input (an environment variable) | | test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) | +| test.cpp:231:14:231:19 | call to malloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:231:21:231:21 | s | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) | | test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) | +| test.cpp:239:2:239:7 | call to malloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:239:9:239:18 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) | | test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:19 | call to getenv | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:19 | call to getenv | user input (an environment variable) | +| test.cpp:241:2:241:7 | call to malloc | test.cpp:211:14:211:27 | call to getenv indirection | test.cpp:241:9:241:24 | call to get_tainted_size | This allocation size is derived from $@ and might overflow. | test.cpp:211:14:211:27 | call to getenv indirection | user input (an environment variable) | | test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:29 | call to getenv | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:29 | call to getenv | user input (an environment variable) | +| test.cpp:245:2:245:9 | call to my_alloc | test.cpp:237:24:237:37 | call to getenv indirection | test.cpp:245:11:245:20 | local_size | This allocation size is derived from $@ and might overflow. | test.cpp:237:24:237:37 | call to getenv indirection | user input (an environment variable) | | test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:25 | call to getenv | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:25 | call to getenv | user input (an environment variable) | +| test.cpp:263:4:263:9 | call to malloc | test.cpp:259:20:259:33 | call to getenv indirection | test.cpp:263:11:263:29 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:259:20:259:33 | call to getenv indirection | user input (an environment variable) | | test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) | +| test.cpp:291:4:291:9 | call to malloc | test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:291:11:291:28 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv indirection | user input (an environment variable) | | test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:23 | call to getenv | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:23 | call to getenv | user input (an environment variable) | +| test.cpp:308:3:308:8 | call to malloc | test.cpp:251:18:251:31 | call to getenv indirection | test.cpp:308:10:308:27 | ... * ... | This allocation size is derived from $@ and might overflow. | test.cpp:251:18:251:31 | call to getenv indirection | user input (an environment variable) | | test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:23 | call to getenv | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) | +| test.cpp:355:25:355:33 | call to MyMalloc1 | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:355:35:355:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv indirection | user input (an environment variable) | | test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:23 | call to getenv | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:23 | call to getenv | user input (an environment variable) | +| test.cpp:356:25:356:33 | call to MyMalloc2 | test.cpp:353:18:353:31 | call to getenv indirection | test.cpp:356:35:356:38 | size | This allocation size is derived from $@ and might overflow. | test.cpp:353:18:353:31 | call to getenv indirection | user input (an environment variable) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected index be5a4ab812f..beda8117dab 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected @@ -4,11 +4,12 @@ edges | test2.cpp:25:22:25:23 | & ... | test2.cpp:27:13:27:13 | v | | test2.cpp:25:22:25:23 | fscanf output argument | test2.cpp:27:13:27:13 | v | | test2.cpp:27:13:27:13 | v | test2.cpp:12:21:12:21 | v | -| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:17:6:17:18 | call to getTaintedInt | -| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:17:6:17:18 | call to getTaintedInt | -| test5.cpp:5:5:5:17 | ReturnValue | test5.cpp:18:6:18:18 | call to getTaintedInt | -| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | ReturnValue | -| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:5:5:5:17 | ReturnValue | +| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt | +| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:17:6:17:18 | call to getTaintedInt | +| test5.cpp:5:5:5:17 | getTaintedInt indirection | test5.cpp:18:6:18:18 | call to getTaintedInt | +| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection | +| test5.cpp:9:7:9:9 | buf | test5.cpp:5:5:5:17 | getTaintedInt indirection | +| test5.cpp:9:7:9:9 | gets output argument | test5.cpp:5:5:5:17 | getTaintedInt indirection | | test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y | | test5.cpp:18:6:18:18 | call to getTaintedInt | test5.cpp:19:6:19:6 | y | | test.c:11:29:11:32 | argv | test.c:14:15:14:28 | maxConnections | @@ -31,7 +32,8 @@ nodes | test2.cpp:25:22:25:23 | & ... | semmle.label | & ... | | test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument | | test2.cpp:27:13:27:13 | v | semmle.label | v | -| test5.cpp:5:5:5:17 | ReturnValue | semmle.label | ReturnValue | +| test5.cpp:5:5:5:17 | getTaintedInt indirection | semmle.label | getTaintedInt indirection | +| test5.cpp:9:7:9:9 | buf | semmle.label | buf | | test5.cpp:9:7:9:9 | buf | semmle.label | buf | | test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument | | test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected index fdc76862fe9..11db5c7acaa 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected @@ -1,68 +1,50 @@ edges | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | -| test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address indirection | -| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | -| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address | -| test.cpp:16:25:16:42 | (const char *)... | test.cpp:20:14:20:20 | address indirection | +| test.cpp:16:25:16:42 | call to getenv | test.cpp:20:14:20:20 | address | +| test.cpp:16:25:16:42 | call to getenv | test.cpp:20:14:20:20 | address | | test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | | test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | -| test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address indirection | -| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | -| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address | -| test.cpp:27:25:27:42 | (const char *)... | test.cpp:31:14:31:20 | address indirection | +| test.cpp:27:25:27:42 | call to getenv | test.cpp:31:14:31:20 | address | +| test.cpp:27:25:27:42 | call to getenv | test.cpp:31:14:31:20 | address | | test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | | test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address | -| test.cpp:38:25:38:30 | call to getenv | test.cpp:42:14:42:20 | address indirection | -| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | -| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address | -| test.cpp:38:25:38:42 | (const char *)... | test.cpp:42:14:42:20 | address indirection | +| test.cpp:38:25:38:42 | call to getenv | test.cpp:42:14:42:20 | address | +| test.cpp:38:25:38:42 | call to getenv | test.cpp:42:14:42:20 | address | | test.cpp:49:25:49:30 | call to getenv | test.cpp:52:14:52:20 | address | | test.cpp:49:25:49:30 | call to getenv | test.cpp:52:14:52:20 | address | -| test.cpp:49:25:49:30 | call to getenv | test.cpp:52:14:52:20 | address indirection | | test.cpp:49:25:49:30 | call to getenv | test.cpp:56:14:56:20 | address | | test.cpp:49:25:49:30 | call to getenv | test.cpp:56:14:56:20 | address | -| test.cpp:49:25:49:30 | call to getenv | test.cpp:56:14:56:20 | address indirection | | test.cpp:49:25:49:30 | call to getenv | test.cpp:60:14:60:20 | address | | test.cpp:49:25:49:30 | call to getenv | test.cpp:60:14:60:20 | address | -| test.cpp:49:25:49:30 | call to getenv | test.cpp:60:14:60:20 | address indirection | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:52:14:52:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:52:14:52:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:52:14:52:20 | address indirection | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:56:14:56:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:56:14:56:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:56:14:56:20 | address indirection | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:60:14:60:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:60:14:60:20 | address | -| test.cpp:49:25:49:42 | (const char *)... | test.cpp:60:14:60:20 | address indirection | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:52:14:52:20 | address | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:52:14:52:20 | address | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:56:14:56:20 | address | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:56:14:56:20 | address | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:60:14:60:20 | address | +| test.cpp:49:25:49:42 | call to getenv | test.cpp:60:14:60:20 | address | subpaths nodes | test.cpp:16:25:16:30 | call to getenv | semmle.label | call to getenv | -| test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:16:25:16:42 | call to getenv | semmle.label | call to getenv | | test.cpp:20:14:20:20 | address | semmle.label | address | | test.cpp:20:14:20:20 | address | semmle.label | address | -| test.cpp:20:14:20:20 | address indirection | semmle.label | address indirection | | test.cpp:27:25:27:30 | call to getenv | semmle.label | call to getenv | -| test.cpp:27:25:27:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:27:25:27:42 | call to getenv | semmle.label | call to getenv | | test.cpp:31:14:31:20 | address | semmle.label | address | | test.cpp:31:14:31:20 | address | semmle.label | address | -| test.cpp:31:14:31:20 | address indirection | semmle.label | address indirection | | test.cpp:38:25:38:30 | call to getenv | semmle.label | call to getenv | -| test.cpp:38:25:38:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:38:25:38:42 | call to getenv | semmle.label | call to getenv | | test.cpp:42:14:42:20 | address | semmle.label | address | | test.cpp:42:14:42:20 | address | semmle.label | address | -| test.cpp:42:14:42:20 | address indirection | semmle.label | address indirection | | test.cpp:49:25:49:30 | call to getenv | semmle.label | call to getenv | -| test.cpp:49:25:49:42 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:49:25:49:42 | call to getenv | semmle.label | call to getenv | | test.cpp:52:14:52:20 | address | semmle.label | address | | test.cpp:52:14:52:20 | address | semmle.label | address | -| test.cpp:52:14:52:20 | address indirection | semmle.label | address indirection | | test.cpp:56:14:56:20 | address | semmle.label | address | | test.cpp:56:14:56:20 | address | semmle.label | address | -| test.cpp:56:14:56:20 | address indirection | semmle.label | address indirection | | test.cpp:60:14:60:20 | address | semmle.label | address | | test.cpp:60:14:60:20 | address | semmle.label | address | -| test.cpp:60:14:60:20 | address indirection | semmle.label | address indirection | #select | test.cpp:20:7:20:12 | call to strcmp | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | | test.cpp:31:7:31:12 | call to strcmp | test.cpp:27:25:27:30 | call to getenv | test.cpp:31:14:31:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:27:25:27:30 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected index 8cece3f45f5..f4d503b340a 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextBufferWrite.expected @@ -1,10 +1,18 @@ edges -| test.cpp:53:27:53:30 | argv | test.cpp:58:25:58:29 | input | +| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | +| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | +| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | +| test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | nodes -| test2.cpp:110:3:110:6 | call to gets | semmle.label | call to gets | -| test.cpp:53:27:53:30 | argv | semmle.label | argv | -| test.cpp:58:25:58:29 | input | semmle.label | input | +| test2.cpp:110:3:110:6 | call to gets indirection | semmle.label | call to gets indirection | +| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection | +| test.cpp:53:27:53:30 | argv indirection | semmle.label | argv indirection | +| test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection | +| test.cpp:58:25:58:29 | input indirection | semmle.label | input indirection | subpaths #select -| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets | user input (string read by gets) | -| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv | user input (a command-line argument) | +| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets indirection | test2.cpp:110:3:110:6 | call to gets indirection | This write into buffer 'password' may contain unencrypted data from $@. | test2.cpp:110:3:110:6 | call to gets indirection | user input (string read by gets) | +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | +| test.cpp:58:3:58:9 | call to sprintf | test.cpp:53:27:53:30 | argv indirection | test.cpp:58:25:58:29 | input indirection | This write into buffer 'passwd' may contain unencrypted data from $@. | test.cpp:53:27:53:30 | argv indirection | user input (a command-line argument) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected index d248e9928da..99af2e52751 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextFileWrite.expected @@ -1,8 +1,22 @@ edges | test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | -| test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf | -| test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf | -| test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | buffer | +| test2.cpp:72:15:72:24 | password | test2.cpp:73:30:73:32 | buf indirection | +| test2.cpp:72:15:72:24 | password | test2.cpp:76:30:76:32 | buf indirection | +| test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf indirection | +| test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf indirection | +| test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | buffer indirection | +| test.cpp:45:9:45:19 | thePassword | test.cpp:45:9:45:19 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:73:43:73:53 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:73:63:73:73 | thePassword | test.cpp:73:43:73:53 | thePassword | +| test.cpp:73:63:73:73 | thePassword | test.cpp:73:43:73:53 | thePassword | nodes | test2.cpp:43:36:43:43 | password | semmle.label | password | | test2.cpp:44:37:44:45 | thepasswd | semmle.label | thepasswd | @@ -13,16 +27,24 @@ nodes | test2.cpp:57:39:57:49 | call to getPassword | semmle.label | call to getPassword | | test2.cpp:62:18:62:25 | password | semmle.label | password | | test2.cpp:65:31:65:34 | cpy1 | semmle.label | cpy1 | +| test2.cpp:72:15:72:24 | password | semmle.label | password | | test2.cpp:72:17:72:24 | password | semmle.label | password | -| test2.cpp:73:30:73:32 | buf | semmle.label | buf | -| test2.cpp:76:30:76:32 | buf | semmle.label | buf | -| test2.cpp:86:36:86:43 | password | semmle.label | password | -| test2.cpp:91:50:91:63 | passwd_config2 | semmle.label | passwd_config2 | +| test2.cpp:73:30:73:32 | buf indirection | semmle.label | buf indirection | +| test2.cpp:76:30:76:32 | buf indirection | semmle.label | buf indirection | | test2.cpp:98:45:98:52 | password | semmle.label | password | -| test2.cpp:99:27:99:32 | buffer | semmle.label | buffer | +| test2.cpp:99:27:99:32 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:45:9:45:19 | thePassword | semmle.label | thePassword | +| test.cpp:45:9:45:19 | thePassword | semmle.label | thePassword | | test.cpp:45:9:45:19 | thePassword | semmle.label | thePassword | | test.cpp:70:38:70:48 | thePassword | semmle.label | thePassword | +| test.cpp:70:38:70:48 | thePassword | semmle.label | thePassword | +| test.cpp:70:38:70:48 | thePassword | semmle.label | thePassword | +| test.cpp:70:38:70:48 | thePassword | semmle.label | thePassword | | test.cpp:73:43:73:53 | thePassword | semmle.label | thePassword | +| test.cpp:73:43:73:53 | thePassword | semmle.label | thePassword | +| test.cpp:73:43:73:53 | thePassword | semmle.label | thePassword | +| test.cpp:73:63:73:73 | thePassword | semmle.label | thePassword | +| test.cpp:73:63:73:73 | thePassword | semmle.label | thePassword | subpaths #select | test2.cpp:43:2:43:8 | call to fprintf | test2.cpp:43:36:43:43 | password | test2.cpp:43:36:43:43 | password | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:43:36:43:43 | password | this source. | @@ -33,9 +55,23 @@ subpaths | test2.cpp:55:2:55:8 | call to fprintf | test2.cpp:55:40:55:51 | widepassword | test2.cpp:55:40:55:51 | widepassword | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:55:40:55:51 | widepassword | this source. | | test2.cpp:57:2:57:8 | call to fprintf | test2.cpp:57:39:57:49 | call to getPassword | test2.cpp:57:39:57:49 | call to getPassword | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:57:39:57:49 | call to getPassword | this source. | | test2.cpp:65:3:65:9 | call to fprintf | test2.cpp:62:18:62:25 | password | test2.cpp:65:31:65:34 | cpy1 | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:62:18:62:25 | password | this source. | -| test2.cpp:73:3:73:9 | call to fprintf | test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | -| test2.cpp:76:3:76:9 | call to fprintf | test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | -| test2.cpp:99:3:99:9 | call to fprintf | test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | buffer | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:98:45:98:52 | password | this source. | +| test2.cpp:73:3:73:9 | call to fprintf | test2.cpp:72:15:72:24 | password | test2.cpp:73:30:73:32 | buf indirection | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | +| test2.cpp:73:3:73:9 | call to fprintf | test2.cpp:72:17:72:24 | password | test2.cpp:73:30:73:32 | buf indirection | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | +| test2.cpp:76:3:76:9 | call to fprintf | test2.cpp:72:15:72:24 | password | test2.cpp:76:30:76:32 | buf indirection | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | +| test2.cpp:76:3:76:9 | call to fprintf | test2.cpp:72:17:72:24 | password | test2.cpp:76:30:76:32 | buf indirection | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:72:17:72:24 | password | this source. | +| test2.cpp:99:3:99:9 | call to fprintf | test2.cpp:98:45:98:52 | password | test2.cpp:99:27:99:32 | buffer indirection | This write into file 'log' may contain unencrypted data from $@. | test2.cpp:98:45:98:52 | password | this source. | +| test.cpp:45:3:45:7 | call to fputs | test.cpp:45:9:45:19 | thePassword | test.cpp:45:9:45:19 | thePassword | This write into file 'file' may contain unencrypted data from $@. | test.cpp:45:9:45:19 | thePassword | this source. | +| test.cpp:45:3:45:7 | call to fputs | test.cpp:45:9:45:19 | thePassword | test.cpp:45:9:45:19 | thePassword | This write into file 'file' may contain unencrypted data from $@. | test.cpp:45:9:45:19 | thePassword | this source. | | test.cpp:45:3:45:7 | call to fputs | test.cpp:45:9:45:19 | thePassword | test.cpp:45:9:45:19 | thePassword | This write into file 'file' may contain unencrypted data from $@. | test.cpp:45:9:45:19 | thePassword | this source. | | test.cpp:70:35:70:35 | call to operator<< | test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:70:35:70:35 | call to operator<< | test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:70:35:70:35 | call to operator<< | test.cpp:70:38:70:48 | thePassword | test.cpp:70:38:70:48 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:70:38:70:48 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:70:38:70:48 | thePassword | this source. | | test.cpp:73:37:73:41 | call to write | test.cpp:73:43:73:53 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:73:43:73:53 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:73:43:73:53 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:73:43:73:53 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:73:43:73:53 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:73:43:73:53 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:73:63:73:73 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:73:63:73:73 | thePassword | this source. | +| test.cpp:73:37:73:41 | call to write | test.cpp:73:63:73:73 | thePassword | test.cpp:73:43:73:53 | thePassword | This write into file 'mystream' may contain unencrypted data from $@. | test.cpp:73:63:73:73 | thePassword | this source. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected index 88c78dabb6a..0968078a67f 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected @@ -1,304 +1,163 @@ edges -| test2.cpp:63:24:63:31 | password | test2.cpp:63:16:63:20 | call to crypt | -| test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 | -| test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 | -| test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password | -| test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password | -| test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr | -| test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr | -| test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password | +| test3.cpp:74:21:74:29 | password1 | test3.cpp:76:15:76:17 | ptr | +| test3.cpp:81:15:81:22 | password | test3.cpp:83:15:83:17 | ptr | | test3.cpp:112:20:112:25 | buffer | test3.cpp:114:14:114:19 | buffer | -| test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer | -| test3.cpp:126:9:126:23 | global_password | test3.cpp:144:16:144:29 | call to get_global_str | -| test3.cpp:129:39:129:47 | password1 | test3.cpp:138:24:138:32 | password1 | -| test3.cpp:132:8:132:15 | password | test3.cpp:134:11:134:18 | password | +| test3.cpp:117:28:117:33 | buffer | test3.cpp:117:13:117:14 | id indirection | +| test3.cpp:124:7:124:20 | get_global_str indirection | test3.cpp:144:16:144:29 | call to get_global_str | +| test3.cpp:126:9:126:23 | global_password | test3.cpp:124:7:124:20 | get_global_str indirection | | test3.cpp:134:11:134:18 | password | test3.cpp:112:20:112:25 | buffer | | test3.cpp:138:21:138:22 | call to id | test3.cpp:140:15:140:17 | ptr | | test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer | | test3.cpp:138:24:138:32 | password1 | test3.cpp:138:21:138:22 | call to id | | test3.cpp:144:16:144:29 | call to get_global_str | test3.cpp:146:15:146:18 | data | -| test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | -| test3.cpp:171:8:171:15 | password | test3.cpp:173:15:173:22 | password | -| test3.cpp:171:8:171:15 | password | test3.cpp:175:3:175:17 | call to decrypt_inplace | -| test3.cpp:171:8:171:15 | password | test3.cpp:175:19:175:26 | password | -| test3.cpp:179:8:179:15 | password | test3.cpp:181:15:181:22 | password | -| test3.cpp:179:8:179:15 | password | test3.cpp:184:3:184:17 | call to decrypt_inplace | -| test3.cpp:179:8:179:15 | password | test3.cpp:184:19:184:26 | password | -| test3.cpp:188:8:188:15 | password | test3.cpp:191:15:191:22 | password | -| test3.cpp:188:8:188:15 | password | test3.cpp:193:18:193:28 | call to rtn_decrypt | -| test3.cpp:188:8:188:15 | password | test3.cpp:193:30:193:37 | password | -| test3.cpp:197:8:197:15 | password | test3.cpp:199:3:199:17 | call to encrypt_inplace | -| test3.cpp:197:8:197:15 | password | test3.cpp:199:19:199:26 | password | -| test3.cpp:197:8:197:15 | password | test3.cpp:201:15:201:22 | password | -| test3.cpp:205:8:205:15 | password | test3.cpp:207:3:207:17 | call to encrypt_inplace | -| test3.cpp:205:8:205:15 | password | test3.cpp:207:19:207:26 | password | -| test3.cpp:205:8:205:15 | password | test3.cpp:210:15:210:22 | password | -| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt | -| test3.cpp:214:8:214:15 | password | test3.cpp:217:18:217:28 | call to rtn_encrypt | -| test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password | -| test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr | -| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr | -| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | -| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | -| test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 | -| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer | -| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 | -| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer | -| test3.cpp:252:24:252:32 | password2 | test3.cpp:256:32:256:40 | password2 | -| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer | -| test3.cpp:260:8:260:16 | password1 | test3.cpp:262:21:262:29 | password1 | -| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:3:262:19 | call to encrypt_to_buffer | -| test3.cpp:260:24:260:32 | password2 | test3.cpp:262:32:262:40 | password2 | -| test3.cpp:260:24:260:32 | password2 | test3.cpp:264:15:264:23 | password2 | -| test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | -| test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data | +| test3.cpp:157:19:157:26 | password | test3.cpp:159:15:159:20 | buffer indirection | +| test3.cpp:270:16:270:23 | password | test3.cpp:272:15:272:18 | data indirection | | test3.cpp:278:20:278:23 | data | test3.cpp:280:14:280:17 | data | -| test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data | | test3.cpp:283:20:283:23 | data | test3.cpp:285:14:285:17 | data | | test3.cpp:288:20:288:23 | data | test3.cpp:290:14:290:17 | data | -| test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data | | test3.cpp:293:20:293:23 | data | test3.cpp:295:14:295:17 | data | | test3.cpp:298:20:298:23 | data | test3.cpp:300:14:300:17 | data | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:3:312:17 | call to encrypt_inplace | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:312:19:312:27 | password1 | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:313:11:313:19 | password1 | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:314:11:314:19 | password1 | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:316:11:316:19 | password1 | -| test3.cpp:308:41:308:49 | password1 | test3.cpp:317:11:317:19 | password1 | -| test3.cpp:308:58:308:66 | password2 | test3.cpp:324:11:324:14 | data | -| test3.cpp:308:58:308:66 | password2 | test3.cpp:325:11:325:14 | data | | test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data | -| test3.cpp:313:11:313:19 | password1 | test3.cpp:313:11:313:19 | ref arg password1 | -| test3.cpp:313:11:313:19 | ref arg password1 | test3.cpp:314:11:314:19 | password1 | | test3.cpp:314:11:314:19 | password1 | test3.cpp:283:20:283:23 | data | | test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data | -| test3.cpp:316:11:316:19 | password1 | test3.cpp:316:11:316:19 | ref arg password1 | -| test3.cpp:316:11:316:19 | ref arg password1 | test3.cpp:317:11:317:19 | password1 | | test3.cpp:317:11:317:19 | password1 | test3.cpp:288:20:288:23 | data | +| test3.cpp:322:16:322:24 | password2 | test3.cpp:324:11:324:14 | data | +| test3.cpp:322:16:322:24 | password2 | test3.cpp:325:11:325:14 | data | | test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data | -| test3.cpp:324:11:324:14 | data | test3.cpp:324:11:324:14 | ref arg data | -| test3.cpp:324:11:324:14 | ref arg data | test3.cpp:325:11:325:14 | data | | test3.cpp:325:11:325:14 | data | test3.cpp:298:20:298:23 | data | -| test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | -| test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password | -| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace | -| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password | -| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | -| test3.cpp:366:8:366:15 | password | test3.cpp:374:3:374:18 | call to SecureZeroBuffer | -| test3.cpp:366:8:366:15 | password | test3.cpp:374:20:374:27 | password | -| test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | -| test3.cpp:398:18:398:25 | password | test3.cpp:400:15:400:23 | & ... | -| test3.cpp:398:18:398:25 | password | test3.cpp:400:16:400:23 | password | -| test3.cpp:398:18:398:25 | password | test3.cpp:400:33:400:40 | password | -| test3.cpp:421:21:421:28 | password | test3.cpp:421:3:421:17 | call to decrypt_inplace | -| test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password | -| test3.cpp:526:44:526:54 | my_latitude | test3.cpp:527:15:527:20 | buffer | -| test3.cpp:532:45:532:58 | home_longitude | test3.cpp:533:15:533:20 | buffer | -| test3.cpp:551:47:551:58 | salaryString | test3.cpp:552:15:552:20 | buffer | -| test3.cpp:556:19:556:30 | salaryString | test3.cpp:559:15:559:20 | buffer | +| test3.cpp:400:16:400:23 | password | test3.cpp:400:15:400:23 | & ... | +| test3.cpp:526:44:526:54 | my_latitude | test3.cpp:527:15:527:20 | buffer indirection | +| test3.cpp:532:45:532:58 | home_longitude | test3.cpp:533:15:533:20 | buffer indirection | +| test3.cpp:551:47:551:58 | salaryString | test3.cpp:552:15:552:20 | buffer indirection | +| test3.cpp:556:19:556:30 | salaryString | test3.cpp:559:15:559:20 | buffer indirection | | test3.cpp:571:8:571:21 | call to get_home_phone | test3.cpp:572:14:572:16 | str | | test3.cpp:577:8:577:23 | call to get_home_address | test3.cpp:578:14:578:16 | str | -| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt | -| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword | -| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt | -| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:29:76:39 | thePassword | nodes -| test2.cpp:63:16:63:20 | call to crypt | semmle.label | call to crypt | -| test2.cpp:63:24:63:31 | password | semmle.label | password | -| test2.cpp:63:24:63:31 | password | semmle.label | password | -| test3.cpp:17:28:17:36 | password1 | semmle.label | password1 | -| test3.cpp:17:51:17:59 | password2 | semmle.label | password2 | | test3.cpp:22:15:22:23 | password1 | semmle.label | password1 | | test3.cpp:26:15:26:23 | password2 | semmle.label | password2 | -| test3.cpp:45:8:45:15 | password | semmle.label | password | | test3.cpp:47:15:47:22 | password | semmle.label | password | -| test3.cpp:53:8:53:15 | password | semmle.label | password | | test3.cpp:55:15:55:22 | password | semmle.label | password | -| test3.cpp:71:32:71:40 | password1 | semmle.label | password1 | +| test3.cpp:74:21:74:29 | password1 | semmle.label | password1 | | test3.cpp:76:15:76:17 | ptr | semmle.label | ptr | -| test3.cpp:80:8:80:15 | password | semmle.label | password | +| test3.cpp:81:15:81:22 | password | semmle.label | password | | test3.cpp:83:15:83:17 | ptr | semmle.label | ptr | -| test3.cpp:98:8:98:15 | password | semmle.label | password | | test3.cpp:101:12:101:19 | password | semmle.label | password | | test3.cpp:112:20:112:25 | buffer | semmle.label | buffer | | test3.cpp:114:14:114:19 | buffer | semmle.label | buffer | +| test3.cpp:117:13:117:14 | id indirection | semmle.label | id indirection | | test3.cpp:117:28:117:33 | buffer | semmle.label | buffer | -| test3.cpp:119:9:119:14 | buffer | semmle.label | buffer | +| test3.cpp:124:7:124:20 | get_global_str indirection | semmle.label | get_global_str indirection | | test3.cpp:126:9:126:23 | global_password | semmle.label | global_password | -| test3.cpp:129:39:129:47 | password1 | semmle.label | password1 | -| test3.cpp:132:8:132:15 | password | semmle.label | password | | test3.cpp:134:11:134:18 | password | semmle.label | password | | test3.cpp:138:21:138:22 | call to id | semmle.label | call to id | | test3.cpp:138:24:138:32 | password1 | semmle.label | password1 | | test3.cpp:140:15:140:17 | ptr | semmle.label | ptr | | test3.cpp:144:16:144:29 | call to get_global_str | semmle.label | call to get_global_str | | test3.cpp:146:15:146:18 | data | semmle.label | data | -| test3.cpp:152:29:152:36 | password | semmle.label | password | -| test3.cpp:159:15:159:20 | buffer | semmle.label | buffer | -| test3.cpp:171:8:171:15 | password | semmle.label | password | +| test3.cpp:157:19:157:26 | password | semmle.label | password | +| test3.cpp:159:15:159:20 | buffer indirection | semmle.label | buffer indirection | | test3.cpp:173:15:173:22 | password | semmle.label | password | -| test3.cpp:175:3:175:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace | -| test3.cpp:175:19:175:26 | password | semmle.label | password | -| test3.cpp:179:8:179:15 | password | semmle.label | password | | test3.cpp:181:15:181:22 | password | semmle.label | password | -| test3.cpp:184:3:184:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace | -| test3.cpp:184:19:184:26 | password | semmle.label | password | -| test3.cpp:188:8:188:15 | password | semmle.label | password | | test3.cpp:191:15:191:22 | password | semmle.label | password | -| test3.cpp:193:18:193:28 | call to rtn_decrypt | semmle.label | call to rtn_decrypt | -| test3.cpp:193:30:193:37 | password | semmle.label | password | -| test3.cpp:197:8:197:15 | password | semmle.label | password | -| test3.cpp:199:3:199:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace | -| test3.cpp:199:19:199:26 | password | semmle.label | password | | test3.cpp:201:15:201:22 | password | semmle.label | password | -| test3.cpp:205:8:205:15 | password | semmle.label | password | -| test3.cpp:207:3:207:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace | -| test3.cpp:207:19:207:26 | password | semmle.label | password | | test3.cpp:210:15:210:22 | password | semmle.label | password | -| test3.cpp:214:8:214:15 | password | semmle.label | password | -| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt | -| test3.cpp:217:18:217:28 | call to rtn_encrypt | semmle.label | call to rtn_encrypt | -| test3.cpp:217:30:217:37 | password | semmle.label | password | | test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr | -| test3.cpp:225:34:225:41 | password | semmle.label | password | | test3.cpp:228:26:228:33 | password | semmle.label | password | -| test3.cpp:239:7:239:14 | password | semmle.label | password | | test3.cpp:241:8:241:15 | password | semmle.label | password | -| test3.cpp:252:8:252:16 | password1 | semmle.label | password1 | -| test3.cpp:252:24:252:32 | password2 | semmle.label | password2 | | test3.cpp:254:15:254:23 | password1 | semmle.label | password1 | -| test3.cpp:256:3:256:19 | call to decrypt_to_buffer | semmle.label | call to decrypt_to_buffer | -| test3.cpp:256:21:256:29 | password1 | semmle.label | password1 | -| test3.cpp:256:32:256:40 | password2 | semmle.label | password2 | -| test3.cpp:260:8:260:16 | password1 | semmle.label | password1 | -| test3.cpp:260:24:260:32 | password2 | semmle.label | password2 | -| test3.cpp:262:3:262:19 | call to encrypt_to_buffer | semmle.label | call to encrypt_to_buffer | -| test3.cpp:262:21:262:29 | password1 | semmle.label | password1 | -| test3.cpp:262:32:262:40 | password2 | semmle.label | password2 | | test3.cpp:264:15:264:23 | password2 | semmle.label | password2 | -| test3.cpp:268:19:268:26 | password | semmle.label | password | -| test3.cpp:272:15:272:18 | data | semmle.label | data | -| test3.cpp:278:20:278:23 | data | semmle.label | data | +| test3.cpp:270:16:270:23 | password | semmle.label | password | +| test3.cpp:272:15:272:18 | data indirection | semmle.label | data indirection | | test3.cpp:278:20:278:23 | data | semmle.label | data | | test3.cpp:280:14:280:17 | data | semmle.label | data | | test3.cpp:283:20:283:23 | data | semmle.label | data | -| test3.cpp:283:20:283:23 | data | semmle.label | data | | test3.cpp:285:14:285:17 | data | semmle.label | data | | test3.cpp:288:20:288:23 | data | semmle.label | data | | test3.cpp:290:14:290:17 | data | semmle.label | data | | test3.cpp:293:20:293:23 | data | semmle.label | data | -| test3.cpp:293:20:293:23 | data | semmle.label | data | | test3.cpp:295:14:295:17 | data | semmle.label | data | | test3.cpp:298:20:298:23 | data | semmle.label | data | | test3.cpp:300:14:300:17 | data | semmle.label | data | -| test3.cpp:308:41:308:49 | password1 | semmle.label | password1 | -| test3.cpp:308:58:308:66 | password2 | semmle.label | password2 | -| test3.cpp:312:3:312:17 | call to encrypt_inplace | semmle.label | call to encrypt_inplace | -| test3.cpp:312:19:312:27 | password1 | semmle.label | password1 | | test3.cpp:313:11:313:19 | password1 | semmle.label | password1 | -| test3.cpp:313:11:313:19 | ref arg password1 | semmle.label | ref arg password1 | | test3.cpp:314:11:314:19 | password1 | semmle.label | password1 | | test3.cpp:316:11:316:19 | password1 | semmle.label | password1 | -| test3.cpp:316:11:316:19 | ref arg password1 | semmle.label | ref arg password1 | | test3.cpp:317:11:317:19 | password1 | semmle.label | password1 | +| test3.cpp:322:16:322:24 | password2 | semmle.label | password2 | | test3.cpp:324:11:324:14 | data | semmle.label | data | -| test3.cpp:324:11:324:14 | ref arg data | semmle.label | ref arg data | | test3.cpp:325:11:325:14 | data | semmle.label | data | -| test3.cpp:339:9:339:16 | password | semmle.label | password | | test3.cpp:341:16:341:23 | password | semmle.label | password | -| test3.cpp:350:9:350:16 | password | semmle.label | password | | test3.cpp:352:16:352:23 | password | semmle.label | password | -| test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace | -| test3.cpp:353:20:353:27 | password | semmle.label | password | -| test3.cpp:366:8:366:15 | password | semmle.label | password | | test3.cpp:368:15:368:22 | password | semmle.label | password | -| test3.cpp:374:3:374:18 | call to SecureZeroBuffer | semmle.label | call to SecureZeroBuffer | -| test3.cpp:374:20:374:27 | password | semmle.label | password | -| test3.cpp:386:8:386:15 | password | semmle.label | password | | test3.cpp:388:15:388:22 | password | semmle.label | password | -| test3.cpp:398:18:398:25 | password | semmle.label | password | | test3.cpp:400:15:400:23 | & ... | semmle.label | & ... | | test3.cpp:400:16:400:23 | password | semmle.label | password | -| test3.cpp:400:33:400:40 | password | semmle.label | password | -| test3.cpp:414:17:414:24 | password | semmle.label | password | -| test3.cpp:420:17:420:24 | password | semmle.label | password | -| test3.cpp:421:3:421:17 | call to decrypt_inplace | semmle.label | call to decrypt_inplace | -| test3.cpp:421:21:421:28 | password | semmle.label | password | -| test3.cpp:421:21:421:28 | password | semmle.label | password | -| test3.cpp:429:7:429:14 | password | semmle.label | password | +| test3.cpp:414:15:414:24 | password | semmle.label | password | +| test3.cpp:420:15:420:24 | password | semmle.label | password | | test3.cpp:431:8:431:15 | password | semmle.label | password | -| test3.cpp:507:18:507:39 | social_security_number | semmle.label | social_security_number | -| test3.cpp:508:18:508:33 | socialSecurityNo | semmle.label | socialSecurityNo | -| test3.cpp:509:18:509:29 | homePostCode | semmle.label | homePostCode | -| test3.cpp:510:18:510:28 | my_zip_code | semmle.label | my_zip_code | -| test3.cpp:511:18:511:26 | telephone | semmle.label | telephone | -| test3.cpp:512:18:512:36 | mobile_phone_number | semmle.label | mobile_phone_number | -| test3.cpp:513:18:513:22 | email | semmle.label | email | -| test3.cpp:514:18:514:38 | my_credit_card_number | semmle.label | my_credit_card_number | -| test3.cpp:515:18:515:35 | my_bank_account_no | semmle.label | my_bank_account_no | -| test3.cpp:516:18:516:29 | employerName | semmle.label | employerName | -| test3.cpp:517:18:517:29 | medical_info | semmle.label | medical_info | -| test3.cpp:518:18:518:28 | license_key | semmle.label | license_key | +| test3.cpp:507:14:507:39 | social_security_number | semmle.label | social_security_number | +| test3.cpp:508:14:508:33 | socialSecurityNo | semmle.label | socialSecurityNo | +| test3.cpp:509:14:509:29 | homePostCode | semmle.label | homePostCode | +| test3.cpp:510:14:510:28 | my_zip_code | semmle.label | my_zip_code | +| test3.cpp:511:14:511:26 | telephone | semmle.label | telephone | +| test3.cpp:512:14:512:36 | mobile_phone_number | semmle.label | mobile_phone_number | +| test3.cpp:513:14:513:22 | email | semmle.label | email | +| test3.cpp:514:14:514:38 | my_credit_card_number | semmle.label | my_credit_card_number | +| test3.cpp:515:14:515:35 | my_bank_account_no | semmle.label | my_bank_account_no | +| test3.cpp:516:14:516:29 | employerName | semmle.label | employerName | +| test3.cpp:517:14:517:29 | medical_info | semmle.label | medical_info | +| test3.cpp:518:14:518:28 | license_key | semmle.label | license_key | | test3.cpp:526:44:526:54 | my_latitude | semmle.label | my_latitude | -| test3.cpp:527:15:527:20 | buffer | semmle.label | buffer | +| test3.cpp:527:15:527:20 | buffer indirection | semmle.label | buffer indirection | | test3.cpp:532:45:532:58 | home_longitude | semmle.label | home_longitude | -| test3.cpp:533:15:533:20 | buffer | semmle.label | buffer | +| test3.cpp:533:15:533:20 | buffer indirection | semmle.label | buffer indirection | | test3.cpp:551:47:551:58 | salaryString | semmle.label | salaryString | -| test3.cpp:552:15:552:20 | buffer | semmle.label | buffer | +| test3.cpp:552:15:552:20 | buffer indirection | semmle.label | buffer indirection | | test3.cpp:556:19:556:30 | salaryString | semmle.label | salaryString | -| test3.cpp:559:15:559:20 | buffer | semmle.label | buffer | +| test3.cpp:559:15:559:20 | buffer indirection | semmle.label | buffer indirection | | test3.cpp:571:8:571:21 | call to get_home_phone | semmle.label | call to get_home_phone | | test3.cpp:572:14:572:16 | str | semmle.label | str | | test3.cpp:577:8:577:23 | call to get_home_address | semmle.label | call to get_home_address | | test3.cpp:578:14:578:16 | str | semmle.label | str | -| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! | -| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt | -| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword | -| test.cpp:66:23:66:43 | cleartext password! | semmle.label | cleartext password! | -| test.cpp:76:21:76:27 | call to encrypt | semmle.label | call to encrypt | -| test.cpp:76:29:76:39 | thePassword | semmle.label | thePassword | subpaths -| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer | test3.cpp:119:9:119:14 | buffer | test3.cpp:138:21:138:22 | call to id | -| test3.cpp:313:11:313:19 | password1 | test3.cpp:278:20:278:23 | data | test3.cpp:278:20:278:23 | data | test3.cpp:313:11:313:19 | ref arg password1 | -| test3.cpp:316:11:316:19 | password1 | test3.cpp:283:20:283:23 | data | test3.cpp:283:20:283:23 | data | test3.cpp:316:11:316:19 | ref arg password1 | -| test3.cpp:324:11:324:14 | data | test3.cpp:293:20:293:23 | data | test3.cpp:293:20:293:23 | data | test3.cpp:324:11:324:14 | ref arg data | +| test3.cpp:138:24:138:32 | password1 | test3.cpp:117:28:117:33 | buffer | test3.cpp:117:13:117:14 | id indirection | test3.cpp:138:21:138:22 | call to id | #select -| test3.cpp:22:3:22:6 | call to send | test3.cpp:17:28:17:36 | password1 | test3.cpp:22:15:22:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@. | test3.cpp:17:28:17:36 | password1 | password1 | -| test3.cpp:26:3:26:6 | call to send | test3.cpp:17:51:17:59 | password2 | test3.cpp:26:15:26:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@. | test3.cpp:17:51:17:59 | password2 | password2 | -| test3.cpp:47:3:47:6 | call to recv | test3.cpp:45:8:45:15 | password | test3.cpp:47:15:47:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:45:8:45:15 | password | password | -| test3.cpp:55:3:55:6 | call to recv | test3.cpp:53:8:53:15 | password | test3.cpp:55:15:55:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:53:8:53:15 | password | password | -| test3.cpp:76:3:76:6 | call to send | test3.cpp:71:32:71:40 | password1 | test3.cpp:76:15:76:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@. | test3.cpp:71:32:71:40 | password1 | password1 | -| test3.cpp:83:3:83:6 | call to recv | test3.cpp:80:8:80:15 | password | test3.cpp:83:15:83:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@. | test3.cpp:80:8:80:15 | password | password | -| test3.cpp:101:3:101:6 | call to read | test3.cpp:98:8:98:15 | password | test3.cpp:101:12:101:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:98:8:98:15 | password | password | -| test3.cpp:114:2:114:5 | call to recv | test3.cpp:132:8:132:15 | password | test3.cpp:114:14:114:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@. | test3.cpp:132:8:132:15 | password | password | -| test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@. | test3.cpp:129:39:129:47 | password1 | password1 | +| test3.cpp:22:3:22:6 | call to send | test3.cpp:22:15:22:23 | password1 | test3.cpp:22:15:22:23 | password1 | This operation transmits 'password1', which may contain unencrypted sensitive data from $@. | test3.cpp:22:15:22:23 | password1 | password1 | +| test3.cpp:26:3:26:6 | call to send | test3.cpp:26:15:26:23 | password2 | test3.cpp:26:15:26:23 | password2 | This operation transmits 'password2', which may contain unencrypted sensitive data from $@. | test3.cpp:26:15:26:23 | password2 | password2 | +| test3.cpp:47:3:47:6 | call to recv | test3.cpp:47:15:47:22 | password | test3.cpp:47:15:47:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:47:15:47:22 | password | password | +| test3.cpp:55:3:55:6 | call to recv | test3.cpp:55:15:55:22 | password | test3.cpp:55:15:55:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:55:15:55:22 | password | password | +| test3.cpp:76:3:76:6 | call to send | test3.cpp:74:21:74:29 | password1 | test3.cpp:76:15:76:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@. | test3.cpp:74:21:74:29 | password1 | password1 | +| test3.cpp:83:3:83:6 | call to recv | test3.cpp:81:15:81:22 | password | test3.cpp:83:15:83:17 | ptr | This operation receives into 'ptr', which may put unencrypted sensitive data into $@. | test3.cpp:81:15:81:22 | password | password | +| test3.cpp:101:3:101:6 | call to read | test3.cpp:101:12:101:19 | password | test3.cpp:101:12:101:19 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:101:12:101:19 | password | password | +| test3.cpp:114:2:114:5 | call to recv | test3.cpp:134:11:134:18 | password | test3.cpp:114:14:114:19 | buffer | This operation receives into 'buffer', which may put unencrypted sensitive data into $@. | test3.cpp:134:11:134:18 | password | password | +| test3.cpp:140:3:140:6 | call to send | test3.cpp:138:24:138:32 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@. | test3.cpp:138:24:138:32 | password1 | password1 | | test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:126:9:126:23 | global_password | global_password | -| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@. | test3.cpp:152:29:152:36 | password | password | -| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@. | test3.cpp:225:34:225:41 | password | password | -| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:239:7:239:14 | password | password | -| test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:268:19:268:26 | password | password | -| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:308:58:308:66 | password2 | password2 | -| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:308:58:308:66 | password2 | password2 | -| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:339:9:339:16 | password | password | -| test3.cpp:388:3:388:6 | call to recv | test3.cpp:386:8:386:15 | password | test3.cpp:388:15:388:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:386:8:386:15 | password | password | -| test3.cpp:414:3:414:6 | call to recv | test3.cpp:414:17:414:24 | password | test3.cpp:414:17:414:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:414:17:414:24 | password | password | -| test3.cpp:420:3:420:6 | call to recv | test3.cpp:420:17:420:24 | password | test3.cpp:420:17:420:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:420:17:420:24 | password | password | -| test3.cpp:431:2:431:6 | call to fgets | test3.cpp:429:7:429:14 | password | test3.cpp:431:8:431:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:429:7:429:14 | password | password | -| test3.cpp:507:2:507:5 | call to send | test3.cpp:507:18:507:39 | social_security_number | test3.cpp:507:18:507:39 | social_security_number | This operation transmits 'social_security_number', which may contain unencrypted sensitive data from $@. | test3.cpp:507:18:507:39 | social_security_number | social_security_number | -| test3.cpp:508:2:508:5 | call to send | test3.cpp:508:18:508:33 | socialSecurityNo | test3.cpp:508:18:508:33 | socialSecurityNo | This operation transmits 'socialSecurityNo', which may contain unencrypted sensitive data from $@. | test3.cpp:508:18:508:33 | socialSecurityNo | socialSecurityNo | -| test3.cpp:509:2:509:5 | call to send | test3.cpp:509:18:509:29 | homePostCode | test3.cpp:509:18:509:29 | homePostCode | This operation transmits 'homePostCode', which may contain unencrypted sensitive data from $@. | test3.cpp:509:18:509:29 | homePostCode | homePostCode | -| test3.cpp:510:2:510:5 | call to send | test3.cpp:510:18:510:28 | my_zip_code | test3.cpp:510:18:510:28 | my_zip_code | This operation transmits 'my_zip_code', which may contain unencrypted sensitive data from $@. | test3.cpp:510:18:510:28 | my_zip_code | my_zip_code | -| test3.cpp:511:2:511:5 | call to send | test3.cpp:511:18:511:26 | telephone | test3.cpp:511:18:511:26 | telephone | This operation transmits 'telephone', which may contain unencrypted sensitive data from $@. | test3.cpp:511:18:511:26 | telephone | telephone | -| test3.cpp:512:2:512:5 | call to send | test3.cpp:512:18:512:36 | mobile_phone_number | test3.cpp:512:18:512:36 | mobile_phone_number | This operation transmits 'mobile_phone_number', which may contain unencrypted sensitive data from $@. | test3.cpp:512:18:512:36 | mobile_phone_number | mobile_phone_number | -| test3.cpp:513:2:513:5 | call to send | test3.cpp:513:18:513:22 | email | test3.cpp:513:18:513:22 | email | This operation transmits 'email', which may contain unencrypted sensitive data from $@. | test3.cpp:513:18:513:22 | email | email | -| test3.cpp:514:2:514:5 | call to send | test3.cpp:514:18:514:38 | my_credit_card_number | test3.cpp:514:18:514:38 | my_credit_card_number | This operation transmits 'my_credit_card_number', which may contain unencrypted sensitive data from $@. | test3.cpp:514:18:514:38 | my_credit_card_number | my_credit_card_number | -| test3.cpp:515:2:515:5 | call to send | test3.cpp:515:18:515:35 | my_bank_account_no | test3.cpp:515:18:515:35 | my_bank_account_no | This operation transmits 'my_bank_account_no', which may contain unencrypted sensitive data from $@. | test3.cpp:515:18:515:35 | my_bank_account_no | my_bank_account_no | -| test3.cpp:516:2:516:5 | call to send | test3.cpp:516:18:516:29 | employerName | test3.cpp:516:18:516:29 | employerName | This operation transmits 'employerName', which may contain unencrypted sensitive data from $@. | test3.cpp:516:18:516:29 | employerName | employerName | -| test3.cpp:517:2:517:5 | call to send | test3.cpp:517:18:517:29 | medical_info | test3.cpp:517:18:517:29 | medical_info | This operation transmits 'medical_info', which may contain unencrypted sensitive data from $@. | test3.cpp:517:18:517:29 | medical_info | medical_info | -| test3.cpp:518:2:518:5 | call to send | test3.cpp:518:18:518:28 | license_key | test3.cpp:518:18:518:28 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | test3.cpp:518:18:518:28 | license_key | license_key | -| test3.cpp:527:3:527:6 | call to send | test3.cpp:526:44:526:54 | my_latitude | test3.cpp:527:15:527:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@. | test3.cpp:526:44:526:54 | my_latitude | my_latitude | -| test3.cpp:533:3:533:6 | call to send | test3.cpp:532:45:532:58 | home_longitude | test3.cpp:533:15:533:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@. | test3.cpp:532:45:532:58 | home_longitude | home_longitude | -| test3.cpp:552:3:552:6 | call to send | test3.cpp:551:47:551:58 | salaryString | test3.cpp:552:15:552:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@. | test3.cpp:551:47:551:58 | salaryString | salaryString | -| test3.cpp:559:3:559:6 | call to send | test3.cpp:556:19:556:30 | salaryString | test3.cpp:559:15:559:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@. | test3.cpp:556:19:556:30 | salaryString | salaryString | +| test3.cpp:159:3:159:6 | call to send | test3.cpp:157:19:157:26 | password | test3.cpp:159:15:159:20 | buffer indirection | This operation transmits 'buffer indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:157:19:157:26 | password | password | +| test3.cpp:228:2:228:5 | call to send | test3.cpp:228:26:228:33 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@. | test3.cpp:228:26:228:33 | password | password | +| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:241:8:241:15 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:241:8:241:15 | password | password | +| test3.cpp:272:3:272:6 | call to send | test3.cpp:270:16:270:23 | password | test3.cpp:272:15:272:18 | data indirection | This operation transmits 'data indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:270:16:270:23 | password | password | +| test3.cpp:290:2:290:5 | call to send | test3.cpp:317:11:317:19 | password1 | test3.cpp:290:14:290:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:317:11:317:19 | password1 | password1 | +| test3.cpp:295:2:295:5 | call to send | test3.cpp:322:16:322:24 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:322:16:322:24 | password2 | password2 | +| test3.cpp:300:2:300:5 | call to send | test3.cpp:322:16:322:24 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@. | test3.cpp:322:16:322:24 | password2 | password2 | +| test3.cpp:341:4:341:7 | call to recv | test3.cpp:341:16:341:23 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:341:16:341:23 | password | password | +| test3.cpp:388:3:388:6 | call to recv | test3.cpp:388:15:388:22 | password | test3.cpp:388:15:388:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:388:15:388:22 | password | password | +| test3.cpp:414:3:414:6 | call to recv | test3.cpp:414:15:414:24 | password | test3.cpp:414:15:414:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:414:15:414:24 | password | password | +| test3.cpp:420:3:420:6 | call to recv | test3.cpp:420:15:420:24 | password | test3.cpp:420:15:420:24 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:420:15:420:24 | password | password | +| test3.cpp:431:2:431:6 | call to fgets | test3.cpp:431:8:431:15 | password | test3.cpp:431:8:431:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@. | test3.cpp:431:8:431:15 | password | password | +| test3.cpp:507:2:507:5 | call to send | test3.cpp:507:14:507:39 | social_security_number | test3.cpp:507:14:507:39 | social_security_number | This operation transmits 'social_security_number', which may contain unencrypted sensitive data from $@. | test3.cpp:507:14:507:39 | social_security_number | social_security_number | +| test3.cpp:508:2:508:5 | call to send | test3.cpp:508:14:508:33 | socialSecurityNo | test3.cpp:508:14:508:33 | socialSecurityNo | This operation transmits 'socialSecurityNo', which may contain unencrypted sensitive data from $@. | test3.cpp:508:14:508:33 | socialSecurityNo | socialSecurityNo | +| test3.cpp:509:2:509:5 | call to send | test3.cpp:509:14:509:29 | homePostCode | test3.cpp:509:14:509:29 | homePostCode | This operation transmits 'homePostCode', which may contain unencrypted sensitive data from $@. | test3.cpp:509:14:509:29 | homePostCode | homePostCode | +| test3.cpp:510:2:510:5 | call to send | test3.cpp:510:14:510:28 | my_zip_code | test3.cpp:510:14:510:28 | my_zip_code | This operation transmits 'my_zip_code', which may contain unencrypted sensitive data from $@. | test3.cpp:510:14:510:28 | my_zip_code | my_zip_code | +| test3.cpp:511:2:511:5 | call to send | test3.cpp:511:14:511:26 | telephone | test3.cpp:511:14:511:26 | telephone | This operation transmits 'telephone', which may contain unencrypted sensitive data from $@. | test3.cpp:511:14:511:26 | telephone | telephone | +| test3.cpp:512:2:512:5 | call to send | test3.cpp:512:14:512:36 | mobile_phone_number | test3.cpp:512:14:512:36 | mobile_phone_number | This operation transmits 'mobile_phone_number', which may contain unencrypted sensitive data from $@. | test3.cpp:512:14:512:36 | mobile_phone_number | mobile_phone_number | +| test3.cpp:513:2:513:5 | call to send | test3.cpp:513:14:513:22 | email | test3.cpp:513:14:513:22 | email | This operation transmits 'email', which may contain unencrypted sensitive data from $@. | test3.cpp:513:14:513:22 | email | email | +| test3.cpp:514:2:514:5 | call to send | test3.cpp:514:14:514:38 | my_credit_card_number | test3.cpp:514:14:514:38 | my_credit_card_number | This operation transmits 'my_credit_card_number', which may contain unencrypted sensitive data from $@. | test3.cpp:514:14:514:38 | my_credit_card_number | my_credit_card_number | +| test3.cpp:515:2:515:5 | call to send | test3.cpp:515:14:515:35 | my_bank_account_no | test3.cpp:515:14:515:35 | my_bank_account_no | This operation transmits 'my_bank_account_no', which may contain unencrypted sensitive data from $@. | test3.cpp:515:14:515:35 | my_bank_account_no | my_bank_account_no | +| test3.cpp:516:2:516:5 | call to send | test3.cpp:516:14:516:29 | employerName | test3.cpp:516:14:516:29 | employerName | This operation transmits 'employerName', which may contain unencrypted sensitive data from $@. | test3.cpp:516:14:516:29 | employerName | employerName | +| test3.cpp:517:2:517:5 | call to send | test3.cpp:517:14:517:29 | medical_info | test3.cpp:517:14:517:29 | medical_info | This operation transmits 'medical_info', which may contain unencrypted sensitive data from $@. | test3.cpp:517:14:517:29 | medical_info | medical_info | +| test3.cpp:518:2:518:5 | call to send | test3.cpp:518:14:518:28 | license_key | test3.cpp:518:14:518:28 | license_key | This operation transmits 'license_key', which may contain unencrypted sensitive data from $@. | test3.cpp:518:14:518:28 | license_key | license_key | +| test3.cpp:527:3:527:6 | call to send | test3.cpp:526:44:526:54 | my_latitude | test3.cpp:527:15:527:20 | buffer indirection | This operation transmits 'buffer indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:526:44:526:54 | my_latitude | my_latitude | +| test3.cpp:533:3:533:6 | call to send | test3.cpp:532:45:532:58 | home_longitude | test3.cpp:533:15:533:20 | buffer indirection | This operation transmits 'buffer indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:532:45:532:58 | home_longitude | home_longitude | +| test3.cpp:552:3:552:6 | call to send | test3.cpp:551:47:551:58 | salaryString | test3.cpp:552:15:552:20 | buffer indirection | This operation transmits 'buffer indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:551:47:551:58 | salaryString | salaryString | +| test3.cpp:559:3:559:6 | call to send | test3.cpp:556:19:556:30 | salaryString | test3.cpp:559:15:559:20 | buffer indirection | This operation transmits 'buffer indirection', which may contain unencrypted sensitive data from $@. | test3.cpp:556:19:556:30 | salaryString | salaryString | | test3.cpp:572:2:572:5 | call to send | test3.cpp:571:8:571:21 | call to get_home_phone | test3.cpp:572:14:572:16 | str | This operation transmits 'str', which may contain unencrypted sensitive data from $@. | test3.cpp:571:8:571:21 | call to get_home_phone | call to get_home_phone | | test3.cpp:578:2:578:5 | call to send | test3.cpp:577:8:577:23 | call to get_home_address | test3.cpp:578:14:578:16 | str | This operation transmits 'str', which may contain unencrypted sensitive data from $@. | test3.cpp:577:8:577:23 | call to get_home_address | call to get_home_address | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp index 70630bbb4c4..f4bfe5ca340 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp @@ -287,7 +287,7 @@ void target2(char *data) void target3(char *data) { - send(val(), data, strlen(data), val()); // BAD: data is a plaintext password [NOT DETECTED] + send(val(), data, strlen(data), val()); // BAD: data is a plaintext password } void target4(char *data) diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/UseOfHttp.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/UseOfHttp.expected index c7cda36e413..d5a39f2465c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/UseOfHttp.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/UseOfHttp.expected @@ -1,30 +1,73 @@ edges -| test.cpp:11:26:11:28 | url | test.cpp:15:30:15:32 | url | -| test.cpp:28:10:28:29 | http://example.com | test.cpp:11:26:11:28 | url | -| test.cpp:35:23:35:42 | http://example.com | test.cpp:39:11:39:15 | url_l | -| test.cpp:36:26:36:45 | http://example.com | test.cpp:40:11:40:17 | access to array | -| test.cpp:39:11:39:15 | url_l | test.cpp:11:26:11:28 | url | -| test.cpp:40:11:40:17 | access to array | test.cpp:11:26:11:28 | url | -| test.cpp:46:18:46:26 | http:// | test.cpp:49:11:49:16 | buffer | -| test.cpp:49:11:49:16 | buffer | test.cpp:11:26:11:28 | url | -| test.cpp:110:21:110:40 | http://example.com | test.cpp:121:11:121:13 | ptr | -| test.cpp:121:11:121:13 | ptr | test.cpp:11:26:11:28 | url | +| test.cpp:11:26:11:28 | url indirection | test.cpp:15:30:15:32 | url indirection | +| test.cpp:11:26:11:28 | url indirection | test.cpp:15:30:15:32 | url indirection | +| test.cpp:24:13:24:17 | url_g indirection | test.cpp:38:11:38:15 | url_g indirection | +| test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:24:13:24:17 | url_g indirection | +| test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:24:13:24:17 | url_g indirection | +| test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:11:26:11:28 | url indirection | +| test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:28:10:28:29 | http://example.com indirection | +| test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:39:11:39:15 | url_l indirection | +| test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:39:11:39:15 | url_l indirection | +| test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:40:11:40:17 | access to array indirection | +| test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:40:11:40:17 | access to array indirection | +| test.cpp:38:11:38:15 | url_g indirection | test.cpp:11:26:11:28 | url indirection | +| test.cpp:39:11:39:15 | url_l indirection | test.cpp:11:26:11:28 | url indirection | +| test.cpp:40:11:40:17 | access to array indirection | test.cpp:11:26:11:28 | url indirection | +| test.cpp:46:18:46:26 | http:// indirection | test.cpp:49:11:49:16 | buffer indirection | +| test.cpp:46:18:46:26 | http:// indirection | test.cpp:49:11:49:16 | buffer indirection | +| test.cpp:49:11:49:16 | buffer indirection | test.cpp:11:26:11:28 | url indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:121:11:121:13 | ptr indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:121:11:121:13 | ptr indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:121:11:121:13 | ptr indirection | +| test.cpp:121:11:121:13 | ptr indirection | test.cpp:11:26:11:28 | url indirection | nodes -| test.cpp:11:26:11:28 | url | semmle.label | url | -| test.cpp:15:30:15:32 | url | semmle.label | url | -| test.cpp:28:10:28:29 | http://example.com | semmle.label | http://example.com | -| test.cpp:35:23:35:42 | http://example.com | semmle.label | http://example.com | -| test.cpp:36:26:36:45 | http://example.com | semmle.label | http://example.com | -| test.cpp:39:11:39:15 | url_l | semmle.label | url_l | -| test.cpp:40:11:40:17 | access to array | semmle.label | access to array | -| test.cpp:46:18:46:26 | http:// | semmle.label | http:// | -| test.cpp:49:11:49:16 | buffer | semmle.label | buffer | -| test.cpp:110:21:110:40 | http://example.com | semmle.label | http://example.com | -| test.cpp:121:11:121:13 | ptr | semmle.label | ptr | +| test.cpp:11:26:11:28 | url indirection | semmle.label | url indirection | +| test.cpp:15:30:15:32 | url indirection | semmle.label | url indirection | +| test.cpp:15:30:15:32 | url indirection | semmle.label | url indirection | +| test.cpp:24:13:24:17 | url_g indirection | semmle.label | url_g indirection | +| test.cpp:24:21:24:40 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:24:21:24:40 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:28:10:28:29 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:28:10:28:29 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:35:23:35:42 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:35:23:35:42 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:36:26:36:45 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:36:26:36:45 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:38:11:38:15 | url_g indirection | semmle.label | url_g indirection | +| test.cpp:39:11:39:15 | url_l indirection | semmle.label | url_l indirection | +| test.cpp:40:11:40:17 | access to array indirection | semmle.label | access to array indirection | +| test.cpp:46:18:46:26 | http:// indirection | semmle.label | http:// indirection | +| test.cpp:46:18:46:26 | http:// indirection | semmle.label | http:// indirection | +| test.cpp:49:11:49:16 | buffer indirection | semmle.label | buffer indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:110:21:110:40 | http://example.com indirection | semmle.label | http://example.com indirection | +| test.cpp:121:11:121:13 | ptr indirection | semmle.label | ptr indirection | subpaths #select -| test.cpp:28:10:28:29 | http://example.com | test.cpp:28:10:28:29 | http://example.com | test.cpp:15:30:15:32 | url | This URL may be constructed with the HTTP protocol. | -| test.cpp:35:23:35:42 | http://example.com | test.cpp:35:23:35:42 | http://example.com | test.cpp:15:30:15:32 | url | This URL may be constructed with the HTTP protocol. | -| test.cpp:36:26:36:45 | http://example.com | test.cpp:36:26:36:45 | http://example.com | test.cpp:15:30:15:32 | url | This URL may be constructed with the HTTP protocol. | -| test.cpp:46:18:46:26 | http:// | test.cpp:46:18:46:26 | http:// | test.cpp:15:30:15:32 | url | This URL may be constructed with the HTTP protocol. | -| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com | test.cpp:15:30:15:32 | url | This URL may be constructed with the HTTP protocol. | +| test.cpp:24:21:24:40 | http://example.com | test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:24:21:24:40 | http://example.com | test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:24:21:24:40 | http://example.com | test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:24:21:24:40 | http://example.com | test.cpp:24:21:24:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:28:10:28:29 | http://example.com | test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:28:10:28:29 | http://example.com | test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:28:10:28:29 | http://example.com | test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:28:10:28:29 | http://example.com | test.cpp:28:10:28:29 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:35:23:35:42 | http://example.com | test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:35:23:35:42 | http://example.com | test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:35:23:35:42 | http://example.com | test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:35:23:35:42 | http://example.com | test.cpp:35:23:35:42 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:36:26:36:45 | http://example.com | test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:36:26:36:45 | http://example.com | test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:36:26:36:45 | http://example.com | test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:36:26:36:45 | http://example.com | test.cpp:36:26:36:45 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:46:18:46:26 | http:// | test.cpp:46:18:46:26 | http:// indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:46:18:46:26 | http:// | test.cpp:46:18:46:26 | http:// indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:46:18:46:26 | http:// | test.cpp:46:18:46:26 | http:// indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:46:18:46:26 | http:// | test.cpp:46:18:46:26 | http:// indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | +| test.cpp:110:21:110:40 | http://example.com | test.cpp:110:21:110:40 | http://example.com indirection | test.cpp:15:30:15:32 | url indirection | This URL may be constructed with the HTTP protocol. | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/test.cpp index 2aac68564d0..573e021979d 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/test.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-319/UseOfHttp/test.cpp @@ -21,7 +21,7 @@ void doNothing(char *url) { } -const char *url_g = "http://example.com"; // BAD [NOT DETECTED] +const char *url_g = "http://example.com"; // BAD void test() { diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-497/SAMATE/PotentiallyExposedSystemData.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-497/SAMATE/PotentiallyExposedSystemData.expected index baffc0303d3..a4d19c1473e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-497/SAMATE/PotentiallyExposedSystemData.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-497/SAMATE/PotentiallyExposedSystemData.expected @@ -1,8 +1,14 @@ edges -| tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion | +| tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | +| tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | +| tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | nodes -| tests.c:57:21:57:28 | password | semmle.label | password | -| tests.c:70:70:70:77 | array to pointer conversion | semmle.label | array to pointer conversion | +| tests.c:57:21:57:28 | password indirection | semmle.label | password indirection | +| tests.c:57:21:57:28 | password indirection | semmle.label | password indirection | +| tests.c:57:21:57:28 | password indirection | semmle.label | password indirection | +| tests.c:70:70:70:77 | password indirection | semmle.label | password indirection | subpaths #select -| tests.c:70:70:70:77 | array to pointer conversion | tests.c:57:21:57:28 | password | tests.c:70:70:70:77 | array to pointer conversion | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password | password | +| tests.c:70:70:70:77 | password indirection | tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password indirection | password indirection | +| tests.c:70:70:70:77 | password indirection | tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password indirection | password indirection | +| tests.c:70:70:70:77 | password indirection | tests.c:57:21:57:28 | password indirection | tests.c:70:70:70:77 | password indirection | This operation potentially exposes sensitive system data from $@. | tests.c:57:21:57:28 | password indirection | password indirection | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/ExposedSystemData.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/ExposedSystemData.expected index 11ec8e849a5..a675c3a99d5 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/ExposedSystemData.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/ExposedSystemData.expected @@ -1,92 +1,121 @@ edges -| tests2.cpp:50:13:50:19 | global1 | tests2.cpp:82:14:82:20 | global1 | -| tests2.cpp:50:13:50:19 | global1 | tests2.cpp:82:14:82:20 | global1 | -| tests2.cpp:50:23:50:43 | Store | tests2.cpp:50:13:50:19 | global1 | -| tests2.cpp:50:23:50:43 | call to mysql_get_client_info | tests2.cpp:50:23:50:43 | Store | -| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:26 | (const char *)... | -| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:26 | (const char *)... | -| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:30 | (const char *)... | -| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:34 | (const char *)... | -| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | -| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:82:14:82:20 | global1 | -| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:82:14:82:20 | global1 | -| tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | -| tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | -| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | tests2.cpp:111:14:111:15 | c1 [read] [ptr] | -| tests2.cpp:109:6:109:8 | ptr [post update] | tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | -| tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:109:6:109:8 | ptr [post update] | -| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | tests2.cpp:111:14:111:19 | (const char *)... | -| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | (const void *)... | -| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | -| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | (const void *)... | -| tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | -| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | (const void *)... | -| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | -| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | (const void *)... | -| tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | -| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | (const void *)... | -| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf | +| tests2.cpp:50:13:50:19 | global1 indirection | tests2.cpp:82:14:82:20 | global1 indirection | +| tests2.cpp:50:13:50:19 | global1 indirection | tests2.cpp:82:14:82:20 | global1 indirection | +| tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | tests2.cpp:50:13:50:19 | global1 indirection | +| tests2.cpp:63:13:63:18 | call to getenv indirection | tests2.cpp:63:13:63:26 | call to getenv indirection | +| tests2.cpp:64:13:64:18 | call to getenv indirection | tests2.cpp:64:13:64:26 | call to getenv indirection | +| tests2.cpp:65:13:65:18 | call to getenv indirection | tests2.cpp:65:13:65:30 | call to getenv indirection | +| tests2.cpp:66:13:66:18 | call to getenv indirection | tests2.cpp:66:13:66:34 | call to getenv indirection | +| tests2.cpp:78:18:78:38 | call to mysql_get_client_info indirection | tests2.cpp:81:14:81:19 | buffer indirection | +| tests2.cpp:91:42:91:45 | str1 indirection | tests2.cpp:93:14:93:17 | str1 indirection | +| tests2.cpp:91:42:91:45 | str1 indirection | tests2.cpp:93:14:93:17 | str1 indirection | +| tests2.cpp:101:8:101:15 | call to getpwuid indirection | tests2.cpp:102:14:102:15 | pw indirection | +| tests2.cpp:101:8:101:15 | call to getpwuid indirection | tests2.cpp:102:14:102:15 | pw indirection | +| tests2.cpp:109:3:109:36 | ... = ... indirection | tests2.cpp:109:6:109:8 | c1 indirection [post update] [ptr indirection] | +| tests2.cpp:109:6:109:8 | c1 indirection [post update] [ptr indirection] | tests2.cpp:111:14:111:15 | c1 indirection [ptr indirection] | +| tests2.cpp:109:12:109:17 | call to getenv indirection | tests2.cpp:109:3:109:36 | ... = ... indirection | +| tests2.cpp:111:14:111:15 | c1 indirection [ptr indirection] | tests2.cpp:111:14:111:19 | ptr indirection | +| tests2.cpp:111:14:111:15 | c1 indirection [ptr indirection] | tests2.cpp:111:17:111:19 | ptr indirection | +| tests2.cpp:111:17:111:19 | ptr indirection | tests2.cpp:111:14:111:19 | ptr indirection | +| tests2.cpp:111:17:111:19 | ptr indirection | tests2.cpp:111:17:111:19 | ptr indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | +| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | +| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | +| tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | nodes -| tests2.cpp:50:13:50:19 | global1 | semmle.label | global1 | -| tests2.cpp:50:23:50:43 | Store | semmle.label | Store | -| tests2.cpp:50:23:50:43 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info | -| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:63:13:63:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:63:13:63:26 | (const char *)... | semmle.label | (const char *)... | -| tests2.cpp:64:13:64:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:64:13:64:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:64:13:64:26 | (const char *)... | semmle.label | (const char *)... | -| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:65:13:65:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:65:13:65:30 | (const char *)... | semmle.label | (const char *)... | -| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:66:13:66:18 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:66:13:66:34 | (const char *)... | semmle.label | (const char *)... | -| tests2.cpp:78:18:78:38 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | semmle.label | call to mysql_get_client_info | -| tests2.cpp:81:14:81:19 | (const char *)... | semmle.label | (const char *)... | -| tests2.cpp:82:14:82:20 | global1 | semmle.label | global1 | -| tests2.cpp:82:14:82:20 | global1 | semmle.label | global1 | -| tests2.cpp:91:42:91:45 | str1 | semmle.label | str1 | -| tests2.cpp:93:14:93:17 | str1 | semmle.label | str1 | -| tests2.cpp:101:8:101:15 | call to getpwuid | semmle.label | call to getpwuid | -| tests2.cpp:102:14:102:15 | pw | semmle.label | pw | -| tests2.cpp:109:3:109:4 | c1 [post update] [ptr] | semmle.label | c1 [post update] [ptr] | -| tests2.cpp:109:6:109:8 | ptr [post update] | semmle.label | ptr [post update] | -| tests2.cpp:109:12:109:17 | call to getenv | semmle.label | call to getenv | -| tests2.cpp:111:14:111:15 | c1 [read] [ptr] | semmle.label | c1 [read] [ptr] | -| tests2.cpp:111:14:111:19 | (const char *)... | semmle.label | (const char *)... | -| tests_sockets.cpp:26:15:26:20 | call to getenv | semmle.label | call to getenv | -| tests_sockets.cpp:39:19:39:22 | (const void *)... | semmle.label | (const void *)... | -| tests_sockets.cpp:39:19:39:22 | path | semmle.label | path | -| tests_sockets.cpp:43:20:43:23 | (const void *)... | semmle.label | (const void *)... | -| tests_sockets.cpp:43:20:43:23 | path | semmle.label | path | -| tests_sockets.cpp:63:15:63:20 | call to getenv | semmle.label | call to getenv | -| tests_sockets.cpp:76:19:76:22 | (const void *)... | semmle.label | (const void *)... | -| tests_sockets.cpp:76:19:76:22 | path | semmle.label | path | -| tests_sockets.cpp:80:20:80:23 | (const void *)... | semmle.label | (const void *)... | -| tests_sockets.cpp:80:20:80:23 | path | semmle.label | path | +| tests2.cpp:50:13:50:19 | global1 indirection | semmle.label | global1 indirection | +| tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | semmle.label | call to mysql_get_client_info indirection | +| tests2.cpp:63:13:63:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:63:13:63:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:63:13:63:26 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:64:13:64:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:64:13:64:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:64:13:64:26 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:65:13:65:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:65:13:65:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:65:13:65:30 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:66:13:66:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:66:13:66:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:66:13:66:34 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:78:18:78:38 | call to mysql_get_client_info indirection | semmle.label | call to mysql_get_client_info indirection | +| tests2.cpp:80:14:80:34 | call to mysql_get_client_info indirection | semmle.label | call to mysql_get_client_info indirection | +| tests2.cpp:81:14:81:19 | buffer indirection | semmle.label | buffer indirection | +| tests2.cpp:82:14:82:20 | global1 indirection | semmle.label | global1 indirection | +| tests2.cpp:82:14:82:20 | global1 indirection | semmle.label | global1 indirection | +| tests2.cpp:91:42:91:45 | str1 indirection | semmle.label | str1 indirection | +| tests2.cpp:93:14:93:17 | str1 indirection | semmle.label | str1 indirection | +| tests2.cpp:93:14:93:17 | str1 indirection | semmle.label | str1 indirection | +| tests2.cpp:101:8:101:15 | call to getpwuid indirection | semmle.label | call to getpwuid indirection | +| tests2.cpp:102:14:102:15 | pw indirection | semmle.label | pw indirection | +| tests2.cpp:102:14:102:15 | pw indirection | semmle.label | pw indirection | +| tests2.cpp:109:3:109:36 | ... = ... indirection | semmle.label | ... = ... indirection | +| tests2.cpp:109:6:109:8 | c1 indirection [post update] [ptr indirection] | semmle.label | c1 indirection [post update] [ptr indirection] | +| tests2.cpp:109:12:109:17 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests2.cpp:111:14:111:15 | c1 indirection [ptr indirection] | semmle.label | c1 indirection [ptr indirection] | +| tests2.cpp:111:14:111:19 | ptr indirection | semmle.label | ptr indirection | +| tests2.cpp:111:17:111:19 | ptr indirection | semmle.label | ptr indirection | +| tests2.cpp:111:17:111:19 | ptr indirection | semmle.label | ptr indirection | +| tests_sockets.cpp:26:15:26:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:63:15:63:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | semmle.label | path indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | semmle.label | path indirection | | tests_sysconf.cpp:36:21:36:27 | confstr output argument | semmle.label | confstr output argument | -| tests_sysconf.cpp:39:19:39:25 | (const void *)... | semmle.label | (const void *)... | -| tests_sysconf.cpp:39:19:39:25 | pathbuf | semmle.label | pathbuf | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | semmle.label | pathbuf indirection | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | semmle.label | pathbuf indirection | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | semmle.label | pathbuf indirection | subpaths #select -| tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | tests2.cpp:63:13:63:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv | call to getenv | -| tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | tests2.cpp:64:13:64:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv | call to getenv | -| tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | tests2.cpp:65:13:65:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv | call to getenv | -| tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | tests2.cpp:66:13:66:18 | call to getenv | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv | call to getenv | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info | -| tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info | call to mysql_get_client_info | -| tests2.cpp:81:14:81:19 | (const char *)... | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | tests2.cpp:81:14:81:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info | call to mysql_get_client_info | -| tests2.cpp:82:14:82:20 | global1 | tests2.cpp:50:23:50:43 | call to mysql_get_client_info | tests2.cpp:82:14:82:20 | global1 | This operation exposes system data from $@. | tests2.cpp:50:23:50:43 | call to mysql_get_client_info | call to mysql_get_client_info | -| tests2.cpp:93:14:93:17 | str1 | tests2.cpp:91:42:91:45 | str1 | tests2.cpp:93:14:93:17 | str1 | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 | str1 | -| tests2.cpp:102:14:102:15 | pw | tests2.cpp:101:8:101:15 | call to getpwuid | tests2.cpp:102:14:102:15 | pw | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid | call to getpwuid | -| tests2.cpp:111:14:111:19 | (const char *)... | tests2.cpp:109:12:109:17 | call to getenv | tests2.cpp:111:14:111:19 | (const char *)... | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv | call to getenv | -| tests_sockets.cpp:39:19:39:22 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:39:19:39:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv | -| tests_sockets.cpp:43:20:43:23 | path | tests_sockets.cpp:26:15:26:20 | call to getenv | tests_sockets.cpp:43:20:43:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv | call to getenv | -| tests_sockets.cpp:76:19:76:22 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:76:19:76:22 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv | -| tests_sockets.cpp:80:20:80:23 | path | tests_sockets.cpp:63:15:63:20 | call to getenv | tests_sockets.cpp:80:20:80:23 | path | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv | call to getenv | -| tests_sysconf.cpp:39:19:39:25 | pathbuf | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument | +| tests2.cpp:63:13:63:18 | call to getenv indirection | tests2.cpp:63:13:63:18 | call to getenv indirection | tests2.cpp:63:13:63:18 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:63:13:63:26 | call to getenv indirection | tests2.cpp:63:13:63:18 | call to getenv indirection | tests2.cpp:63:13:63:26 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:63:13:63:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:64:13:64:18 | call to getenv indirection | tests2.cpp:64:13:64:18 | call to getenv indirection | tests2.cpp:64:13:64:18 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:64:13:64:26 | call to getenv indirection | tests2.cpp:64:13:64:18 | call to getenv indirection | tests2.cpp:64:13:64:26 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:64:13:64:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:65:13:65:18 | call to getenv indirection | tests2.cpp:65:13:65:18 | call to getenv indirection | tests2.cpp:65:13:65:18 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:65:13:65:30 | call to getenv indirection | tests2.cpp:65:13:65:18 | call to getenv indirection | tests2.cpp:65:13:65:30 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:65:13:65:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:66:13:66:18 | call to getenv indirection | tests2.cpp:66:13:66:18 | call to getenv indirection | tests2.cpp:66:13:66:18 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:66:13:66:34 | call to getenv indirection | tests2.cpp:66:13:66:18 | call to getenv indirection | tests2.cpp:66:13:66:34 | call to getenv indirection | This operation exposes system data from $@. | tests2.cpp:66:13:66:18 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:80:14:80:34 | call to mysql_get_client_info indirection | tests2.cpp:80:14:80:34 | call to mysql_get_client_info indirection | tests2.cpp:80:14:80:34 | call to mysql_get_client_info indirection | This operation exposes system data from $@. | tests2.cpp:80:14:80:34 | call to mysql_get_client_info indirection | call to mysql_get_client_info indirection | +| tests2.cpp:81:14:81:19 | buffer indirection | tests2.cpp:78:18:78:38 | call to mysql_get_client_info indirection | tests2.cpp:81:14:81:19 | buffer indirection | This operation exposes system data from $@. | tests2.cpp:78:18:78:38 | call to mysql_get_client_info indirection | call to mysql_get_client_info indirection | +| tests2.cpp:82:14:82:20 | global1 indirection | tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | tests2.cpp:82:14:82:20 | global1 indirection | This operation exposes system data from $@. | tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | call to mysql_get_client_info indirection | +| tests2.cpp:82:14:82:20 | global1 indirection | tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | tests2.cpp:82:14:82:20 | global1 indirection | This operation exposes system data from $@. | tests2.cpp:50:23:50:43 | call to mysql_get_client_info indirection | call to mysql_get_client_info indirection | +| tests2.cpp:93:14:93:17 | str1 indirection | tests2.cpp:91:42:91:45 | str1 indirection | tests2.cpp:93:14:93:17 | str1 indirection | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 indirection | str1 indirection | +| tests2.cpp:93:14:93:17 | str1 indirection | tests2.cpp:91:42:91:45 | str1 indirection | tests2.cpp:93:14:93:17 | str1 indirection | This operation exposes system data from $@. | tests2.cpp:91:42:91:45 | str1 indirection | str1 indirection | +| tests2.cpp:102:14:102:15 | pw indirection | tests2.cpp:101:8:101:15 | call to getpwuid indirection | tests2.cpp:102:14:102:15 | pw indirection | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid indirection | call to getpwuid indirection | +| tests2.cpp:102:14:102:15 | pw indirection | tests2.cpp:101:8:101:15 | call to getpwuid indirection | tests2.cpp:102:14:102:15 | pw indirection | This operation exposes system data from $@. | tests2.cpp:101:8:101:15 | call to getpwuid indirection | call to getpwuid indirection | +| tests2.cpp:111:14:111:19 | ptr indirection | tests2.cpp:109:12:109:17 | call to getenv indirection | tests2.cpp:111:14:111:19 | ptr indirection | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv indirection | call to getenv indirection | +| tests2.cpp:111:17:111:19 | ptr indirection | tests2.cpp:109:12:109:17 | call to getenv indirection | tests2.cpp:111:17:111:19 | ptr indirection | This operation exposes system data from $@. | tests2.cpp:109:12:109:17 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:39:19:39:22 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:39:19:39:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:43:20:43:23 | path indirection | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | tests_sockets.cpp:43:20:43:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:26:15:26:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:76:19:76:22 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:76:19:76:22 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sockets.cpp:80:20:80:23 | path indirection | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | tests_sockets.cpp:80:20:80:23 | path indirection | This operation exposes system data from $@. | tests_sockets.cpp:63:15:63:20 | call to getenv indirection | call to getenv indirection | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument | +| tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | tests_sysconf.cpp:36:21:36:27 | confstr output argument | tests_sysconf.cpp:39:19:39:25 | pathbuf indirection | This operation exposes system data from $@. | tests_sysconf.cpp:36:21:36:27 | confstr output argument | confstr output argument | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/PotentiallyExposedSystemData.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/PotentiallyExposedSystemData.expected index ff10a3b9c1c..4c37d69d3d6 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/PotentiallyExposedSystemData.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-497/semmle/tests/PotentiallyExposedSystemData.expected @@ -1,126 +1,119 @@ edges -| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... | -| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... | -| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... | -| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... | -| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | -| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | -| tests.cpp:62:7:62:18 | global_token | tests.cpp:69:17:69:28 | global_token | -| tests.cpp:62:7:62:18 | global_token | tests.cpp:71:27:71:38 | global_token | -| tests.cpp:62:7:62:18 | global_token | tests.cpp:71:27:71:38 | global_token | -| tests.cpp:62:22:62:27 | Store | tests.cpp:62:7:62:18 | global_token | -| tests.cpp:62:22:62:27 | call to getenv | tests.cpp:62:22:62:27 | Store | -| tests.cpp:69:17:69:28 | global_token | tests.cpp:73:27:73:31 | maybe | -| tests.cpp:71:27:71:38 | global_token | tests.cpp:71:27:71:38 | global_token | -| tests.cpp:71:27:71:38 | global_token | tests.cpp:71:27:71:38 | global_token | -| tests.cpp:86:29:86:31 | *msg | tests.cpp:88:15:88:17 | msg | -| tests.cpp:86:29:86:31 | msg | tests.cpp:88:15:88:17 | msg | -| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | -| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv | -| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | call to getenv indirection | -| tests.cpp:97:13:97:34 | call to getenv | tests.cpp:86:29:86:31 | msg | -| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:86:29:86:31 | *msg | -| tests.cpp:107:30:107:32 | *msg | tests.cpp:111:15:111:17 | tmp | -| tests.cpp:107:30:107:32 | msg | tests.cpp:111:15:111:17 | tmp | -| tests.cpp:114:30:114:32 | *msg | tests.cpp:119:7:119:12 | (const char *)... | -| tests.cpp:114:30:114:32 | msg | tests.cpp:119:7:119:12 | (const char *)... | -| tests.cpp:122:30:122:32 | *msg | tests.cpp:124:15:124:17 | msg | -| tests.cpp:122:30:122:32 | msg | tests.cpp:124:15:124:17 | msg | -| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv | -| tests.cpp:131:14:131:19 | call to getenv | tests.cpp:131:14:131:35 | call to getenv indirection | -| tests.cpp:131:14:131:35 | call to getenv | tests.cpp:107:30:107:32 | msg | -| tests.cpp:131:14:131:35 | call to getenv indirection | tests.cpp:107:30:107:32 | *msg | -| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv | -| tests.cpp:132:14:132:19 | call to getenv | tests.cpp:132:14:132:35 | call to getenv indirection | -| tests.cpp:132:14:132:35 | call to getenv | tests.cpp:114:30:114:32 | msg | -| tests.cpp:132:14:132:35 | call to getenv indirection | tests.cpp:114:30:114:32 | *msg | -| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... | -| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv | -| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | call to getenv indirection | -| tests.cpp:133:14:133:35 | call to getenv | tests.cpp:122:30:122:32 | msg | -| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:122:30:122:32 | *msg | -| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd | -| tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd | +| tests.cpp:48:15:48:20 | call to getenv indirection | tests.cpp:48:15:48:36 | call to getenv indirection | +| tests.cpp:49:15:49:20 | call to getenv indirection | tests.cpp:49:15:49:36 | call to getenv indirection | +| tests.cpp:50:15:50:20 | call to getenv indirection | tests.cpp:50:15:50:36 | call to getenv indirection | +| tests.cpp:57:18:57:23 | call to getenv indirection | tests.cpp:57:18:57:39 | call to getenv indirection | +| tests.cpp:58:41:58:46 | call to getenv indirection | tests.cpp:58:41:58:62 | call to getenv indirection | +| tests.cpp:59:43:59:48 | call to getenv indirection | tests.cpp:59:43:59:64 | call to getenv indirection | +| tests.cpp:62:7:62:18 | global_token indirection | tests.cpp:71:27:71:38 | global_token indirection | +| tests.cpp:62:7:62:18 | global_token indirection | tests.cpp:71:27:71:38 | global_token indirection | +| tests.cpp:62:7:62:18 | global_token indirection | tests.cpp:73:27:73:31 | maybe indirection | +| tests.cpp:62:7:62:18 | global_token indirection | tests.cpp:73:27:73:31 | maybe indirection | +| tests.cpp:62:22:62:27 | call to getenv indirection | tests.cpp:62:7:62:18 | global_token indirection | +| tests.cpp:86:29:86:31 | msg indirection | tests.cpp:88:15:88:17 | msg indirection | +| tests.cpp:86:29:86:31 | msg indirection | tests.cpp:88:15:88:17 | msg indirection | +| tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:97:13:97:34 | call to getenv indirection | +| tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:97:13:97:34 | call to getenv indirection | +| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:86:29:86:31 | msg indirection | +| tests.cpp:107:30:107:32 | msg indirection | tests.cpp:111:15:111:17 | tmp indirection | +| tests.cpp:107:30:107:32 | msg indirection | tests.cpp:111:15:111:17 | tmp indirection | +| tests.cpp:114:30:114:32 | msg indirection | tests.cpp:119:7:119:12 | buffer indirection | +| tests.cpp:122:30:122:32 | msg indirection | tests.cpp:124:15:124:17 | msg indirection | +| tests.cpp:122:30:122:32 | msg indirection | tests.cpp:124:15:124:17 | msg indirection | +| tests.cpp:131:14:131:19 | call to getenv indirection | tests.cpp:131:14:131:35 | call to getenv indirection | +| tests.cpp:131:14:131:35 | call to getenv indirection | tests.cpp:107:30:107:32 | msg indirection | +| tests.cpp:132:14:132:19 | call to getenv indirection | tests.cpp:132:14:132:35 | call to getenv indirection | +| tests.cpp:132:14:132:35 | call to getenv indirection | tests.cpp:114:30:114:32 | msg indirection | +| tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:133:14:133:35 | call to getenv indirection | +| tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:133:14:133:35 | call to getenv indirection | +| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:122:30:122:32 | msg indirection | +| tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:18:29:18:31 | pwd indirection | +| tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:18:29:18:31 | pwd indirection | +| tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:19:26:19:28 | pwd indirection | +| tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:19:26:19:28 | pwd indirection | nodes -| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:48:15:48:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:48:15:48:36 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:49:15:49:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:49:15:49:36 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:50:15:50:20 | call to getenv | semmle.label | call to getenv | -| tests.cpp:50:15:50:36 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv | -| tests.cpp:57:18:57:23 | call to getenv | semmle.label | call to getenv | -| tests.cpp:57:18:57:39 | (const char_type *)... | semmle.label | (const char_type *)... | -| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv | -| tests.cpp:58:41:58:46 | call to getenv | semmle.label | call to getenv | -| tests.cpp:58:41:58:62 | (const char_type *)... | semmle.label | (const char_type *)... | -| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv | -| tests.cpp:59:43:59:48 | call to getenv | semmle.label | call to getenv | -| tests.cpp:59:43:59:64 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:62:7:62:18 | global_token | semmle.label | global_token | -| tests.cpp:62:22:62:27 | Store | semmle.label | Store | -| tests.cpp:62:22:62:27 | call to getenv | semmle.label | call to getenv | -| tests.cpp:69:17:69:28 | global_token | semmle.label | global_token | -| tests.cpp:71:27:71:38 | global_token | semmle.label | global_token | -| tests.cpp:71:27:71:38 | global_token | semmle.label | global_token | -| tests.cpp:73:27:73:31 | maybe | semmle.label | maybe | -| tests.cpp:86:29:86:31 | *msg | semmle.label | *msg | -| tests.cpp:86:29:86:31 | msg | semmle.label | msg | -| tests.cpp:88:15:88:17 | msg | semmle.label | msg | -| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv | -| tests.cpp:97:13:97:18 | call to getenv | semmle.label | call to getenv | -| tests.cpp:97:13:97:34 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:97:13:97:34 | call to getenv | semmle.label | call to getenv | +| tests.cpp:48:15:48:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:48:15:48:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:48:15:48:36 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:49:15:49:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:49:15:49:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:49:15:49:36 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:50:15:50:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:50:15:50:20 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:50:15:50:36 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:57:18:57:23 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:57:18:57:23 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:57:18:57:39 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:58:41:58:46 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:58:41:58:46 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:58:41:58:62 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:59:43:59:48 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:59:43:59:48 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:59:43:59:64 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:62:7:62:18 | global_token indirection | semmle.label | global_token indirection | +| tests.cpp:62:22:62:27 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:71:27:71:38 | global_token indirection | semmle.label | global_token indirection | +| tests.cpp:71:27:71:38 | global_token indirection | semmle.label | global_token indirection | +| tests.cpp:73:27:73:31 | maybe indirection | semmle.label | maybe indirection | +| tests.cpp:73:27:73:31 | maybe indirection | semmle.label | maybe indirection | +| tests.cpp:86:29:86:31 | msg indirection | semmle.label | msg indirection | +| tests.cpp:88:15:88:17 | msg indirection | semmle.label | msg indirection | +| tests.cpp:88:15:88:17 | msg indirection | semmle.label | msg indirection | +| tests.cpp:97:13:97:18 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:97:13:97:18 | call to getenv indirection | semmle.label | call to getenv indirection | | tests.cpp:97:13:97:34 | call to getenv indirection | semmle.label | call to getenv indirection | -| tests.cpp:107:30:107:32 | *msg | semmle.label | *msg | -| tests.cpp:107:30:107:32 | msg | semmle.label | msg | -| tests.cpp:111:15:111:17 | tmp | semmle.label | tmp | -| tests.cpp:114:30:114:32 | *msg | semmle.label | *msg | -| tests.cpp:114:30:114:32 | msg | semmle.label | msg | -| tests.cpp:119:7:119:12 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:122:30:122:32 | *msg | semmle.label | *msg | -| tests.cpp:122:30:122:32 | msg | semmle.label | msg | -| tests.cpp:124:15:124:17 | msg | semmle.label | msg | -| tests.cpp:131:14:131:19 | call to getenv | semmle.label | call to getenv | -| tests.cpp:131:14:131:35 | call to getenv | semmle.label | call to getenv | +| tests.cpp:97:13:97:34 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:107:30:107:32 | msg indirection | semmle.label | msg indirection | +| tests.cpp:111:15:111:17 | tmp indirection | semmle.label | tmp indirection | +| tests.cpp:111:15:111:17 | tmp indirection | semmle.label | tmp indirection | +| tests.cpp:114:30:114:32 | msg indirection | semmle.label | msg indirection | +| tests.cpp:119:7:119:12 | buffer indirection | semmle.label | buffer indirection | +| tests.cpp:122:30:122:32 | msg indirection | semmle.label | msg indirection | +| tests.cpp:124:15:124:17 | msg indirection | semmle.label | msg indirection | +| tests.cpp:124:15:124:17 | msg indirection | semmle.label | msg indirection | +| tests.cpp:131:14:131:19 | call to getenv indirection | semmle.label | call to getenv indirection | | tests.cpp:131:14:131:35 | call to getenv indirection | semmle.label | call to getenv indirection | -| tests.cpp:132:14:132:19 | call to getenv | semmle.label | call to getenv | -| tests.cpp:132:14:132:35 | call to getenv | semmle.label | call to getenv | +| tests.cpp:132:14:132:19 | call to getenv indirection | semmle.label | call to getenv indirection | | tests.cpp:132:14:132:35 | call to getenv indirection | semmle.label | call to getenv indirection | -| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv | -| tests.cpp:133:14:133:19 | call to getenv | semmle.label | call to getenv | -| tests.cpp:133:14:133:35 | (const char *)... | semmle.label | (const char *)... | -| tests.cpp:133:14:133:35 | call to getenv | semmle.label | call to getenv | +| tests.cpp:133:14:133:19 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests.cpp:133:14:133:19 | call to getenv indirection | semmle.label | call to getenv indirection | | tests.cpp:133:14:133:35 | call to getenv indirection | semmle.label | call to getenv indirection | -| tests_passwd.cpp:16:8:16:15 | call to getpwnam | semmle.label | call to getpwnam | -| tests_passwd.cpp:18:29:18:31 | pwd | semmle.label | pwd | -| tests_passwd.cpp:19:26:19:28 | pwd | semmle.label | pwd | +| tests.cpp:133:14:133:35 | call to getenv indirection | semmle.label | call to getenv indirection | +| tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | semmle.label | call to getpwnam indirection | +| tests_passwd.cpp:18:29:18:31 | pwd indirection | semmle.label | pwd indirection | +| tests_passwd.cpp:18:29:18:31 | pwd indirection | semmle.label | pwd indirection | +| tests_passwd.cpp:19:26:19:28 | pwd indirection | semmle.label | pwd indirection | +| tests_passwd.cpp:19:26:19:28 | pwd indirection | semmle.label | pwd indirection | subpaths #select -| tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv | -| tests.cpp:48:15:48:36 | (const char *)... | tests.cpp:48:15:48:20 | call to getenv | tests.cpp:48:15:48:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv | call to getenv | -| tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv | -| tests.cpp:49:15:49:36 | (const char *)... | tests.cpp:49:15:49:20 | call to getenv | tests.cpp:49:15:49:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv | call to getenv | -| tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:20 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv | -| tests.cpp:50:15:50:36 | (const char *)... | tests.cpp:50:15:50:20 | call to getenv | tests.cpp:50:15:50:36 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv | call to getenv | -| tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:23 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv | -| tests.cpp:57:18:57:39 | (const char_type *)... | tests.cpp:57:18:57:23 | call to getenv | tests.cpp:57:18:57:39 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv | call to getenv | -| tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:46 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv | -| tests.cpp:58:41:58:62 | (const char_type *)... | tests.cpp:58:41:58:46 | call to getenv | tests.cpp:58:41:58:62 | (const char_type *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv | call to getenv | -| tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:48 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv | -| tests.cpp:59:43:59:64 | (const char *)... | tests.cpp:59:43:59:48 | call to getenv | tests.cpp:59:43:59:64 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv | call to getenv | -| tests.cpp:71:27:71:38 | global_token | tests.cpp:62:22:62:27 | call to getenv | tests.cpp:71:27:71:38 | global_token | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv | call to getenv | -| tests.cpp:73:27:73:31 | maybe | tests.cpp:62:22:62:27 | call to getenv | tests.cpp:73:27:73:31 | maybe | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv | call to getenv | -| tests.cpp:88:15:88:17 | msg | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:88:15:88:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv | -| tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:18 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv | -| tests.cpp:97:13:97:34 | (const char *)... | tests.cpp:97:13:97:18 | call to getenv | tests.cpp:97:13:97:34 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv | call to getenv | -| tests.cpp:111:15:111:17 | tmp | tests.cpp:131:14:131:19 | call to getenv | tests.cpp:111:15:111:17 | tmp | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv | call to getenv | -| tests.cpp:119:7:119:12 | (const char *)... | tests.cpp:132:14:132:19 | call to getenv | tests.cpp:119:7:119:12 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:132:14:132:19 | call to getenv | call to getenv | -| tests.cpp:124:15:124:17 | msg | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:124:15:124:17 | msg | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv | -| tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:19 | call to getenv | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv | -| tests.cpp:133:14:133:35 | (const char *)... | tests.cpp:133:14:133:19 | call to getenv | tests.cpp:133:14:133:35 | (const char *)... | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv | call to getenv | -| tests_passwd.cpp:18:29:18:31 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:18:29:18:31 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam | -| tests_passwd.cpp:19:26:19:28 | pwd | tests_passwd.cpp:16:8:16:15 | call to getpwnam | tests_passwd.cpp:19:26:19:28 | pwd | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam | call to getpwnam | +| tests.cpp:48:15:48:20 | call to getenv indirection | tests.cpp:48:15:48:20 | call to getenv indirection | tests.cpp:48:15:48:20 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:48:15:48:36 | call to getenv indirection | tests.cpp:48:15:48:20 | call to getenv indirection | tests.cpp:48:15:48:36 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:48:15:48:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:49:15:49:20 | call to getenv indirection | tests.cpp:49:15:49:20 | call to getenv indirection | tests.cpp:49:15:49:20 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:49:15:49:36 | call to getenv indirection | tests.cpp:49:15:49:20 | call to getenv indirection | tests.cpp:49:15:49:36 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:49:15:49:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:50:15:50:20 | call to getenv indirection | tests.cpp:50:15:50:20 | call to getenv indirection | tests.cpp:50:15:50:20 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:50:15:50:36 | call to getenv indirection | tests.cpp:50:15:50:20 | call to getenv indirection | tests.cpp:50:15:50:36 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:50:15:50:20 | call to getenv indirection | call to getenv indirection | +| tests.cpp:57:18:57:23 | call to getenv indirection | tests.cpp:57:18:57:23 | call to getenv indirection | tests.cpp:57:18:57:23 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv indirection | call to getenv indirection | +| tests.cpp:57:18:57:39 | call to getenv indirection | tests.cpp:57:18:57:23 | call to getenv indirection | tests.cpp:57:18:57:39 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:57:18:57:23 | call to getenv indirection | call to getenv indirection | +| tests.cpp:58:41:58:46 | call to getenv indirection | tests.cpp:58:41:58:46 | call to getenv indirection | tests.cpp:58:41:58:46 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv indirection | call to getenv indirection | +| tests.cpp:58:41:58:62 | call to getenv indirection | tests.cpp:58:41:58:46 | call to getenv indirection | tests.cpp:58:41:58:62 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:58:41:58:46 | call to getenv indirection | call to getenv indirection | +| tests.cpp:59:43:59:48 | call to getenv indirection | tests.cpp:59:43:59:48 | call to getenv indirection | tests.cpp:59:43:59:48 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv indirection | call to getenv indirection | +| tests.cpp:59:43:59:64 | call to getenv indirection | tests.cpp:59:43:59:48 | call to getenv indirection | tests.cpp:59:43:59:64 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:59:43:59:48 | call to getenv indirection | call to getenv indirection | +| tests.cpp:71:27:71:38 | global_token indirection | tests.cpp:62:22:62:27 | call to getenv indirection | tests.cpp:71:27:71:38 | global_token indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv indirection | call to getenv indirection | +| tests.cpp:71:27:71:38 | global_token indirection | tests.cpp:62:22:62:27 | call to getenv indirection | tests.cpp:71:27:71:38 | global_token indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv indirection | call to getenv indirection | +| tests.cpp:73:27:73:31 | maybe indirection | tests.cpp:62:22:62:27 | call to getenv indirection | tests.cpp:73:27:73:31 | maybe indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv indirection | call to getenv indirection | +| tests.cpp:73:27:73:31 | maybe indirection | tests.cpp:62:22:62:27 | call to getenv indirection | tests.cpp:73:27:73:31 | maybe indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:62:22:62:27 | call to getenv indirection | call to getenv indirection | +| tests.cpp:88:15:88:17 | msg indirection | tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:88:15:88:17 | msg indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv indirection | call to getenv indirection | +| tests.cpp:88:15:88:17 | msg indirection | tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:88:15:88:17 | msg indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv indirection | call to getenv indirection | +| tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:97:13:97:18 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv indirection | call to getenv indirection | +| tests.cpp:97:13:97:34 | call to getenv indirection | tests.cpp:97:13:97:18 | call to getenv indirection | tests.cpp:97:13:97:34 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:97:13:97:18 | call to getenv indirection | call to getenv indirection | +| tests.cpp:111:15:111:17 | tmp indirection | tests.cpp:131:14:131:19 | call to getenv indirection | tests.cpp:111:15:111:17 | tmp indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:111:15:111:17 | tmp indirection | tests.cpp:131:14:131:19 | call to getenv indirection | tests.cpp:111:15:111:17 | tmp indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:131:14:131:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:119:7:119:12 | buffer indirection | tests.cpp:132:14:132:19 | call to getenv indirection | tests.cpp:119:7:119:12 | buffer indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:132:14:132:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:124:15:124:17 | msg indirection | tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:124:15:124:17 | msg indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:124:15:124:17 | msg indirection | tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:124:15:124:17 | msg indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:133:14:133:19 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv indirection | call to getenv indirection | +| tests.cpp:133:14:133:35 | call to getenv indirection | tests.cpp:133:14:133:19 | call to getenv indirection | tests.cpp:133:14:133:35 | call to getenv indirection | This operation potentially exposes sensitive system data from $@. | tests.cpp:133:14:133:19 | call to getenv indirection | call to getenv indirection | +| tests_passwd.cpp:18:29:18:31 | pwd indirection | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:18:29:18:31 | pwd indirection | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | call to getpwnam indirection | +| tests_passwd.cpp:18:29:18:31 | pwd indirection | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:18:29:18:31 | pwd indirection | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | call to getpwnam indirection | +| tests_passwd.cpp:19:26:19:28 | pwd indirection | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:19:26:19:28 | pwd indirection | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | call to getpwnam indirection | +| tests_passwd.cpp:19:26:19:28 | pwd indirection | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | tests_passwd.cpp:19:26:19:28 | pwd indirection | This operation potentially exposes sensitive system data from $@. | tests_passwd.cpp:16:8:16:15 | call to getpwnam indirection | call to getpwnam indirection | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected index 7403cba893a..7acab8885ed 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/XXE.expected @@ -1,173 +1,196 @@ edges -| tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | -| tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | -| tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p | -| tests3.cpp:35:16:35:20 | p_3_3 | tests3.cpp:38:2:38:6 | p_3_3 | -| tests3.cpp:35:24:35:56 | Store | tests3.cpp:35:16:35:20 | p_3_3 | -| tests3.cpp:35:24:35:56 | call to createXMLReader | tests3.cpp:35:24:35:56 | Store | -| tests3.cpp:41:16:41:20 | p_3_4 | tests3.cpp:45:2:45:6 | p_3_4 | -| tests3.cpp:41:24:41:56 | Store | tests3.cpp:41:16:41:20 | p_3_4 | -| tests3.cpp:41:24:41:56 | call to createXMLReader | tests3.cpp:41:24:41:56 | Store | -| tests3.cpp:48:16:48:20 | p_3_5 | tests3.cpp:56:2:56:6 | p_3_5 | -| tests3.cpp:48:24:48:56 | Store | tests3.cpp:48:16:48:20 | p_3_5 | -| tests3.cpp:48:24:48:56 | call to createXMLReader | tests3.cpp:48:24:48:56 | Store | -| tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p | -| tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p | -| tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p | -| tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p | -| tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p | -| tests5.cpp:63:14:63:17 | g_p1 | tests5.cpp:76:2:76:5 | g_p1 | -| tests5.cpp:63:21:63:24 | g_p2 | tests5.cpp:77:2:77:5 | g_p2 | -| tests5.cpp:67:2:67:32 | Store | tests5.cpp:63:14:63:17 | g_p1 | -| tests5.cpp:67:17:67:30 | call to createLSParser | tests5.cpp:67:2:67:32 | Store | -| tests5.cpp:70:2:70:32 | Store | tests5.cpp:63:21:63:24 | g_p2 | -| tests5.cpp:70:17:70:30 | call to createLSParser | tests5.cpp:70:2:70:32 | Store | -| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p | -| tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p | -| tests5.cpp:83:2:83:2 | p | tests5.cpp:85:2:85:2 | p | -| tests5.cpp:85:2:85:2 | p | tests5.cpp:86:2:86:2 | p | -| tests5.cpp:86:2:86:2 | p | tests5.cpp:88:2:88:2 | p | -| tests5.cpp:88:2:88:2 | p | tests5.cpp:89:2:89:2 | p | -| tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p | -| tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p | -| tests.cpp:35:19:35:19 | VariableAddress [post update] | tests.cpp:37:2:37:2 | p | -| tests.cpp:35:23:35:43 | XercesDOMParser output argument | tests.cpp:35:19:35:19 | VariableAddress [post update] | -| tests.cpp:37:2:37:2 | p | tests.cpp:38:2:38:2 | p | -| tests.cpp:38:2:38:2 | p | tests.cpp:39:2:39:2 | p | -| tests.cpp:51:19:51:19 | VariableAddress [post update] | tests.cpp:53:2:53:2 | p | -| tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:51:19:51:19 | VariableAddress [post update] | -| tests.cpp:53:2:53:2 | p | tests.cpp:54:2:54:2 | p | -| tests.cpp:54:2:54:2 | p | tests.cpp:55:2:55:2 | p | -| tests.cpp:55:2:55:2 | p | tests.cpp:56:2:56:2 | p | -| tests.cpp:55:2:55:2 | p | tests.cpp:56:2:56:2 | p | -| tests.cpp:56:2:56:2 | p | tests.cpp:57:2:57:2 | p | -| tests.cpp:57:2:57:2 | p | tests.cpp:58:2:58:2 | p | -| tests.cpp:58:2:58:2 | p | tests.cpp:59:2:59:2 | p | -| tests.cpp:59:2:59:2 | p | tests.cpp:60:2:60:2 | p | -| tests.cpp:66:23:66:43 | XercesDOMParser output argument | tests.cpp:69:2:69:2 | p | -| tests.cpp:73:23:73:43 | XercesDOMParser output argument | tests.cpp:80:2:80:2 | p | -| tests.cpp:85:24:85:44 | XercesDOMParser output argument | tests.cpp:88:3:88:3 | q | -| tests.cpp:100:24:100:44 | XercesDOMParser output argument | tests.cpp:104:3:104:3 | q | -| tests.cpp:112:39:112:39 | p | tests.cpp:113:2:113:2 | p | -| tests.cpp:116:39:116:39 | p | tests.cpp:117:2:117:2 | p | -| tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:126:18:126:18 | q | -| tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:128:18:128:18 | q | -| tests.cpp:126:18:126:18 | q | tests.cpp:112:39:112:39 | p | -| tests.cpp:128:18:128:18 | q | tests.cpp:116:39:116:39 | p | +| tests2.cpp:20:17:20:31 | call to SAXParser | tests2.cpp:22:2:22:2 | p indirection | +| tests2.cpp:20:17:20:31 | call to SAXParser | tests2.cpp:22:2:22:2 | p indirection | +| tests2.cpp:33:17:33:31 | call to SAXParser | tests2.cpp:37:2:37:2 | p indirection | +| tests2.cpp:33:17:33:31 | call to SAXParser | tests2.cpp:37:2:37:2 | p indirection | +| tests2.cpp:49:12:49:12 | call to SAXParser | tests2.cpp:51:2:51:2 | p indirection | +| tests3.cpp:23:21:23:53 | call to createXMLReader indirection | tests3.cpp:25:2:25:2 | p indirection | +| tests3.cpp:23:21:23:53 | call to createXMLReader indirection | tests3.cpp:25:2:25:2 | p indirection | +| tests3.cpp:35:16:35:20 | p_3_3 indirection | tests3.cpp:38:2:38:6 | p_3_3 indirection | +| tests3.cpp:35:16:35:20 | p_3_3 indirection | tests3.cpp:38:2:38:6 | p_3_3 indirection | +| tests3.cpp:35:24:35:56 | call to createXMLReader indirection | tests3.cpp:35:16:35:20 | p_3_3 indirection | +| tests3.cpp:48:16:48:20 | p_3_5 indirection | tests3.cpp:56:2:56:6 | p_3_5 indirection | +| tests3.cpp:48:16:48:20 | p_3_5 indirection | tests3.cpp:56:2:56:6 | p_3_5 indirection | +| tests3.cpp:48:24:48:56 | call to createXMLReader indirection | tests3.cpp:48:16:48:20 | p_3_5 indirection | +| tests3.cpp:60:21:60:53 | call to createXMLReader indirection | tests3.cpp:63:2:63:2 | p indirection | +| tests3.cpp:60:21:60:53 | call to createXMLReader indirection | tests3.cpp:63:2:63:2 | p indirection | +| tests3.cpp:67:21:67:53 | call to createXMLReader indirection | tests3.cpp:70:2:70:2 | p indirection | +| tests3.cpp:67:21:67:53 | call to createXMLReader indirection | tests3.cpp:70:2:70:2 | p indirection | +| tests5.cpp:27:25:27:38 | call to createLSParser indirection | tests5.cpp:29:2:29:2 | p indirection | +| tests5.cpp:27:25:27:38 | call to createLSParser indirection | tests5.cpp:29:2:29:2 | p indirection | +| tests5.cpp:40:25:40:38 | call to createLSParser indirection | tests5.cpp:43:2:43:2 | p indirection | +| tests5.cpp:40:25:40:38 | call to createLSParser indirection | tests5.cpp:43:2:43:2 | p indirection | +| tests5.cpp:55:25:55:38 | call to createLSParser indirection | tests5.cpp:59:2:59:2 | p indirection | +| tests5.cpp:55:25:55:38 | call to createLSParser indirection | tests5.cpp:59:2:59:2 | p indirection | +| tests5.cpp:63:21:63:24 | g_p2 indirection | tests5.cpp:77:2:77:5 | g_p2 indirection | +| tests5.cpp:63:21:63:24 | g_p2 indirection | tests5.cpp:77:2:77:5 | g_p2 indirection | +| tests5.cpp:70:17:70:30 | call to createLSParser indirection | tests5.cpp:63:21:63:24 | g_p2 indirection | +| tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:83:2:83:2 | p indirection | +| tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:83:2:83:2 | p indirection | +| tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:83:2:83:2 | p indirection | +| tests5.cpp:83:2:83:2 | p indirection | tests5.cpp:85:2:85:2 | p indirection | +| tests5.cpp:85:2:85:2 | p indirection | tests5.cpp:86:2:86:2 | p indirection | +| tests5.cpp:86:2:86:2 | p indirection | tests5.cpp:88:2:88:2 | p indirection | +| tests5.cpp:88:2:88:2 | p indirection | tests5.cpp:89:2:89:2 | p indirection | +| tests5.cpp:88:2:88:2 | p indirection | tests5.cpp:89:2:89:2 | p indirection | +| tests.cpp:15:23:15:43 | call to XercesDOMParser | tests.cpp:17:2:17:2 | p indirection | +| tests.cpp:28:23:28:43 | call to XercesDOMParser | tests.cpp:31:2:31:2 | p indirection | +| tests.cpp:35:23:35:43 | call to XercesDOMParser | tests.cpp:35:23:35:43 | new indirection | +| tests.cpp:35:23:35:43 | new indirection | tests.cpp:37:2:37:2 | p indirection | +| tests.cpp:37:2:37:2 | p indirection | tests.cpp:37:2:37:2 | p indirection | +| tests.cpp:37:2:37:2 | p indirection | tests.cpp:38:2:38:2 | p indirection | +| tests.cpp:38:2:38:2 | p indirection | tests.cpp:39:2:39:2 | p indirection | +| tests.cpp:51:23:51:43 | call to XercesDOMParser | tests.cpp:51:23:51:43 | new indirection | +| tests.cpp:51:23:51:43 | new indirection | tests.cpp:53:2:53:2 | p indirection | +| tests.cpp:53:2:53:2 | p indirection | tests.cpp:54:2:54:2 | p indirection | +| tests.cpp:54:2:54:2 | p indirection | tests.cpp:55:2:55:2 | p indirection | +| tests.cpp:55:2:55:2 | p indirection | tests.cpp:56:2:56:2 | p indirection | +| tests.cpp:55:2:55:2 | p indirection | tests.cpp:56:2:56:2 | p indirection | +| tests.cpp:56:2:56:2 | p indirection | tests.cpp:57:2:57:2 | p indirection | +| tests.cpp:57:2:57:2 | p indirection | tests.cpp:58:2:58:2 | p indirection | +| tests.cpp:58:2:58:2 | p indirection | tests.cpp:59:2:59:2 | p indirection | +| tests.cpp:59:2:59:2 | p indirection | tests.cpp:60:2:60:2 | p indirection | +| tests.cpp:66:23:66:43 | call to XercesDOMParser | tests.cpp:69:2:69:2 | p indirection | +| tests.cpp:73:23:73:43 | call to XercesDOMParser | tests.cpp:80:2:80:2 | p indirection | +| tests.cpp:85:24:85:44 | call to XercesDOMParser | tests.cpp:88:3:88:3 | q indirection | +| tests.cpp:100:24:100:44 | call to XercesDOMParser | tests.cpp:104:3:104:3 | q indirection | +| tests.cpp:112:39:112:39 | p indirection | tests.cpp:113:2:113:2 | p indirection | +| tests.cpp:116:39:116:39 | p indirection | tests.cpp:117:2:117:2 | p indirection | +| tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:126:18:126:18 | q indirection | +| tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:128:18:128:18 | q indirection | +| tests.cpp:126:18:126:18 | q indirection | tests.cpp:112:39:112:39 | p indirection | +| tests.cpp:128:18:128:18 | q indirection | tests.cpp:116:39:116:39 | p indirection | nodes -| tests2.cpp:20:17:20:31 | SAXParser output argument | semmle.label | SAXParser output argument | -| tests2.cpp:22:2:22:2 | p | semmle.label | p | -| tests2.cpp:33:17:33:31 | SAXParser output argument | semmle.label | SAXParser output argument | -| tests2.cpp:37:2:37:2 | p | semmle.label | p | -| tests3.cpp:23:21:23:53 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:25:2:25:2 | p | semmle.label | p | -| tests3.cpp:35:16:35:20 | p_3_3 | semmle.label | p_3_3 | -| tests3.cpp:35:24:35:56 | Store | semmle.label | Store | -| tests3.cpp:35:24:35:56 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:38:2:38:6 | p_3_3 | semmle.label | p_3_3 | -| tests3.cpp:41:16:41:20 | p_3_4 | semmle.label | p_3_4 | -| tests3.cpp:41:24:41:56 | Store | semmle.label | Store | -| tests3.cpp:41:24:41:56 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:45:2:45:6 | p_3_4 | semmle.label | p_3_4 | -| tests3.cpp:48:16:48:20 | p_3_5 | semmle.label | p_3_5 | -| tests3.cpp:48:24:48:56 | Store | semmle.label | Store | -| tests3.cpp:48:24:48:56 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:56:2:56:6 | p_3_5 | semmle.label | p_3_5 | -| tests3.cpp:60:21:60:53 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:63:2:63:2 | p | semmle.label | p | -| tests3.cpp:67:21:67:53 | call to createXMLReader | semmle.label | call to createXMLReader | -| tests3.cpp:70:2:70:2 | p | semmle.label | p | -| tests4.cpp:26:34:26:48 | (int)... | semmle.label | (int)... | -| tests4.cpp:36:34:36:50 | (int)... | semmle.label | (int)... | +| tests2.cpp:20:17:20:31 | call to SAXParser | semmle.label | call to SAXParser | +| tests2.cpp:22:2:22:2 | p indirection | semmle.label | p indirection | +| tests2.cpp:22:2:22:2 | p indirection | semmle.label | p indirection | +| tests2.cpp:33:17:33:31 | call to SAXParser | semmle.label | call to SAXParser | +| tests2.cpp:37:2:37:2 | p indirection | semmle.label | p indirection | +| tests2.cpp:37:2:37:2 | p indirection | semmle.label | p indirection | +| tests2.cpp:49:12:49:12 | call to SAXParser | semmle.label | call to SAXParser | +| tests2.cpp:51:2:51:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:23:21:23:53 | call to createXMLReader indirection | semmle.label | call to createXMLReader indirection | +| tests3.cpp:25:2:25:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:25:2:25:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:35:16:35:20 | p_3_3 indirection | semmle.label | p_3_3 indirection | +| tests3.cpp:35:24:35:56 | call to createXMLReader indirection | semmle.label | call to createXMLReader indirection | +| tests3.cpp:38:2:38:6 | p_3_3 indirection | semmle.label | p_3_3 indirection | +| tests3.cpp:38:2:38:6 | p_3_3 indirection | semmle.label | p_3_3 indirection | +| tests3.cpp:48:16:48:20 | p_3_5 indirection | semmle.label | p_3_5 indirection | +| tests3.cpp:48:24:48:56 | call to createXMLReader indirection | semmle.label | call to createXMLReader indirection | +| tests3.cpp:56:2:56:6 | p_3_5 indirection | semmle.label | p_3_5 indirection | +| tests3.cpp:56:2:56:6 | p_3_5 indirection | semmle.label | p_3_5 indirection | +| tests3.cpp:60:21:60:53 | call to createXMLReader indirection | semmle.label | call to createXMLReader indirection | +| tests3.cpp:63:2:63:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:63:2:63:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:67:21:67:53 | call to createXMLReader indirection | semmle.label | call to createXMLReader indirection | +| tests3.cpp:70:2:70:2 | p indirection | semmle.label | p indirection | +| tests3.cpp:70:2:70:2 | p indirection | semmle.label | p indirection | +| tests4.cpp:26:34:26:48 | XML_PARSE_NOENT | semmle.label | XML_PARSE_NOENT | +| tests4.cpp:36:34:36:50 | XML_PARSE_DTDLOAD | semmle.label | XML_PARSE_DTDLOAD | | tests4.cpp:46:34:46:68 | ... \| ... | semmle.label | ... \| ... | | tests4.cpp:77:34:77:38 | flags | semmle.label | flags | -| tests4.cpp:130:39:130:55 | (int)... | semmle.label | (int)... | -| tests5.cpp:27:25:27:38 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:29:2:29:2 | p | semmle.label | p | -| tests5.cpp:40:25:40:38 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:43:2:43:2 | p | semmle.label | p | -| tests5.cpp:55:25:55:38 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:59:2:59:2 | p | semmle.label | p | -| tests5.cpp:63:14:63:17 | g_p1 | semmle.label | g_p1 | -| tests5.cpp:63:21:63:24 | g_p2 | semmle.label | g_p2 | -| tests5.cpp:67:2:67:32 | Store | semmle.label | Store | -| tests5.cpp:67:17:67:30 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:70:2:70:32 | Store | semmle.label | Store | -| tests5.cpp:70:17:70:30 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:76:2:76:5 | g_p1 | semmle.label | g_p1 | -| tests5.cpp:77:2:77:5 | g_p2 | semmle.label | g_p2 | -| tests5.cpp:81:25:81:38 | call to createLSParser | semmle.label | call to createLSParser | -| tests5.cpp:83:2:83:2 | p | semmle.label | p | -| tests5.cpp:83:2:83:2 | p | semmle.label | p | -| tests5.cpp:85:2:85:2 | p | semmle.label | p | -| tests5.cpp:86:2:86:2 | p | semmle.label | p | -| tests5.cpp:88:2:88:2 | p | semmle.label | p | -| tests5.cpp:89:2:89:2 | p | semmle.label | p | -| tests.cpp:15:23:15:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:17:2:17:2 | p | semmle.label | p | -| tests.cpp:28:23:28:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:31:2:31:2 | p | semmle.label | p | -| tests.cpp:35:19:35:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] | -| tests.cpp:35:23:35:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:37:2:37:2 | p | semmle.label | p | -| tests.cpp:38:2:38:2 | p | semmle.label | p | -| tests.cpp:39:2:39:2 | p | semmle.label | p | -| tests.cpp:51:19:51:19 | VariableAddress [post update] | semmle.label | VariableAddress [post update] | -| tests.cpp:51:23:51:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:53:2:53:2 | p | semmle.label | p | -| tests.cpp:54:2:54:2 | p | semmle.label | p | -| tests.cpp:55:2:55:2 | p | semmle.label | p | -| tests.cpp:56:2:56:2 | p | semmle.label | p | -| tests.cpp:56:2:56:2 | p | semmle.label | p | -| tests.cpp:57:2:57:2 | p | semmle.label | p | -| tests.cpp:58:2:58:2 | p | semmle.label | p | -| tests.cpp:59:2:59:2 | p | semmle.label | p | -| tests.cpp:60:2:60:2 | p | semmle.label | p | -| tests.cpp:66:23:66:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:69:2:69:2 | p | semmle.label | p | -| tests.cpp:73:23:73:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:80:2:80:2 | p | semmle.label | p | -| tests.cpp:85:24:85:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:88:3:88:3 | q | semmle.label | q | -| tests.cpp:100:24:100:44 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:104:3:104:3 | q | semmle.label | q | -| tests.cpp:112:39:112:39 | p | semmle.label | p | -| tests.cpp:113:2:113:2 | p | semmle.label | p | -| tests.cpp:116:39:116:39 | p | semmle.label | p | -| tests.cpp:117:2:117:2 | p | semmle.label | p | -| tests.cpp:122:23:122:43 | XercesDOMParser output argument | semmle.label | XercesDOMParser output argument | -| tests.cpp:126:18:126:18 | q | semmle.label | q | -| tests.cpp:128:18:128:18 | q | semmle.label | q | +| tests4.cpp:130:39:130:55 | XML_PARSE_DTDLOAD | semmle.label | XML_PARSE_DTDLOAD | +| tests5.cpp:27:25:27:38 | call to createLSParser indirection | semmle.label | call to createLSParser indirection | +| tests5.cpp:29:2:29:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:29:2:29:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:40:25:40:38 | call to createLSParser indirection | semmle.label | call to createLSParser indirection | +| tests5.cpp:43:2:43:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:43:2:43:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:55:25:55:38 | call to createLSParser indirection | semmle.label | call to createLSParser indirection | +| tests5.cpp:59:2:59:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:59:2:59:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:63:21:63:24 | g_p2 indirection | semmle.label | g_p2 indirection | +| tests5.cpp:70:17:70:30 | call to createLSParser indirection | semmle.label | call to createLSParser indirection | +| tests5.cpp:77:2:77:5 | g_p2 indirection | semmle.label | g_p2 indirection | +| tests5.cpp:77:2:77:5 | g_p2 indirection | semmle.label | g_p2 indirection | +| tests5.cpp:81:25:81:38 | call to createLSParser indirection | semmle.label | call to createLSParser indirection | +| tests5.cpp:83:2:83:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:83:2:83:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:83:2:83:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:85:2:85:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:86:2:86:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:88:2:88:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:89:2:89:2 | p indirection | semmle.label | p indirection | +| tests5.cpp:89:2:89:2 | p indirection | semmle.label | p indirection | +| tests.cpp:15:23:15:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:17:2:17:2 | p indirection | semmle.label | p indirection | +| tests.cpp:28:23:28:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:31:2:31:2 | p indirection | semmle.label | p indirection | +| tests.cpp:35:23:35:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:35:23:35:43 | new indirection | semmle.label | new indirection | +| tests.cpp:37:2:37:2 | p indirection | semmle.label | p indirection | +| tests.cpp:37:2:37:2 | p indirection | semmle.label | p indirection | +| tests.cpp:38:2:38:2 | p indirection | semmle.label | p indirection | +| tests.cpp:39:2:39:2 | p indirection | semmle.label | p indirection | +| tests.cpp:51:23:51:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:51:23:51:43 | new indirection | semmle.label | new indirection | +| tests.cpp:53:2:53:2 | p indirection | semmle.label | p indirection | +| tests.cpp:54:2:54:2 | p indirection | semmle.label | p indirection | +| tests.cpp:55:2:55:2 | p indirection | semmle.label | p indirection | +| tests.cpp:56:2:56:2 | p indirection | semmle.label | p indirection | +| tests.cpp:56:2:56:2 | p indirection | semmle.label | p indirection | +| tests.cpp:57:2:57:2 | p indirection | semmle.label | p indirection | +| tests.cpp:58:2:58:2 | p indirection | semmle.label | p indirection | +| tests.cpp:59:2:59:2 | p indirection | semmle.label | p indirection | +| tests.cpp:60:2:60:2 | p indirection | semmle.label | p indirection | +| tests.cpp:66:23:66:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:69:2:69:2 | p indirection | semmle.label | p indirection | +| tests.cpp:73:23:73:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:80:2:80:2 | p indirection | semmle.label | p indirection | +| tests.cpp:85:24:85:44 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:88:3:88:3 | q indirection | semmle.label | q indirection | +| tests.cpp:100:24:100:44 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:104:3:104:3 | q indirection | semmle.label | q indirection | +| tests.cpp:112:39:112:39 | p indirection | semmle.label | p indirection | +| tests.cpp:113:2:113:2 | p indirection | semmle.label | p indirection | +| tests.cpp:116:39:116:39 | p indirection | semmle.label | p indirection | +| tests.cpp:117:2:117:2 | p indirection | semmle.label | p indirection | +| tests.cpp:122:23:122:43 | call to XercesDOMParser | semmle.label | call to XercesDOMParser | +| tests.cpp:126:18:126:18 | q indirection | semmle.label | q indirection | +| tests.cpp:128:18:128:18 | q indirection | semmle.label | q indirection | subpaths #select -| tests2.cpp:22:2:22:2 | p | tests2.cpp:20:17:20:31 | SAXParser output argument | tests2.cpp:22:2:22:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | SAXParser output argument | XML parser | -| tests2.cpp:37:2:37:2 | p | tests2.cpp:33:17:33:31 | SAXParser output argument | tests2.cpp:37:2:37:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | SAXParser output argument | XML parser | -| tests3.cpp:25:2:25:2 | p | tests3.cpp:23:21:23:53 | call to createXMLReader | tests3.cpp:25:2:25:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader | XML parser | -| tests3.cpp:38:2:38:6 | p_3_3 | tests3.cpp:35:24:35:56 | call to createXMLReader | tests3.cpp:38:2:38:6 | p_3_3 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:35:24:35:56 | call to createXMLReader | XML parser | -| tests3.cpp:45:2:45:6 | p_3_4 | tests3.cpp:41:24:41:56 | call to createXMLReader | tests3.cpp:45:2:45:6 | p_3_4 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:41:24:41:56 | call to createXMLReader | XML parser | -| tests3.cpp:56:2:56:6 | p_3_5 | tests3.cpp:48:24:48:56 | call to createXMLReader | tests3.cpp:56:2:56:6 | p_3_5 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:48:24:48:56 | call to createXMLReader | XML parser | -| tests3.cpp:63:2:63:2 | p | tests3.cpp:60:21:60:53 | call to createXMLReader | tests3.cpp:63:2:63:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader | XML parser | -| tests3.cpp:70:2:70:2 | p | tests3.cpp:67:21:67:53 | call to createXMLReader | tests3.cpp:70:2:70:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader | XML parser | -| tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | tests4.cpp:26:34:26:48 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:26:34:26:48 | (int)... | XML parser | -| tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | tests4.cpp:36:34:36:50 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:36:34:36:50 | (int)... | XML parser | +| tests2.cpp:22:2:22:2 | p indirection | tests2.cpp:20:17:20:31 | call to SAXParser | tests2.cpp:22:2:22:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | call to SAXParser | XML parser | +| tests2.cpp:22:2:22:2 | p indirection | tests2.cpp:20:17:20:31 | call to SAXParser | tests2.cpp:22:2:22:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:20:17:20:31 | call to SAXParser | XML parser | +| tests2.cpp:37:2:37:2 | p indirection | tests2.cpp:33:17:33:31 | call to SAXParser | tests2.cpp:37:2:37:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | call to SAXParser | XML parser | +| tests2.cpp:37:2:37:2 | p indirection | tests2.cpp:33:17:33:31 | call to SAXParser | tests2.cpp:37:2:37:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:33:17:33:31 | call to SAXParser | XML parser | +| tests2.cpp:51:2:51:2 | p indirection | tests2.cpp:49:12:49:12 | call to SAXParser | tests2.cpp:51:2:51:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests2.cpp:49:12:49:12 | call to SAXParser | XML parser | +| tests3.cpp:25:2:25:2 | p indirection | tests3.cpp:23:21:23:53 | call to createXMLReader indirection | tests3.cpp:25:2:25:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader indirection | XML parser | +| tests3.cpp:25:2:25:2 | p indirection | tests3.cpp:23:21:23:53 | call to createXMLReader indirection | tests3.cpp:25:2:25:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:23:21:23:53 | call to createXMLReader indirection | XML parser | +| tests3.cpp:38:2:38:6 | p_3_3 indirection | tests3.cpp:35:24:35:56 | call to createXMLReader indirection | tests3.cpp:38:2:38:6 | p_3_3 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:35:24:35:56 | call to createXMLReader indirection | XML parser | +| tests3.cpp:38:2:38:6 | p_3_3 indirection | tests3.cpp:35:24:35:56 | call to createXMLReader indirection | tests3.cpp:38:2:38:6 | p_3_3 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:35:24:35:56 | call to createXMLReader indirection | XML parser | +| tests3.cpp:56:2:56:6 | p_3_5 indirection | tests3.cpp:48:24:48:56 | call to createXMLReader indirection | tests3.cpp:56:2:56:6 | p_3_5 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:48:24:48:56 | call to createXMLReader indirection | XML parser | +| tests3.cpp:56:2:56:6 | p_3_5 indirection | tests3.cpp:48:24:48:56 | call to createXMLReader indirection | tests3.cpp:56:2:56:6 | p_3_5 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:48:24:48:56 | call to createXMLReader indirection | XML parser | +| tests3.cpp:63:2:63:2 | p indirection | tests3.cpp:60:21:60:53 | call to createXMLReader indirection | tests3.cpp:63:2:63:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader indirection | XML parser | +| tests3.cpp:63:2:63:2 | p indirection | tests3.cpp:60:21:60:53 | call to createXMLReader indirection | tests3.cpp:63:2:63:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:60:21:60:53 | call to createXMLReader indirection | XML parser | +| tests3.cpp:70:2:70:2 | p indirection | tests3.cpp:67:21:67:53 | call to createXMLReader indirection | tests3.cpp:70:2:70:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader indirection | XML parser | +| tests3.cpp:70:2:70:2 | p indirection | tests3.cpp:67:21:67:53 | call to createXMLReader indirection | tests3.cpp:70:2:70:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests3.cpp:67:21:67:53 | call to createXMLReader indirection | XML parser | +| tests4.cpp:26:34:26:48 | XML_PARSE_NOENT | tests4.cpp:26:34:26:48 | XML_PARSE_NOENT | tests4.cpp:26:34:26:48 | XML_PARSE_NOENT | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:26:34:26:48 | XML_PARSE_NOENT | XML parser | +| tests4.cpp:36:34:36:50 | XML_PARSE_DTDLOAD | tests4.cpp:36:34:36:50 | XML_PARSE_DTDLOAD | tests4.cpp:36:34:36:50 | XML_PARSE_DTDLOAD | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:36:34:36:50 | XML_PARSE_DTDLOAD | XML parser | | tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | tests4.cpp:46:34:46:68 | ... \| ... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:46:34:46:68 | ... \| ... | XML parser | | tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | tests4.cpp:77:34:77:38 | flags | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:77:34:77:38 | flags | XML parser | -| tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | tests4.cpp:130:39:130:55 | (int)... | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:130:39:130:55 | (int)... | XML parser | -| tests5.cpp:29:2:29:2 | p | tests5.cpp:27:25:27:38 | call to createLSParser | tests5.cpp:29:2:29:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:27:25:27:38 | call to createLSParser | XML parser | -| tests5.cpp:43:2:43:2 | p | tests5.cpp:40:25:40:38 | call to createLSParser | tests5.cpp:43:2:43:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:40:25:40:38 | call to createLSParser | XML parser | -| tests5.cpp:59:2:59:2 | p | tests5.cpp:55:25:55:38 | call to createLSParser | tests5.cpp:59:2:59:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:55:25:55:38 | call to createLSParser | XML parser | -| tests5.cpp:76:2:76:5 | g_p1 | tests5.cpp:67:17:67:30 | call to createLSParser | tests5.cpp:76:2:76:5 | g_p1 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:67:17:67:30 | call to createLSParser | XML parser | -| tests5.cpp:77:2:77:5 | g_p2 | tests5.cpp:70:17:70:30 | call to createLSParser | tests5.cpp:77:2:77:5 | g_p2 | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:70:17:70:30 | call to createLSParser | XML parser | -| tests5.cpp:83:2:83:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:83:2:83:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser | -| tests5.cpp:89:2:89:2 | p | tests5.cpp:81:25:81:38 | call to createLSParser | tests5.cpp:89:2:89:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser | XML parser | -| tests.cpp:17:2:17:2 | p | tests.cpp:15:23:15:43 | XercesDOMParser output argument | tests.cpp:17:2:17:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:15:23:15:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:31:2:31:2 | p | tests.cpp:28:23:28:43 | XercesDOMParser output argument | tests.cpp:31:2:31:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:28:23:28:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:39:2:39:2 | p | tests.cpp:35:23:35:43 | XercesDOMParser output argument | tests.cpp:39:2:39:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:35:23:35:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:56:2:56:2 | p | tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:56:2:56:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:60:2:60:2 | p | tests.cpp:51:23:51:43 | XercesDOMParser output argument | tests.cpp:60:2:60:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:69:2:69:2 | p | tests.cpp:66:23:66:43 | XercesDOMParser output argument | tests.cpp:69:2:69:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:66:23:66:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:80:2:80:2 | p | tests.cpp:73:23:73:43 | XercesDOMParser output argument | tests.cpp:80:2:80:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:73:23:73:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:88:3:88:3 | q | tests.cpp:85:24:85:44 | XercesDOMParser output argument | tests.cpp:88:3:88:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:85:24:85:44 | XercesDOMParser output argument | XML parser | -| tests.cpp:104:3:104:3 | q | tests.cpp:100:24:100:44 | XercesDOMParser output argument | tests.cpp:104:3:104:3 | q | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:100:24:100:44 | XercesDOMParser output argument | XML parser | -| tests.cpp:113:2:113:2 | p | tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:113:2:113:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | XercesDOMParser output argument | XML parser | -| tests.cpp:117:2:117:2 | p | tests.cpp:122:23:122:43 | XercesDOMParser output argument | tests.cpp:117:2:117:2 | p | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | XercesDOMParser output argument | XML parser | +| tests4.cpp:130:39:130:55 | XML_PARSE_DTDLOAD | tests4.cpp:130:39:130:55 | XML_PARSE_DTDLOAD | tests4.cpp:130:39:130:55 | XML_PARSE_DTDLOAD | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests4.cpp:130:39:130:55 | XML_PARSE_DTDLOAD | XML parser | +| tests5.cpp:29:2:29:2 | p indirection | tests5.cpp:27:25:27:38 | call to createLSParser indirection | tests5.cpp:29:2:29:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:27:25:27:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:29:2:29:2 | p indirection | tests5.cpp:27:25:27:38 | call to createLSParser indirection | tests5.cpp:29:2:29:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:27:25:27:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:43:2:43:2 | p indirection | tests5.cpp:40:25:40:38 | call to createLSParser indirection | tests5.cpp:43:2:43:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:40:25:40:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:43:2:43:2 | p indirection | tests5.cpp:40:25:40:38 | call to createLSParser indirection | tests5.cpp:43:2:43:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:40:25:40:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:59:2:59:2 | p indirection | tests5.cpp:55:25:55:38 | call to createLSParser indirection | tests5.cpp:59:2:59:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:55:25:55:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:59:2:59:2 | p indirection | tests5.cpp:55:25:55:38 | call to createLSParser indirection | tests5.cpp:59:2:59:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:55:25:55:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:77:2:77:5 | g_p2 indirection | tests5.cpp:70:17:70:30 | call to createLSParser indirection | tests5.cpp:77:2:77:5 | g_p2 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:70:17:70:30 | call to createLSParser indirection | XML parser | +| tests5.cpp:77:2:77:5 | g_p2 indirection | tests5.cpp:70:17:70:30 | call to createLSParser indirection | tests5.cpp:77:2:77:5 | g_p2 indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:70:17:70:30 | call to createLSParser indirection | XML parser | +| tests5.cpp:83:2:83:2 | p indirection | tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:83:2:83:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:83:2:83:2 | p indirection | tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:83:2:83:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:89:2:89:2 | p indirection | tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:89:2:89:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser indirection | XML parser | +| tests5.cpp:89:2:89:2 | p indirection | tests5.cpp:81:25:81:38 | call to createLSParser indirection | tests5.cpp:89:2:89:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests5.cpp:81:25:81:38 | call to createLSParser indirection | XML parser | +| tests.cpp:17:2:17:2 | p indirection | tests.cpp:15:23:15:43 | call to XercesDOMParser | tests.cpp:17:2:17:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:15:23:15:43 | call to XercesDOMParser | XML parser | +| tests.cpp:31:2:31:2 | p indirection | tests.cpp:28:23:28:43 | call to XercesDOMParser | tests.cpp:31:2:31:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:28:23:28:43 | call to XercesDOMParser | XML parser | +| tests.cpp:39:2:39:2 | p indirection | tests.cpp:35:23:35:43 | call to XercesDOMParser | tests.cpp:39:2:39:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:35:23:35:43 | call to XercesDOMParser | XML parser | +| tests.cpp:56:2:56:2 | p indirection | tests.cpp:51:23:51:43 | call to XercesDOMParser | tests.cpp:56:2:56:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | call to XercesDOMParser | XML parser | +| tests.cpp:60:2:60:2 | p indirection | tests.cpp:51:23:51:43 | call to XercesDOMParser | tests.cpp:60:2:60:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:51:23:51:43 | call to XercesDOMParser | XML parser | +| tests.cpp:69:2:69:2 | p indirection | tests.cpp:66:23:66:43 | call to XercesDOMParser | tests.cpp:69:2:69:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:66:23:66:43 | call to XercesDOMParser | XML parser | +| tests.cpp:80:2:80:2 | p indirection | tests.cpp:73:23:73:43 | call to XercesDOMParser | tests.cpp:80:2:80:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:73:23:73:43 | call to XercesDOMParser | XML parser | +| tests.cpp:88:3:88:3 | q indirection | tests.cpp:85:24:85:44 | call to XercesDOMParser | tests.cpp:88:3:88:3 | q indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:85:24:85:44 | call to XercesDOMParser | XML parser | +| tests.cpp:104:3:104:3 | q indirection | tests.cpp:100:24:100:44 | call to XercesDOMParser | tests.cpp:104:3:104:3 | q indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:100:24:100:44 | call to XercesDOMParser | XML parser | +| tests.cpp:113:2:113:2 | p indirection | tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:113:2:113:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | call to XercesDOMParser | XML parser | +| tests.cpp:117:2:117:2 | p indirection | tests.cpp:122:23:122:43 | call to XercesDOMParser | tests.cpp:117:2:117:2 | p indirection | This $@ is not configured to prevent an XML external entity (XXE) attack. | tests.cpp:122:23:122:43 | call to XercesDOMParser | XML parser | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp index 147be557844..8154536fd95 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests2.cpp @@ -44,3 +44,16 @@ void test2_4(InputSource &data) { p->setDisableDefaultEntityResolution(v); p->parse(data); // GOOD } + +void test2_5(InputSource &data) { + SAXParser p; + + p.parse(data); // BAD (parser not correctly configured) +} + +void test2_6(InputSource &data) { + SAXParser p; + + p.setDisableDefaultEntityResolution(true); + p.parse(data); // GOOD +} diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp index 8af560a8e6d..064eadac4fa 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests3.cpp @@ -22,7 +22,7 @@ public: void test3_1(InputSource &data) { SAX2XMLReader *p = XMLReaderFactory::createXMLReader(); - p->parse(data); // BAD (parser not correctly configured) [NOT DETECTED] + p->parse(data); // BAD (parser not correctly configured) } void test3_2(InputSource &data) { @@ -42,7 +42,7 @@ SAX2XMLReader *p_3_4 = XMLReaderFactory::createXMLReader(); void test3_4(InputSource &data) { p_3_4->setFeature(XMLUni::fgXercesDisableDefaultEntityResolution, true); - p_3_4->parse(data); // GOOD [FALSE POSITIVE] + p_3_4->parse(data); // GOOD } SAX2XMLReader *p_3_5 = XMLReaderFactory::createXMLReader(); diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp index 0d55be455da..063c47b025e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-611/tests5.cpp @@ -73,7 +73,7 @@ void test5_6_init() { void test5_6() { test5_6_init(); - g_p1->parse(*g_data); // GOOD [FALSE POSITIVE] + g_p1->parse(*g_data); // GOOD g_p2->parse(*g_data); // BAD (parser not correctly configured) } diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected index f0011ddbbd8..c2bd2653994 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected @@ -1,12 +1,12 @@ edges | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | -| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:10:24:35 | ! ... | -| test.cpp:20:29:20:47 | (const char *)... | test.cpp:24:11:24:16 | call to strcmp | +| test.cpp:20:29:20:47 | call to getenv | test.cpp:24:10:24:35 | ! ... | +| test.cpp:20:29:20:47 | call to getenv | test.cpp:24:11:24:16 | call to strcmp | subpaths nodes | test.cpp:20:29:20:34 | call to getenv | semmle.label | call to getenv | -| test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... | +| test.cpp:20:29:20:47 | call to getenv | semmle.label | call to getenv | | test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... | | test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | #select diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs index ec7c63a022d..9590e132229 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp.Tests/BuildScripts.cs @@ -1,5 +1,6 @@ using Xunit; using Semmle.Autobuild.Shared; +using Semmle.Util; using System.Collections.Generic; using System; using System.Linq; @@ -85,6 +86,15 @@ namespace Semmle.Autobuild.CSharp.Tests return ret; } + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? env, BuildOutputHandler onOutput, BuildOutputHandler onError) + { + var ret = (this as IBuildActions).RunProcess(cmd, args, workingDirectory, env, out var stdout); + + stdout.ForEach(line => onOutput(line)); + + return ret; + } + public IList DirectoryDeleteIn { get; } = new List(); void IBuildActions.DirectoryDelete(string dir, bool recursive) @@ -200,6 +210,16 @@ namespace Semmle.Autobuild.CSharp.Tests if (!DownloadFiles.Contains((address, fileName))) throw new ArgumentException($"Missing DownloadFile, {address}, {fileName}"); } + + + public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new TestDiagnosticWriter(); + } + + internal class TestDiagnosticWriter : IDiagnosticsWriter + { + public IList Diagnostics { get; } = new List(); + + public void AddEntry(DiagnosticMessage message) => this.Diagnostics.Add(message); } /// @@ -391,6 +411,7 @@ namespace Semmle.Autobuild.CSharp.Tests actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_TRAP_DIR"] = ""; actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_SOURCE_ARCHIVE_DIR"] = ""; actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_ROOT"] = $@"C:\codeql\{codeqlUpperLanguage.ToLowerInvariant()}"; + actions.GetEnvironmentVariable[$"CODEQL_EXTRACTOR_{codeqlUpperLanguage}_DIAGNOSTIC_DIR"] = ""; actions.GetEnvironmentVariable["CODEQL_JAVA_HOME"] = @"C:\codeql\tools\java"; actions.GetEnvironmentVariable["CODEQL_PLATFORM"] = isWindows ? "win64" : "linux64"; actions.GetEnvironmentVariable["LGTM_INDEX_VSTOOLS_VERSION"] = vsToolsVersion; diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs new file mode 100644 index 00000000000..cd138d62af5 --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/AutoBuildRule.cs @@ -0,0 +1,69 @@ +using Semmle.Autobuild.Shared; +using Semmle.Extraction.CSharp; + +namespace Semmle.Autobuild.CSharp +{ + internal class AutoBuildRule : IBuildRule + { + private readonly CSharpAutobuilder autobuilder; + + public DotNetRule DotNetRule { get; } + + public MsBuildRule MsBuildRule { get; } + + public BuildCommandAutoRule BuildCommandAutoRule { get; } + + public AutoBuildRule(CSharpAutobuilder autobuilder) + { + this.autobuilder = autobuilder; + this.DotNetRule = new DotNetRule(); + this.MsBuildRule = new MsBuildRule(); + this.BuildCommandAutoRule = new BuildCommandAutoRule(DotNetRule.WithDotNet); + } + + public BuildScript Analyse(IAutobuilder builder, bool auto) + { + var cleanTrapFolder = + BuildScript.DeleteDirectory(this.autobuilder.TrapDir); + var cleanSourceArchive = + BuildScript.DeleteDirectory(this.autobuilder.SourceArchiveDir); + var tryCleanExtractorArgsLogs = + BuildScript.Create(actions => + { + foreach (var file in Extractor.GetCSharpArgsLogs()) + { + try + { + actions.FileDelete(file); + } + catch // lgtm[cs/catch-of-all-exceptions] lgtm[cs/empty-catch-block] + { } + } + + return 0; + }); + var attemptExtractorCleanup = + BuildScript.Try(cleanTrapFolder) & + BuildScript.Try(cleanSourceArchive) & + tryCleanExtractorArgsLogs & + BuildScript.DeleteFile(Extractor.GetCSharpLogPath()); + + /// + /// Execute script `s` and check that the C# extractor has been executed. + /// If either fails, attempt to cleanup any artifacts produced by the extractor, + /// and exit with code 1, in order to proceed to the next attempt. + /// + BuildScript IntermediateAttempt(BuildScript s) => + (s & this.autobuilder.CheckExtractorRun(false)) | + (attemptExtractorCleanup & BuildScript.Failure); + + return + // First try .NET Core + IntermediateAttempt(this.DotNetRule.Analyse(this.autobuilder, true)) | + // Then MSBuild + (() => IntermediateAttempt(this.MsBuildRule.Analyse(this.autobuilder, true))) | + // And finally look for a script that might be a build script + (() => this.BuildCommandAutoRule.Analyse(this.autobuilder, true) & this.autobuilder.CheckExtractorRun(true)); + } + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs index 71891fa4e8b..92c615419cc 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpAutobuilder.cs @@ -1,6 +1,8 @@ using Semmle.Extraction.CSharp; using Semmle.Util.Logging; using Semmle.Autobuild.Shared; +using Semmle.Util; +using System.Linq; namespace Semmle.Autobuild.CSharp { @@ -29,25 +31,16 @@ namespace Semmle.Autobuild.CSharp public class CSharpAutobuilder : Autobuilder { - public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options) { } + private const string buildCommandDocsUrl = + "https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages"; + + private readonly AutoBuildRule autoBuildRule; + + public CSharpAutobuilder(IBuildActions actions, CSharpAutobuildOptions options) : base(actions, options, new CSharpDiagnosticClassifier()) => + this.autoBuildRule = new AutoBuildRule(this); public override BuildScript GetBuildScript() { - /// - /// A script that checks that the C# extractor has been executed. - /// - BuildScript CheckExtractorRun(bool warnOnFailure) => - BuildScript.Create(actions => - { - if (actions.FileExists(Extractor.GetCSharpLogPath())) - return 0; - - if (warnOnFailure) - Log(Severity.Error, "No C# code detected during build."); - - return 1; - }); - var attempt = BuildScript.Failure; switch (GetCSharpBuildStrategy()) { @@ -65,47 +58,9 @@ namespace Semmle.Autobuild.CSharp attempt = new DotNetRule().Analyse(this, false) & CheckExtractorRun(true); break; case CSharpBuildStrategy.Auto: - var cleanTrapFolder = - BuildScript.DeleteDirectory(TrapDir); - var cleanSourceArchive = - BuildScript.DeleteDirectory(SourceArchiveDir); - var tryCleanExtractorArgsLogs = - BuildScript.Create(actions => - { - foreach (var file in Extractor.GetCSharpArgsLogs()) - { - try - { - actions.FileDelete(file); - } - catch // lgtm[cs/catch-of-all-exceptions] lgtm[cs/empty-catch-block] - { } - } - - return 0; - }); - var attemptExtractorCleanup = - BuildScript.Try(cleanTrapFolder) & - BuildScript.Try(cleanSourceArchive) & - tryCleanExtractorArgsLogs & - BuildScript.DeleteFile(Extractor.GetCSharpLogPath()); - - /// - /// Execute script `s` and check that the C# extractor has been executed. - /// If either fails, attempt to cleanup any artifacts produced by the extractor, - /// and exit with code 1, in order to proceed to the next attempt. - /// - BuildScript IntermediateAttempt(BuildScript s) => - (s & CheckExtractorRun(false)) | - (attemptExtractorCleanup & BuildScript.Failure); - attempt = - // First try .NET Core - IntermediateAttempt(new DotNetRule().Analyse(this, true)) | - // Then MSBuild - (() => IntermediateAttempt(new MsBuildRule().Analyse(this, true))) | - // And finally look for a script that might be a build script - (() => new BuildCommandAutoRule(DotNetRule.WithDotNet).Analyse(this, true) & CheckExtractorRun(true)) | + // Attempt a few different build strategies to see if one works + this.autoBuildRule.Analyse(this, true) | // All attempts failed: print message AutobuildFailure(); break; @@ -114,6 +69,127 @@ namespace Semmle.Autobuild.CSharp return attempt; } + /// + /// A script that checks that the C# extractor has been executed. + /// + public BuildScript CheckExtractorRun(bool warnOnFailure) => + BuildScript.Create(actions => + { + if (actions.FileExists(Extractor.GetCSharpLogPath())) + return 0; + + if (warnOnFailure) + Log(Severity.Error, "No C# code detected during build."); + + return 1; + }); + + protected override void AutobuildFailureDiagnostic() + { + // if `ScriptPath` is not null here, the `BuildCommandAuto` rule was + // run and found at least one script to execute + if (this.autoBuildRule.BuildCommandAutoRule.ScriptPath is not null) + { + var relScriptPath = this.MakeRelative(autoBuildRule.BuildCommandAutoRule.ScriptPath); + + // if we found multiple build scripts in the project directory, then we can say + // as much to indicate that we may have picked the wrong one; + // otherwise, we just report that the one script we found didn't work + DiagnosticMessage message = + this.autoBuildRule.BuildCommandAutoRule.CandidatePaths.Count() > 1 ? + new( + this.Options.Language, + "multiple-build-scripts", + "There are multiple potential build scripts", + markdownMessage: + "CodeQL found multiple potential build scripts for your project and " + + $"attempted to run `{relScriptPath}`, which failed. " + + "This may not be the right build script for your project.\n\n" + + $"Set up a [manual build command]({buildCommandDocsUrl})." + ) : + new( + this.Options.Language, + "script-failure", + "Unable to build project using build script", + markdownMessage: + "CodeQL attempted to build your project using a script located at " + + $"`{relScriptPath}`, which failed.\n\n" + + $"Set up a [manual build command]({buildCommandDocsUrl})." + ); + + AddDiagnostic(message); + } + + // project files which don't exist get marked as not .NET core projects, but we don't want + // to show an error for this if the files don't exist + var foundNotDotNetProjects = autoBuildRule.DotNetRule.NotDotNetProjects.Where( + proj => this.Actions.FileExists(proj.FullPath) + ); + + // both dotnet and msbuild builds require project or solution files; if we haven't found any + // then neither of those rules would've worked + if (this.ProjectsOrSolutionsToBuild.Count == 0) + { + this.AddDiagnostic(new( + this.Options.Language, + "no-projects-or-solutions", + "No project or solutions files found", + markdownMessage: + "CodeQL could not find any project or solution files in your repository.\n\n" + + $"Set up a [manual build command]({buildCommandDocsUrl})." + )); + } + // show a warning if there are projects which are not compatible with .NET Core, in case that is unintentional + else if (foundNotDotNetProjects.Any()) + { + this.AddDiagnostic(new( + this.Options.Language, + "dotnet-incompatible-projects", + "Some projects are incompatible with .NET Core", + severity: DiagnosticMessage.TspSeverity.Warning, + markdownMessage: $""" + CodeQL found some projects which cannot be built with .NET Core: + + {autoBuildRule.DotNetRule.NotDotNetProjects.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 5)} + """ + )); + } + + // report any projects that failed to build with .NET Core + if (autoBuildRule.DotNetRule.FailedProjectsOrSolutions.Any()) + { + this.AddDiagnostic(new( + this.Options.Language, + "dotnet-build-failure", + "Some projects or solutions failed to build using .NET Core", + markdownMessage: $""" + CodeQL was unable to build the following projects using .NET Core: + + {autoBuildRule.DotNetRule.FailedProjectsOrSolutions.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 10)} + + Set up a [manual build command]({buildCommandDocsUrl}). + """ + )); + } + + // report any projects that failed to build with MSBuild + if (autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.Any()) + { + this.AddDiagnostic(new( + this.Options.Language, + "msbuild-build-failure", + "Some projects or solutions failed to build using MSBuild", + markdownMessage: $""" + CodeQL was unable to build the following projects using MSBuild: + + {autoBuildRule.MsBuildRule.FailedProjectsOrSolutions.Select(p => this.MakeRelative(p.FullPath)).ToMarkdownList(MarkdownUtil.CodeFormatter, 10)} + + Set up a [manual build command]({buildCommandDocsUrl}). + """ + )); + } + } + /// /// Gets the build strategy that the autobuilder should apply, based on the /// options in the `lgtm.yml` file. diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs new file mode 100644 index 00000000000..821ad3222e1 --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/CSharpDiagnosticClassifier.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Semmle.Autobuild.Shared; +using Semmle.Util; + +namespace Semmle.Autobuild.CSharp +{ + /// + /// A diagnostic rule which tries to identify missing Xamarin SDKs. + /// + public class MissingXamarinSdkRule : DiagnosticRule + { + private const string docsUrl = "https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-xamarin-applications"; + + public class Result : IDiagnosticsResult + { + /// + /// The name of the SDK that is missing. + /// + public string SDKName { get; } + + public Result(string sdkName) + { + this.SDKName = sdkName; + } + + public DiagnosticMessage ToDiagnosticMessage(Autobuilder builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared => new( + builder.Options.Language, + $"missing-xamarin-{this.SDKName.ToLower()}-sdk", + $"Missing Xamarin SDK for {this.SDKName}", + severity: severity ?? DiagnosticMessage.TspSeverity.Error, + markdownMessage: $"[Configure your workflow]({docsUrl}) for this SDK before running CodeQL." + ); + } + + public MissingXamarinSdkRule() : + base("MSB4019:[^\"]*\"[^\"]*Xamarin\\.(?[^\\.]*)\\.CSharp\\.targets\"") + { + } + + public override void Fire(DiagnosticClassifier classifier, Match match) + { + if (!match.Groups.TryGetValue("sdkName", out var sdkName)) + throw new ArgumentException("Expected regular expression match to contain sdkName"); + + var xamarinResults = classifier.Results.OfType().Where(result => + result.SDKName.Equals(sdkName.Value) + ); + + if (!xamarinResults.Any()) + classifier.Results.Add(new Result(sdkName.Value)); + } + } + + public class MissingProjectFileRule : DiagnosticRule + { + private const string runsOnDocsUrl = "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on"; + private const string checkoutDocsUrl = "https://github.com/actions/checkout#usage"; + + public class Result : IDiagnosticsResult + { + /// + /// A set of missing project files. + /// + public HashSet MissingProjectFiles { get; } + + public Result() + { + this.MissingProjectFiles = new HashSet(); + } + + public DiagnosticMessage ToDiagnosticMessage(Autobuilder builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared => new( + builder.Options.Language, + "missing-project-files", + "Missing project files", + severity: severity ?? DiagnosticMessage.TspSeverity.Warning, + markdownMessage: $""" + Some project files were not found when CodeQL built your project: + + {this.MissingProjectFiles.AsEnumerable().Select(p => builder.MakeRelative(p)).ToMarkdownList(MarkdownUtil.CodeFormatter, 5)} + + This may lead to subsequent failures. You can check for common causes for missing project files: + + - Ensure that the project is built using the {runsOnDocsUrl.ToMarkdownLink("intended operating system")} and that filenames on case-sensitive platforms are correctly specified. + - If your repository uses Git submodules, ensure that those are {checkoutDocsUrl.ToMarkdownLink("checked out")} before the CodeQL Action is run. + - If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL Action is run. + """ + ); + } + + public MissingProjectFileRule() : + base("MSB3202: The project file \"(?[^\"]+)\" was not found. \\[(?[^\\]]+)\\]") + { + } + + public override void Fire(DiagnosticClassifier classifier, Match match) + { + if (!match.Groups.TryGetValue("projectFile", out var projectFile)) + throw new ArgumentException("Expected regular expression match to contain projectFile"); + if (!match.Groups.TryGetValue("location", out var location)) + throw new ArgumentException("Expected regular expression match to contain location"); + + var result = classifier.Results.OfType().FirstOrDefault(); + + // if we do not yet have a result for this rule, create one and add it to the list + // of results the classifier knows about + if (result is null) + { + result = new Result(); + classifier.Results.Add(result); + } + + // then add the missing project file + result.MissingProjectFiles.Add(projectFile.Value); + } + } + + /// + /// Implements a which applies C#-specific rules to + /// the build output. + /// + public class CSharpDiagnosticClassifier : DiagnosticClassifier + { + public CSharpDiagnosticClassifier() + { + // add C#-specific rules to this classifier + this.AddRule(new MissingXamarinSdkRule()); + this.AddRule(new MissingProjectFileRule()); + } + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs index 394349e2a40..e18058339f5 100644 --- a/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.CSharp/DotNetRule.cs @@ -15,6 +15,15 @@ namespace Semmle.Autobuild.CSharp /// internal class DotNetRule : IBuildRule { + public readonly List FailedProjectsOrSolutions = new(); + + /// + /// A list of projects which are incompatible with DotNet. + /// + public IEnumerable> NotDotNetProjects { get; private set; } + + public DotNetRule() => NotDotNetProjects = new List>(); + public BuildScript Analyse(IAutobuilder builder, bool auto) { if (!builder.ProjectsOrSolutionsToBuild.Any()) @@ -22,10 +31,12 @@ namespace Semmle.Autobuild.CSharp if (auto) { - var notDotNetProject = builder.ProjectsOrSolutionsToBuild + NotDotNetProjects = builder.ProjectsOrSolutionsToBuild .SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)) .OfType>() - .FirstOrDefault(p => !p.DotNetProject); + .Where(p => !p.DotNetProject); + var notDotNetProject = NotDotNetProjects.FirstOrDefault(); + if (notDotNetProject is not null) { builder.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject); @@ -50,7 +61,10 @@ namespace Semmle.Autobuild.CSharp var build = GetBuildScript(builder, dotNetPath, environment, projectOrSolution.FullPath); - ret &= BuildScript.Try(clean) & BuildScript.Try(restore) & build; + ret &= BuildScript.Try(clean) & BuildScript.Try(restore) & BuildScript.OnFailure(build, ret => + { + FailedProjectsOrSolutions.Add(projectOrSolution); + }); } return ret; }); diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/AutobuildOptions.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/AutobuildOptions.cs index d51612272d0..8a02370bcf6 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/AutobuildOptions.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/AutobuildOptions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; +using Semmle.Util; namespace Semmle.Autobuild.Shared { diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs index 1ef5ebd815d..29d60331d5d 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/Autobuilder.cs @@ -1,3 +1,4 @@ +using Semmle.Util; using Semmle.Util.Logging; using System; using System.Collections.Generic; @@ -189,10 +190,11 @@ namespace Semmle.Autobuild.Shared /// solution file and tools. /// /// The command line options. - protected Autobuilder(IBuildActions actions, TAutobuildOptions options) + protected Autobuilder(IBuildActions actions, TAutobuildOptions options, DiagnosticClassifier diagnosticClassifier) { Actions = actions; Options = options; + DiagnosticClassifier = diagnosticClassifier; pathsLazy = new Lazy>(() => { @@ -232,24 +234,53 @@ namespace Semmle.Autobuild.Shared return ret ?? new List(); }); - CodeQLExtractorLangRoot = Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_ROOT"); - CodeQlPlatform = Actions.GetEnvironmentVariable("CODEQL_PLATFORM"); + CodeQLExtractorLangRoot = Actions.GetEnvironmentVariable(EnvVars.Root(this.Options.Language)); + CodeQlPlatform = Actions.GetEnvironmentVariable(EnvVars.Platform); - TrapDir = - Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_TRAP_DIR") ?? - throw new InvalidEnvironmentException($"The environment variable CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_TRAP_DIR has not been set."); + TrapDir = RequireEnvironmentVariable(EnvVars.TrapDir(this.Options.Language)); + SourceArchiveDir = RequireEnvironmentVariable(EnvVars.SourceArchiveDir(this.Options.Language)); + DiagnosticsDir = RequireEnvironmentVariable(EnvVars.DiagnosticDir(this.Options.Language)); - SourceArchiveDir = - Actions.GetEnvironmentVariable($"CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_SOURCE_ARCHIVE_DIR") ?? - throw new InvalidEnvironmentException($"The environment variable CODEQL_EXTRACTOR_{this.Options.Language.UpperCaseName}_SOURCE_ARCHIVE_DIR has not been set."); + this.diagnostics = actions.CreateDiagnosticsWriter(Path.Combine(DiagnosticsDir, $"autobuilder-{DateTime.UtcNow:yyyyMMddHHmm}-{Environment.ProcessId}.jsonc")); } - protected string TrapDir { get; } + /// + /// Retrieves the value of an environment variable named or throws + /// an exception if no such environment variable has been set. + /// + /// The name of the environment variable. + /// The value of the environment variable. + /// + /// Thrown if the environment variable is not set. + /// + protected string RequireEnvironmentVariable(string name) + { + return Actions.GetEnvironmentVariable(name) ?? + throw new InvalidEnvironmentException($"The environment variable {name} has not been set."); + } - protected string SourceArchiveDir { get; } + public string TrapDir { get; } + + public string SourceArchiveDir { get; } + + public string DiagnosticsDir { get; } + + protected DiagnosticClassifier DiagnosticClassifier { get; } private readonly ILogger logger = new ConsoleLogger(Verbosity.Info); + private readonly IDiagnosticsWriter diagnostics; + + /// + /// Makes relative to the root source directory. + /// + /// The path which to make relative. + /// The relative path. + public string MakeRelative(string path) + { + return Path.GetRelativePath(this.RootDirectory, path); + } + /// /// Log a given build event to the console. /// @@ -260,6 +291,15 @@ namespace Semmle.Autobuild.Shared logger.Log(severity, format, args); } + /// + /// Write to the diagnostics file. + /// + /// The diagnostics entry to write. + public void AddDiagnostic(DiagnosticMessage diagnostic) + { + diagnostics.AddEntry(diagnostic); + } + /// /// Attempt to build this project. /// @@ -283,7 +323,19 @@ namespace Semmle.Autobuild.Shared Log(silent ? Severity.Debug : Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}"); } - return script.Run(Actions, startCallback, exitCallback); + var onOutput = BuildOutputHandler(Console.Out); + var onError = BuildOutputHandler(Console.Error); + + var buildResult = script.Run(Actions, startCallback, exitCallback, onOutput, onError); + + // if the build succeeded, all diagnostics we captured from the build output should be warnings; + // otherwise they should all be errors + var diagSeverity = buildResult == 0 ? DiagnosticMessage.TspSeverity.Warning : DiagnosticMessage.TspSeverity.Error; + this.DiagnosticClassifier.Results + .Select(result => result.ToDiagnosticMessage(this, diagSeverity)) + .ForEach(AddDiagnostic); + + return buildResult; } /// @@ -291,13 +343,58 @@ namespace Semmle.Autobuild.Shared /// public abstract BuildScript GetBuildScript(); + + /// + /// Produces a diagnostic for the tool status page that we were unable to automatically + /// build the user's project and that they can manually specify a build command. This + /// can be overriden to implement more specific messages depending on the origin of + /// the failure. + /// + protected virtual void AutobuildFailureDiagnostic() => AddDiagnostic(new DiagnosticMessage( + this.Options.Language, + "autobuild-failure", + "Unable to build project", + visibility: new DiagnosticMessage.TspVisibility(statusPage: true), + plaintextMessage: """ + We were unable to automatically build your project. + Set up a manual build command. + """ + )); + + /// + /// Returns a build script that can be run upon autobuild failure. + /// + /// + /// A build script that reports that we could not automatically detect a suitable build method. + /// protected BuildScript AutobuildFailure() => BuildScript.Create(actions => { Log(Severity.Error, "Could not auto-detect a suitable build method"); + + AutobuildFailureDiagnostic(); + return 1; }); + /// + /// Constructs a which uses the + /// to classify build output. All data also gets written to . + /// + /// + /// The to which the build output would have normally been written to. + /// This is normally or . + /// + /// The constructed . + protected BuildOutputHandler BuildOutputHandler(TextWriter writer) => new(data => + { + if (data is not null) + { + writer.WriteLine(data); + DiagnosticClassifier.ClassifyLine(data); + } + }); + /// /// Value of CODEQL_EXTRACTOR__ROOT environment variable. /// diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs index f3f9ae15da6..46c32ecbd72 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildActions.cs @@ -11,11 +11,26 @@ using System.Runtime.InteropServices; namespace Semmle.Autobuild.Shared { + public delegate void BuildOutputHandler(string? data); + /// /// Wrapper around system calls so that the build scripts can be unit-tested. /// public interface IBuildActions { + + /// + /// Runs a process, captures its output, and provides it asynchronously. + /// + /// The exe to run. + /// The other command line arguments. + /// The working directory (null for current directory). + /// Additional environment variables. + /// A handler for stdout output. + /// A handler for stderr output. + /// The process exit code. + int RunProcess(string exe, string args, string? workingDirectory, IDictionary? env, BuildOutputHandler onOutput, BuildOutputHandler onError); + /// /// Runs a process and captures its output. /// @@ -152,6 +167,17 @@ namespace Semmle.Autobuild.Shared /// Downloads the resource with the specified URI to a local file. /// void DownloadFile(string address, string fileName); + + /// + /// Creates an for the given . + /// + /// + /// The path suggesting where the diagnostics should be written to. + /// + /// + /// A to which diagnostic entries can be added. + /// + IDiagnosticsWriter CreateDiagnosticsWriter(string filename); } /// @@ -173,15 +199,31 @@ namespace Semmle.Autobuild.Shared if (workingDirectory is not null) pi.WorkingDirectory = workingDirectory; - // Environment variables can only be used when not redirecting stdout - if (!redirectStandardOutput) - { - if (environment is not null) - environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value); - } + environment?.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value); + return pi; } + int IBuildActions.RunProcess(string exe, string args, string? workingDirectory, System.Collections.Generic.IDictionary? env, BuildOutputHandler onOutput, BuildOutputHandler onError) + { + var pi = GetProcessStartInfo(exe, args, workingDirectory, env, true); + using var p = new Process + { + StartInfo = pi + }; + p.StartInfo.RedirectStandardError = true; + p.OutputDataReceived += new DataReceivedEventHandler((sender, e) => onOutput(e.Data)); + p.ErrorDataReceived += new DataReceivedEventHandler((sender, e) => onError(e.Data)); + + p.Start(); + + p.BeginErrorReadLine(); + p.BeginOutputReadLine(); + + p.WaitForExit(); + return p.ExitCode; + } + int IBuildActions.RunProcess(string cmd, string args, string? workingDirectory, IDictionary? environment) { var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false); @@ -253,6 +295,8 @@ namespace Semmle.Autobuild.Shared public void DownloadFile(string address, string fileName) => DownloadFileAsync(address, fileName).Wait(); + public IDiagnosticsWriter CreateDiagnosticsWriter(string filename) => new DiagnosticsStream(filename); + public static IBuildActions Instance { get; } = new SystemBuildActions(); } } diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildCommandAutoRule.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildCommandAutoRule.cs index 0d44f0dad4d..c0990a75ae1 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildCommandAutoRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildCommandAutoRule.cs @@ -11,22 +11,42 @@ namespace Semmle.Autobuild.Shared { private readonly WithDotNet withDotNet; + /// + /// A list of paths to files in the project directory which we classified as scripts. + /// + public IEnumerable CandidatePaths { get; private set; } + + /// + /// The path of the script we decided to run, if any. + /// + public string? ScriptPath { get; private set; } + public BuildCommandAutoRule(WithDotNet withDotNet) { this.withDotNet = withDotNet; + this.CandidatePaths = new List(); } + /// + /// A list of extensions that we consider to be for scripts on Windows. + /// private readonly IEnumerable winExtensions = new List { ".bat", ".cmd", ".exe" }; + /// + /// A list of extensions that we consider to be for scripts on Linux. + /// private readonly IEnumerable linuxExtensions = new List { "", ".sh" }; + /// + /// A list of filenames without extensions that we think might be build scripts. + /// private readonly IEnumerable buildScripts = new List { "build" }; @@ -35,18 +55,25 @@ namespace Semmle.Autobuild.Shared { builder.Log(Severity.Info, "Attempting to locate build script"); + // a list of extensions for files that we consider to be scripts on the current platform var extensions = builder.Actions.IsWindows() ? winExtensions : linuxExtensions; + // a list of combined base script names with the current platform's script extensions + // e.g. for Linux: build, build.sh var scripts = buildScripts.SelectMany(s => extensions.Select(e => s + e)); - var scriptPath = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1).FirstOrDefault(); + // search through the files in the project directory for paths which end in one of + // the names given by `scripts`, then order them by their distance from the root + this.CandidatePaths = builder.Paths.Where(p => scripts.Any(p.Item1.ToLower().EndsWith)).OrderBy(p => p.Item2).Select(p => p.Item1); + // pick the first matching path, if there is one + this.ScriptPath = this.CandidatePaths.FirstOrDefault(); - if (scriptPath is null) + if (this.ScriptPath is null) return BuildScript.Failure; var chmod = new CommandBuilder(builder.Actions); - chmod.RunCommand("/bin/chmod", $"u+x {scriptPath}"); + chmod.RunCommand("/bin/chmod", $"u+x {this.ScriptPath}"); var chmodScript = builder.Actions.IsWindows() ? BuildScript.Success : BuildScript.Try(chmod.Script); - var dir = builder.Actions.GetDirectoryName(scriptPath); + var dir = builder.Actions.GetDirectoryName(this.ScriptPath); // A specific .NET Core version may be required return chmodScript & withDotNet(builder, environment => @@ -58,7 +85,7 @@ namespace Semmle.Autobuild.Shared if (vsTools is not null) command.CallBatFile(vsTools.Path); - command.RunCommand(scriptPath); + command.RunCommand(this.ScriptPath); return command.Script; }); } diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildScript.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildScript.cs index 9840d63c5e4..573c6f3043b 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/BuildScript.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/BuildScript.cs @@ -46,6 +46,33 @@ namespace Semmle.Autobuild.Shared /// The exit code from this build script. public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout); + /// + /// Runs this build command. + /// + /// + /// The interface used to implement the build actions. + /// + /// + /// A call back that is called every time a new process is started. The + /// argument to the call back is a textual representation of the process. + /// + /// + /// A call back that is called every time a new process exits. The first + /// argument to the call back is the exit code, and the second argument is + /// an exit message. + /// + /// + /// A handler for data read from stdout. + /// + /// + /// A handler for data read from stderr. + /// + /// The exit code from this build script. + public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError); + + /// + /// A build script which executes an external program or script. + /// private class BuildCommand : BuildScript { private readonly string exe, arguments; @@ -110,8 +137,29 @@ namespace Semmle.Autobuild.Shared return ret; } + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError) + { + startCallback(this.ToString(), silent); + var ret = 1; + var retMessage = ""; + try + { + ret = actions.RunProcess(exe, arguments, workingDirectory, environment, onOutput, onError); + } + catch (Exception ex) + when (ex is System.ComponentModel.Win32Exception || ex is FileNotFoundException) + { + retMessage = ex.Message; + } + exitCallBack(ret, retMessage, silent); + return ret; + } + } + /// + /// A build script which runs a C# function. + /// private class ReturnBuildCommand : BuildScript { private readonly Func func; @@ -127,8 +175,13 @@ namespace Semmle.Autobuild.Shared stdout = Array.Empty(); return func(actions); } + + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError) => func(actions); } + /// + /// Allows two build scripts to be composed sequentially. + /// private class BindBuildScript : BuildScript { private readonly BuildScript s1; @@ -175,6 +228,32 @@ namespace Semmle.Autobuild.Shared stdout = @out; return ret2; } + + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, BuildOutputHandler onOutput, BuildOutputHandler onError) + { + int ret1; + if (s2a is not null) + { + var stdout1 = new List(); + var onOutputWrapper = new BuildOutputHandler(data => + { + if (data is not null) + stdout1.Add(data); + + onOutput(data); + }); + ret1 = s1.Run(actions, startCallback, exitCallBack, onOutputWrapper, onError); + return s2a(stdout1, ret1).Run(actions, startCallback, exitCallBack, onOutput, onError); + } + + if (s2b is not null) + { + ret1 = s1.Run(actions, startCallback, exitCallBack, onOutput, onError); + return s2b(ret1).Run(actions, startCallback, exitCallBack, onOutput, onError); + } + + throw new InvalidOperationException("Unexpected error"); + } } /// @@ -260,6 +339,23 @@ namespace Semmle.Autobuild.Shared /// public static BuildScript Try(BuildScript s) => s | Success; + /// + /// Creates a build script that runs the build script . If + /// running fails, is invoked with + /// the exit code. + /// + /// The build script to run. + /// + /// The callback that is invoked if failed. + /// + /// The build script which implements this. + public static BuildScript OnFailure(BuildScript s, Action k) => + new BindBuildScript(s, ret => Create(actions => + { + if (!Succeeded(ret)) k(ret); + return ret; + })); + /// /// Creates a build script that deletes the given directory. /// diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/DiagnosticClassifier.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/DiagnosticClassifier.cs new file mode 100644 index 00000000000..94af39ca959 --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/DiagnosticClassifier.cs @@ -0,0 +1,96 @@ +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Semmle.Util; + +namespace Semmle.Autobuild.Shared +{ + /// + /// Direct results result from the successful application of a , + /// which can later be converted to a corresponding . + /// + public interface IDiagnosticsResult + { + /// + /// Produces a corresponding to this result. + /// + /// + /// The autobuilder to use for constructing the base . + /// + /// + /// An optional severity value which overrides the default severity of the diagnostic. + /// + /// The corresponding to this result. + DiagnosticMessage ToDiagnosticMessage(Autobuilder builder, DiagnosticMessage.TspSeverity? severity = null) where T : AutobuildOptionsShared; + } + + public class DiagnosticRule + { + /// + /// The pattern against which this rule matches build output. + /// + public Regex Pattern { get; } + + /// + /// Constructs a diagnostic rule for the given . + /// + /// + public DiagnosticRule(Regex pattern) + { + this.Pattern = pattern; + } + + /// + /// Constructs a diagnostic rule for the given regular expression . + /// + /// + public DiagnosticRule(string pattern) + { + this.Pattern = new Regex(pattern, RegexOptions.Compiled); + } + + /// + /// Used by a to + /// signal that the rule has matched some build output with . + /// + /// The classifier which is firing the rule. + /// The that resulted from applying the rule. + public virtual void Fire(DiagnosticClassifier classifier, Match match) { } + } + + public class DiagnosticClassifier + { + private readonly List rules; + public readonly List Results; + + public DiagnosticClassifier() + { + this.rules = new List(); + this.Results = new List(); + } + + /// + /// Adds to this classifier. + /// + /// The rule to add. + protected void AddRule(DiagnosticRule rule) + { + this.rules.Add(rule); + } + + /// + /// Applies all of this classifier's rules to to see which match. + /// + /// The line to which the rules should be applied to. + public void ClassifyLine(string line) + { + this.rules.ForEach(rule => + { + var match = rule.Pattern.Match(line); + if (match.Success) + { + rule.Fire(this, match); + } + }); + } + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/EnvVars.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/EnvVars.cs new file mode 100644 index 00000000000..5d1197f0a9e --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/EnvVars.cs @@ -0,0 +1,13 @@ +using Semmle.Util; + +namespace Semmle.Autobuild.Shared +{ + public static class EnvVars + { + public const string Platform = "CODEQL_PLATFORM"; + public static string Root(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_ROOT"; + public static string TrapDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_TRAP_DIR"; + public static string SourceArchiveDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_SOURCE_ARCHIVE_DIR"; + public static string DiagnosticDir(Language language) => $"CODEQL_EXTRACTOR_{language.UpperCaseName}_DIAGNOSTIC_DIR"; + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs new file mode 100644 index 00000000000..13a3533eb31 --- /dev/null +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/MarkdownUtil.cs @@ -0,0 +1,65 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Semmle.Autobuild.Shared +{ + public static class MarkdownUtil + { + /// + /// Formats items as markdown inline code. + /// + /// A function which formats items as markdown inline code. + public static readonly Func CodeFormatter = item => $"`{item}`"; + + /// + /// Formats the string as a markdown link. + /// + /// The URL for the link. + /// The text that is displayed. + /// A string containing a markdown-formatted link. + public static string ToMarkdownLink(this string link, string title) => $"[{title}]({link})"; + + /// + /// Renders as a markdown list of the project paths. + /// + /// + /// The list of projects whose paths should be rendered as a markdown list. + /// + /// The maximum number of items to include in the list. + /// Returns the markdown list as a string. + public static string ToMarkdownList(this IEnumerable projects, int? limit = null) + { + return projects.ToMarkdownList(p => $"`{p.FullPath}`", limit); + } + + /// + /// Renders as a markdown list. + /// + /// The item type. + /// The list that should be formatted as a markdown list. + /// A function which converts individual items into a string representation. + /// The maximum number of items to include in the list. + /// Returns the markdown list as a string. + public static string ToMarkdownList(this IEnumerable items, Func formatter, int? limit = null) + { + var sb = new StringBuilder(); + + // if there is a limit, take at most that many items from the start of the list + var list = limit is not null ? items.Take(limit.Value) : items; + sb.Append(string.Join('\n', list.Select(item => $"- {formatter(item)}"))); + + // if there were more items than allowed in the list, add an extra item indicating + // how many more items there were + var length = items.Count(); + + if (limit is not null && length > limit) + { + sb.Append($"\n- and {length - limit} more. View the CodeQL logs for a full list."); + } + + return sb.ToString(); + } + } +} diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs index 56858cc87a2..e0e4404f312 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/MsBuildRule.cs @@ -1,7 +1,6 @@ using Semmle.Util.Logging; -using System; +using System.Collections.Generic; using System.Linq; -using System.Runtime.InteropServices; namespace Semmle.Autobuild.Shared { @@ -31,6 +30,11 @@ namespace Semmle.Autobuild.Shared /// public class MsBuildRule : IBuildRule { + /// + /// A list of solutions or projects which failed to build. + /// + public readonly List FailedProjectsOrSolutions = new(); + public BuildScript Analyse(IAutobuilder builder, bool auto) { if (!builder.ProjectsOrSolutionsToBuild.Any()) @@ -128,7 +132,13 @@ namespace Semmle.Autobuild.Shared command.Argument(builder.Options.MsBuildArguments); - ret &= command.Script; + // append the build script which invokes msbuild to the overall build script `ret`; + // we insert a check that building the current project or solution was successful: + // if it was not successful, we add it to `FailedProjectsOrSolutions` + ret &= BuildScript.OnFailure(command.Script, ret => + { + FailedProjectsOrSolutions.Add(projectOrSolution); + }); } return ret; diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/ProjectOrSolution.cs b/csharp/autobuilder/Semmle.Autobuild.Shared/ProjectOrSolution.cs index d0c9eeb9669..c0504dbcba4 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/ProjectOrSolution.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Shared/ProjectOrSolution.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Linq; +using Semmle.Util; namespace Semmle.Autobuild.Shared { diff --git a/csharp/autobuilder/Semmle.Autobuild.Shared/Language.cs b/csharp/extractor/Semmle.Util/Language.cs similarity index 95% rename from csharp/autobuilder/Semmle.Autobuild.Shared/Language.cs rename to csharp/extractor/Semmle.Util/Language.cs index c53eb7e592d..fa3d71b6154 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Shared/Language.cs +++ b/csharp/extractor/Semmle.Util/Language.cs @@ -1,4 +1,4 @@ -namespace Semmle.Autobuild.Shared +namespace Semmle.Util { public sealed class Language { diff --git a/csharp/extractor/Semmle.Util/Semmle.Util.csproj b/csharp/extractor/Semmle.Util/Semmle.Util.csproj index b2fa737f7c4..894488f9f84 100644 --- a/csharp/extractor/Semmle.Util/Semmle.Util.csproj +++ b/csharp/extractor/Semmle.Util/Semmle.Util.csproj @@ -15,6 +15,7 @@ + diff --git a/csharp/extractor/Semmle.Util/ToolStatusPage.cs b/csharp/extractor/Semmle.Util/ToolStatusPage.cs new file mode 100644 index 00000000000..a3f8297e844 --- /dev/null +++ b/csharp/extractor/Semmle.Util/ToolStatusPage.cs @@ -0,0 +1,242 @@ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; + +namespace Semmle.Util +{ + /// + /// Represents diagnostic messages for the tool status page. + /// + public class DiagnosticMessage + { + /// + /// Represents sources of diagnostic messages. + /// + public class TspSource + { + /// + /// An identifier under which it makes sense to group this diagnostic message. + /// This is used to build the SARIF reporting descriptor object. + /// + public string Id { get; } + /// + /// Display name for the ID. This is used to build the SARIF reporting descriptor object. + /// + public string Name { get; } + /// + /// Name of the CodeQL extractor. This is used to identify which tool component the reporting descriptor object should be nested under in SARIF. + /// + public string? ExtractorName { get; } + + public TspSource(string id, string name, string? extractorName = null) + { + Id = id; + Name = name; + ExtractorName = extractorName; + } + } + + /// + /// Enumerates severity levels for diagnostics. + /// + [JsonConverter(typeof(StringEnumConverter), typeof(CamelCaseNamingStrategy))] + public enum TspSeverity + { + Note, + Warning, + Error + } + + /// + /// Stores flags indicating where the diagnostic should be displayed. + /// + public class TspVisibility + { + /// + /// A read-only instance of which indicates that the + /// diagnostic should be used in all supported locations. + /// + public static readonly TspVisibility All = new(true, true, true); + + /// + /// True if the message should be displayed on the status page (defaults to false). + /// + public bool? StatusPage { get; } + /// + /// True if the message should be counted in the diagnostics summary table printed by + /// codeql database analyze (defaults to false). + /// + public bool? CLISummaryTable { get; } + /// + /// True if the message should be sent to telemetry (defaults to false). + /// + public bool? Telemetry { get; } + + public TspVisibility(bool? statusPage = null, bool? cliSummaryTable = null, bool? telemetry = null) + { + this.StatusPage = statusPage; + this.CLISummaryTable = cliSummaryTable; + this.Telemetry = telemetry; + } + } + + /// + /// Represents source code locations for diagnostic messages. + /// + public class TspLocation + { + /// + /// Path to the affected file if appropriate, relative to the source root. + /// + public string? File { get; } + /// + /// The line where the range to which the diagnostic relates to starts. + /// + public int? StartLine { get; } + /// + /// The column where the range to which the diagnostic relates to starts. + /// + public int? StartColumn { get; } + /// + /// The line where the range to which the diagnostic relates to ends. + /// + public int? EndLine { get; } + /// + /// The column where the range to which the diagnostic relates to ends. + /// + public int? EndColumn { get; } + + public TspLocation(string? file = null, int? startLine = null, int? startColumn = null, int? endLine = null, int? endColumn = null) + { + this.File = file; + this.StartLine = startLine; + this.StartColumn = startColumn; + this.EndLine = endLine; + this.EndColumn = endColumn; + } + } + + /// + /// ISO 8601 timestamp. + /// + public string Timestamp { get; } + /// + /// The source of the diagnostic message. + /// + public TspSource Source { get; } + /// + /// GitHub flavored Markdown formatted message. Should include inline links to any help pages. + /// + public string? MarkdownMessage { get; } + /// + /// Plain text message. Used by components where the string processing needed to support + /// Markdown is cumbersome. + /// + public string? PlaintextMessage { get; } + /// + /// List of help links intended to supplement . + /// + public List HelpLinks { get; } + /// + /// SARIF severity. + /// + public TspSeverity? Severity { get; } + /// + /// If true, then this message won't be presented to users. + /// + public bool Internal { get; } + public TspVisibility Visibility { get; } + public TspLocation? Location { get; } + /// + /// Structured metadata about the diagnostic message. + /// + public Dictionary Attributes { get; } + + public DiagnosticMessage( + Language language, string id, string name, string? markdownMessage = null, string? plaintextMessage = null, + TspVisibility? visibility = null, TspLocation? location = null, TspSeverity? severity = TspSeverity.Error, + DateTime? timestamp = null, bool? intrnl = null + ) + { + this.Source = new TspSource( + id: $"{language.UpperCaseName.ToLower()}/autobuilder/{id}", + name: name, + extractorName: language.UpperCaseName.ToLower() + ); + this.Timestamp = (timestamp ?? DateTime.UtcNow).ToString("o", CultureInfo.InvariantCulture); + this.HelpLinks = new List(); + this.Attributes = new Dictionary(); + this.Severity = severity; + this.Visibility = visibility ?? TspVisibility.All; + this.Location = location; + this.Internal = intrnl ?? false; + this.MarkdownMessage = markdownMessage; + this.PlaintextMessage = plaintextMessage; + } + } + + /// + /// Provides the ability to write diagnostic messages to some output. + /// + public interface IDiagnosticsWriter + { + /// + /// Adds as a new diagnostics entry. + /// + /// The diagnostics entry to add. + void AddEntry(DiagnosticMessage message); + } + + /// + /// A wrapper around an underlying which allows + /// objects to be serialized to it. + /// + public sealed class DiagnosticsStream : IDiagnosticsWriter, IDisposable + { + private readonly JsonSerializer serializer; + private readonly StreamWriter writer; + + /// + /// Initialises a new for a file at . + /// + /// The path to the file that should be created. + public DiagnosticsStream(string path) + { + this.writer = File.CreateText(path); + + var contractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy() + }; + + serializer = new JsonSerializer + { + ContractResolver = contractResolver, + NullValueHandling = NullValueHandling.Ignore + }; + } + + /// + /// Adds as a new diagnostics entry. + /// + /// The diagnostics entry to add. + public void AddEntry(DiagnosticMessage message) + { + serializer.Serialize(writer, message); + writer.Flush(); + } + + /// + /// Releases all resources used by the object. + /// + public void Dispose() + { + writer.Dispose(); + } + } +} diff --git a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md index 3d63162ca4d..1f2dc408daf 100644 --- a/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.4 + +No user-facing changes. + ## 1.4.3 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.4.md b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.4.md new file mode 100644 index 00000000000..cb7dd204b9c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/lib/change-notes/released/1.4.4.md @@ -0,0 +1,3 @@ +## 1.4.4 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml index 08f88b689fb..1dfca6daa3b 100644 --- a/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.4.3 +lastReleaseVersion: 1.4.4 diff --git a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml index 7aa032fa92d..14647a2593b 100644 --- a/csharp/ql/campaigns/Solorigate/lib/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-all -version: 1.4.4-dev +version: 1.4.5-dev groups: - csharp - solorigate diff --git a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md index 3d63162ca4d..1f2dc408daf 100644 --- a/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md +++ b/csharp/ql/campaigns/Solorigate/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.4.4 + +No user-facing changes. + ## 1.4.3 No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.4.md b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.4.md new file mode 100644 index 00000000000..cb7dd204b9c --- /dev/null +++ b/csharp/ql/campaigns/Solorigate/src/change-notes/released/1.4.4.md @@ -0,0 +1,3 @@ +## 1.4.4 + +No user-facing changes. diff --git a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml index 08f88b689fb..1dfca6daa3b 100644 --- a/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml +++ b/csharp/ql/campaigns/Solorigate/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 1.4.3 +lastReleaseVersion: 1.4.4 diff --git a/csharp/ql/campaigns/Solorigate/src/qlpack.yml b/csharp/ql/campaigns/Solorigate/src/qlpack.yml index 72f0256ef39..48bb9aecd88 100644 --- a/csharp/ql/campaigns/Solorigate/src/qlpack.yml +++ b/csharp/ql/campaigns/Solorigate/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-solorigate-queries -version: 1.4.4-dev +version: 1.4.5-dev groups: - csharp - solorigate diff --git a/csharp/ql/consistency-queries/DataFlowConsistency.ql b/csharp/ql/consistency-queries/DataFlowConsistency.ql index 1978b2988f2..48d8024c8c5 100644 --- a/csharp/ql/consistency-queries/DataFlowConsistency.ql +++ b/csharp/ql/consistency-queries/DataFlowConsistency.ql @@ -2,6 +2,7 @@ import csharp import cil import semmle.code.csharp.dataflow.internal.DataFlowPrivate import semmle.code.csharp.dataflow.internal.DataFlowPublic +import semmle.code.csharp.dataflow.internal.DataFlowDispatch import semmle.code.csharp.dataflow.internal.DataFlowImplConsistency::Consistency private class MyConsistencyConfiguration extends ConsistencyConfiguration { @@ -14,6 +15,15 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration { ) } + override predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { + // TODO: Remove once static initializers are folded into the + // static constructors + exists(ControlFlow::Node cfn | + cfn.getElement() = any(FieldOrProperty f | f.isStatic()).getAChild+() and + cfn = call.getControlFlowNode() + ) + } + override predicate uniqueNodeLocationExclude(Node n) { // Methods with multiple implementations n instanceof ParameterNode diff --git a/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/diagnostics.expected b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/diagnostics.expected new file mode 100644 index 00000000000..689ddcc3652 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL found some projects which cannot be built with .NET Core:\n\n- `test.csproj`", + "severity": "warning", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/dotnet-incompatible-projects", + "name": "Some projects are incompatible with .NET Core" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/msbuild-build-failure", + "name": "Some projects or solutions failed to build using MSBuild" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.csproj b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.csproj new file mode 100644 index 00000000000..a07aa955494 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.csproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + {F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1} + Library + Properties + Example + Example + v4.0 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + true + bin\x86\Debug\ + DEBUG;TRACE + full + x86 + prompt + MinimumRecommendedRules.ruleset + + + bin\x86\Release\ + TRACE + true + pdbonly + x86 + prompt + MinimumRecommendedRules.ruleset + + + + + + + + + + diff --git a/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.py b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_dotnet_incompatible/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/diagnostics.expected b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/diagnostics.expected new file mode 100644 index 00000000000..6eca0003987 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.sln`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/msbuild-build-failure", + "name": "Some projects or solutions failed to build using MSBuild" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "Some project files were not found when CodeQL built your project:\n\n- `Example.csproj`\n- `Example.Test.csproj`\n\nThis may lead to subsequent failures. You can check for common causes for missing project files:\n\n- Ensure that the project is built using the [intended operating system](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idruns-on) and that filenames on case-sensitive platforms are correctly specified.\n- If your repository uses Git submodules, ensure that those are [checked out](https://github.com/actions/checkout#usage) before the CodeQL Action is run.\n- If you auto-generate some project files as part of your build process, ensure that these are generated before the CodeQL Action is run.", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/missing-project-files", + "name": "Missing project files" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.py b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.sln b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.sln new file mode 100644 index 00000000000..60a70f32fe2 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_project_files/test.sln @@ -0,0 +1,26 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example.csproj", "{F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example.Test", "Example.Test.csproj", "{F4587B5F-9918-4079-9291-5A08CD9761FB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Debug|x86.ActiveCfg = Debug|x86 + {F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Debug|x86.Build.0 = Debug|x86 + {F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Release|x86.ActiveCfg = Release|x86 + {F70CE6B6-1735-4AD2-B1EB-B91FCD1012D1}.Release|x86.Build.0 = Release|x86 + {F4587B5F-9918-4079-9291-5A08CD9761FB}.Debug|x86.ActiveCfg = Debug|x86 + {F4587B5F-9918-4079-9291-5A08CD9761FB}.Debug|x86.Build.0 = Debug|x86 + {F4587B5F-9918-4079-9291-5A08CD9761FB}.Release|x86.ActiveCfg = Release|x86 + {F4587B5F-9918-4079-9291-5A08CD9761FB}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/diagnostics.expected b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/diagnostics.expected new file mode 100644 index 00000000000..0825ee8ae85 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/diagnostics.expected @@ -0,0 +1,51 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL was unable to build the following projects using .NET Core:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/dotnet-build-failure", + "name": "Some projects or solutions failed to build using .NET Core" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL was unable to build the following projects using MSBuild:\n\n- `test.csproj`\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/msbuild-build-failure", + "name": "Some projects or solutions failed to build using MSBuild" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "[Configure your workflow](https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-xamarin-applications) for this SDK before running CodeQL.", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/missing-xamarin-ios-sdk", + "name": "Missing Xamarin SDK for iOS" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.csproj b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.csproj new file mode 100644 index 00000000000..5776266cc03 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.csproj @@ -0,0 +1,11 @@ + + + + Exe + net7.0 + enable + enable + $(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets + + + diff --git a/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.py b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/all-platforms/diag_missing_xamarin_sdk/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py index 2568768ad6b..8bc8d33ba1d 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_build/test.py @@ -1,3 +1,5 @@ from create_database_utils import * +from diagnostics_test_utils import * -run_codeql_database_create(['dotnet build'], test_db="default-db", db=None, lang="csharp") +run_codeql_database_create(['dotnet build'], db=None, lang="csharp") +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py index 9eac6efe388..b91e73ef11c 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_pack/test.py @@ -1,8 +1,11 @@ import os from create_database_utils import * +from diagnostics_test_utils import * -run_codeql_database_create(['dotnet pack'], test_db="default-db", db=None, lang="csharp") +run_codeql_database_create(['dotnet pack'], db=None, lang="csharp") ## Check that the NuGet package is created. if not os.path.isfile("bin/Debug/dotnet_pack.1.0.0.nupkg"): - raise Exception("The NuGet package was not created.") + raise Exception("The NuGet package was not created.") + +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py index 89fa2a42e0b..10e617dd32e 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_publish/test.py @@ -1,9 +1,12 @@ import os from create_database_utils import * +from diagnostics_test_utils import * artifacts = 'bin/Temp' -run_codeql_database_create([f"dotnet publish -o {artifacts}"], test_db="default-db", db=None, lang="csharp") +run_codeql_database_create([f"dotnet publish -o {artifacts}"], db=None, lang="csharp") ## Check that the publish folder is created. if not os.path.isdir(artifacts): - raise Exception("The publish artifact folder was not created.") + raise Exception("The publish artifact folder was not created.") + +check_diagnostics() diff --git a/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py b/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py index be1b516ce5a..12ca67463ec 100644 --- a/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py +++ b/csharp/ql/integration-tests/all-platforms/dotnet_run/test.py @@ -1,5 +1,6 @@ import os from create_database_utils import * +from diagnostics_test_utils import * def run_codeql_database_create_stdout(args, dbname): stdout = open(dbname + "file.txt", 'w+') @@ -16,32 +17,40 @@ def check_build_out(msg, s): # no arguments s = run_codeql_database_create_stdout(['dotnet run'], "test-db") check_build_out("Default reply", s) +check_diagnostics() # no arguments, but `--` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test-db', 'dotnet run --'], "test2-db") check_build_out("Default reply", s) +check_diagnostics(diagnostics_dir="test2-db/diagnostic") # one argument, no `--` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test2-db', 'dotnet run hello'], "test3-db") check_build_out("Default reply", s) +check_diagnostics(diagnostics_dir="test3-db/diagnostic") # one argument, but `--` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test3-db', 'dotnet run -- hello'], "test4-db") check_build_out("Default reply", s) +check_diagnostics(diagnostics_dir="test4-db/diagnostic") # two arguments, no `--` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test4-db', 'dotnet run hello world'], "test5-db") check_build_out("hello, world", s) +check_diagnostics(diagnostics_dir="test5-db/diagnostic") # two arguments, and `--` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test5-db', 'dotnet run -- hello world'], "test6-db") check_build_out("hello, world", s) +check_diagnostics(diagnostics_dir="test6-db/diagnostic") # shared compilation enabled; tracer should override by changing the command # to `dotnet run -p:UseSharedCompilation=true -p:UseSharedCompilation=false -- hello world` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test6-db', 'dotnet run -p:UseSharedCompilation=true -- hello world'], "test7-db") check_build_out("hello, world", s) +check_diagnostics(diagnostics_dir="test7-db/diagnostic") # option passed into `dotnet run` s = run_codeql_database_create_stdout(['dotnet clean', 'rm -rf test7-db', 'dotnet build', 'dotnet run --no-build hello world'], "test8-db") check_build_out("hello, world", s) +check_diagnostics(diagnostics_dir="test8-db/diagnostic") diff --git a/csharp/ql/integration-tests/all-platforms/msbuild/test.py b/csharp/ql/integration-tests/all-platforms/msbuild/test.py index 97682d28205..7471e3374e5 100644 --- a/csharp/ql/integration-tests/all-platforms/msbuild/test.py +++ b/csharp/ql/integration-tests/all-platforms/msbuild/test.py @@ -1,4 +1,6 @@ from create_database_utils import * +from diagnostics_test_utils import * # force CodeQL to use MSBuild by setting `LGTM_INDEX_MSBUILD_TARGET` -run_codeql_database_create([], test_db="default-db", db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' }) +run_codeql_database_create([], db=None, lang="csharp", extra_env={ 'LGTM_INDEX_MSBUILD_TARGET': 'Build' }) +check_diagnostics() diff --git a/csharp/ql/integration-tests/posix-only/diag_autobuild_script/build.sh b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/build.sh new file mode 100755 index 00000000000..2bb8d868bd0 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 1 diff --git a/csharp/ql/integration-tests/posix-only/diag_autobuild_script/diagnostics.expected b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/diagnostics.expected new file mode 100644 index 00000000000..129675517a6 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL attempted to build your project using a script located at `build.sh`, which failed.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/script-failure", + "name": "Unable to build project using build script" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL could not find any project or solution files in your repository.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/no-projects-or-solutions", + "name": "No project or solutions files found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/posix-only/diag_autobuild_script/test.py b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_autobuild_script/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/build.sh b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/build.sh new file mode 100755 index 00000000000..2bb8d868bd0 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 1 diff --git a/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/diagnostics.expected b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/diagnostics.expected new file mode 100644 index 00000000000..4e6b5823018 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL could not find any project or solution files in your repository.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/no-projects-or-solutions", + "name": "No project or solutions files found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL found multiple potential build scripts for your project and attempted to run `build.sh`, which failed. This may not be the right build script for your project.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/multiple-build-scripts", + "name": "There are multiple potential build scripts" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/scripts/build.sh b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/scripts/build.sh new file mode 100755 index 00000000000..2bb8d868bd0 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/scripts/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +exit 1 diff --git a/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/test.py b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/posix-only/diag_multiple_scripts/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/posix-only/dotnet_test/test.py b/csharp/ql/integration-tests/posix-only/dotnet_test/test.py index 6e3cdab30f7..7bc159e6720 100644 --- a/csharp/ql/integration-tests/posix-only/dotnet_test/test.py +++ b/csharp/ql/integration-tests/posix-only/dotnet_test/test.py @@ -1,3 +1,5 @@ from create_database_utils import * +from diagnostics_test_utils import * -run_codeql_database_create(['dotnet test'], test_db="default-db", db=None, lang="csharp") \ No newline at end of file +run_codeql_database_create(['dotnet test'], db=None, lang="csharp") +check_diagnostics() diff --git a/csharp/ql/integration-tests/posix-only/inherit-env-vars/test.py b/csharp/ql/integration-tests/posix-only/inherit-env-vars/test.py index 1b49fb18519..92d90e53ec5 100644 --- a/csharp/ql/integration-tests/posix-only/inherit-env-vars/test.py +++ b/csharp/ql/integration-tests/posix-only/inherit-env-vars/test.py @@ -1,6 +1,8 @@ from create_database_utils import * +from diagnostics_test_utils import * import os os.environ["PROJECT_TO_BUILD"] = "proj.csproj.no_auto" -run_codeql_database_create([], test_db="default-db", db=None, lang="csharp") +run_codeql_database_create([], db=None, lang="csharp") +check_diagnostics() diff --git a/csharp/ql/integration-tests/windows-only/diag_autobuild_script/build.bat b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/build.bat new file mode 100644 index 00000000000..8f7ce95c0eb --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/build.bat @@ -0,0 +1 @@ +exit /b 1 diff --git a/csharp/ql/integration-tests/windows-only/diag_autobuild_script/diagnostics.expected b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/diagnostics.expected new file mode 100644 index 00000000000..6135496f878 --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL attempted to build your project using a script located at `build.bat`, which failed.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/script-failure", + "name": "Unable to build project using build script" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL could not find any project or solution files in your repository.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/no-projects-or-solutions", + "name": "No project or solutions files found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/windows-only/diag_autobuild_script/test.py b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_autobuild_script/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/build.bat b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/build.bat new file mode 100644 index 00000000000..8f7ce95c0eb --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/build.bat @@ -0,0 +1 @@ +exit /b 1 diff --git a/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/diagnostics.expected b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/diagnostics.expected new file mode 100644 index 00000000000..4e165ac11fc --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/diagnostics.expected @@ -0,0 +1,34 @@ +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL could not find any project or solution files in your repository.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/no-projects-or-solutions", + "name": "No project or solutions files found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} +{ + "attributes": {}, + "helpLinks": [], + "internal": false, + "markdownMessage": "CodeQL found multiple potential build scripts for your project and attempted to run `build.bat`, which failed. This may not be the right build script for your project.\n\nSet up a [manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "csharp", + "id": "csharp/autobuilder/multiple-build-scripts", + "name": "There are multiple potential build scripts" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/scripts/build.bat b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/scripts/build.bat new file mode 100644 index 00000000000..8f7ce95c0eb --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/scripts/build.bat @@ -0,0 +1 @@ +exit /b 1 diff --git a/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/test.py b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/test.py new file mode 100644 index 00000000000..62c4d3934a4 --- /dev/null +++ b/csharp/ql/integration-tests/windows-only/diag_multiple_scripts/test.py @@ -0,0 +1,5 @@ +from create_database_utils import * +from diagnostics_test_utils import * + +run_codeql_database_create([], db=None, lang="csharp", runFunction=runUnsuccessfully) +check_diagnostics() diff --git a/csharp/ql/lib/CHANGELOG.md b/csharp/ql/lib/CHANGELOG.md index 7d14d20ddbc..42eaea79fd6 100644 --- a/csharp/ql/lib/CHANGELOG.md +++ b/csharp/ql/lib/CHANGELOG.md @@ -1,3 +1,14 @@ +## 0.5.4 + +### Minor Analysis Improvements + +* The query `cs/static-field-written-by-instance` is updated to handle properties. +* C# 11: Support for explicit interface member implementation of operators. +* The extraction of member modifiers has been generalized, which could lead to the extraction of more modifiers. +* C# 11: Added extractor and library support for `file` scoped types. +* C# 11: Added extractor support for `required` fields and properties. +* C# 11: Added library support for `checked` operators. + ## 0.5.3 ### Minor Analysis Improvements diff --git a/csharp/ql/lib/change-notes/2023-02-14-checked-operators.md b/csharp/ql/lib/change-notes/2023-02-14-checked-operators.md deleted file mode 100644 index 19d4a7f3f66..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-14-checked-operators.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* C# 11: Added library support for `checked` operators. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md b/csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md deleted file mode 100644 index 8a318ca52ec..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-16-requiredmembers.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* C# 11: Added extractor support for `required` fields and properties. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-02-17-filescopedtypes.md b/csharp/ql/lib/change-notes/2023-02-17-filescopedtypes.md deleted file mode 100644 index f3baf13fde4..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-17-filescopedtypes.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* C# 11: Added extractor and library support for `file` scoped types. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-02-22-modifierextraction.md b/csharp/ql/lib/change-notes/2023-02-22-modifierextraction.md deleted file mode 100644 index 2078c2a9f1e..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-22-modifierextraction.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The extraction of member modifiers has been generalised, which could lead to the extraction of more modifiers. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-02-27-explicitinterfacemember.md b/csharp/ql/lib/change-notes/2023-02-27-explicitinterfacemember.md deleted file mode 100644 index 7fd5f2ce8be..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-27-explicitinterfacemember.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* C# 11: Support for explicit interface member implementation of operators. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-02-28-staticfieldwrites.md b/csharp/ql/lib/change-notes/2023-02-28-staticfieldwrites.md deleted file mode 100644 index 8f726f7a6df..00000000000 --- a/csharp/ql/lib/change-notes/2023-02-28-staticfieldwrites.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The query `cs/static-field-written-by-instance` is updated to handle properties. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md b/csharp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md new file mode 100644 index 00000000000..89190af399f --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md @@ -0,0 +1,9 @@ +--- +category: majorAnalysis +--- +* The main data flow and taint tracking APIs have been changed. The old APIs + remain in place for now and translate to the new through a + backwards-compatible wrapper. If multiple configurations are in scope + simultaneously, then this may affect results slightly. The new API is quite + similar to the old, but makes use of a configuration module instead of a + configuration class. diff --git a/csharp/ql/lib/change-notes/2023-03-02-unsafemembers.md b/csharp/ql/lib/change-notes/2023-03-02-unsafemembers.md new file mode 100644 index 00000000000..7ff64ca1301 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-02-unsafemembers.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The `unsafe` predicate for `Modifiable` has been extended to cover delegate return types and identify pointer like types at any nest level. This is relevant for `unsafe` declarations extracted from assemblies. \ No newline at end of file diff --git a/csharp/ql/lib/change-notes/2023-03-03-delete-deps.md b/csharp/ql/lib/change-notes/2023-03-03-delete-deps.md new file mode 100644 index 00000000000..f5557fc5b77 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-03-delete-deps.md @@ -0,0 +1,6 @@ +--- +category: minorAnalysis +--- +* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class. +* Deleted the deprecated `getAssertionIndex`, and `getAssertedParameter` predicates from the `AssertMethod` class. +* Deleted the deprecated `OverridableMethod` and `OverridableAccessor` classes. diff --git a/csharp/ql/lib/change-notes/2023-03-13-mergepathgraph.md b/csharp/ql/lib/change-notes/2023-03-13-mergepathgraph.md new file mode 100644 index 00000000000..63bfade2f10 --- /dev/null +++ b/csharp/ql/lib/change-notes/2023-03-13-mergepathgraph.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query. diff --git a/csharp/ql/lib/change-notes/released/0.5.4.md b/csharp/ql/lib/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..2b7fefbe7c2 --- /dev/null +++ b/csharp/ql/lib/change-notes/released/0.5.4.md @@ -0,0 +1,10 @@ +## 0.5.4 + +### Minor Analysis Improvements + +* The query `cs/static-field-written-by-instance` is updated to handle properties. +* C# 11: Support for explicit interface member implementation of operators. +* The extraction of member modifiers has been generalized, which could lead to the extraction of more modifiers. +* C# 11: Added extractor and library support for `file` scoped types. +* C# 11: Added extractor support for `required` fields and properties. +* C# 11: Added library support for `checked` operators. diff --git a/csharp/ql/lib/codeql-pack.release.yml b/csharp/ql/lib/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/csharp/ql/lib/codeql-pack.release.yml +++ b/csharp/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/csharp/ql/lib/qlpack.yml b/csharp/ql/lib/qlpack.yml index 3f118d8115f..34880f509e8 100644 --- a/csharp/ql/lib/qlpack.yml +++ b/csharp/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-all -version: 0.5.4-dev +version: 0.5.5-dev groups: csharp dbscheme: semmlecode.csharp.dbscheme extractor: csharp diff --git a/csharp/ql/lib/semmle/code/cil/Method.qll b/csharp/ql/lib/semmle/code/cil/Method.qll index 4ba193fb01f..08abb9f41c7 100644 --- a/csharp/ql/lib/semmle/code/cil/Method.qll +++ b/csharp/ql/lib/semmle/code/cil/Method.qll @@ -67,7 +67,8 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation { * destructors, operators, accessors and so on. */ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode, - CustomModifierReceiver, Parameterizable, @cil_method { + CustomModifierReceiver, Parameterizable, @cil_method +{ /** * Gets a method implementation, if any. Note that there can * be several implementations in different assemblies. diff --git a/csharp/ql/lib/semmle/code/cil/Types.qll b/csharp/ql/lib/semmle/code/cil/Types.qll index 32efaf193ad..0e41fe748f4 100644 --- a/csharp/ql/lib/semmle/code/cil/Types.qll +++ b/csharp/ql/lib/semmle/code/cil/Types.qll @@ -302,7 +302,8 @@ class SystemType extends ValueOrRefType { * ``` */ class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable, - @cil_function_pointer_type { + @cil_function_pointer_type +{ /** Gets the return type of this function pointer. */ Type getReturnType() { cil_function_pointer_return_type(this, result) } diff --git a/csharp/ql/lib/semmle/code/csharp/Member.qll b/csharp/ql/lib/semmle/code/csharp/Member.qll index 2308911e770..eb62a2f0b5c 100644 --- a/csharp/ql/lib/semmle/code/csharp/Member.qll +++ b/csharp/ql/lib/semmle/code/csharp/Member.qll @@ -98,10 +98,21 @@ class Modifiable extends Declaration, @modifiable { /** Holds if this declaration is `unsafe`. */ predicate isUnsafe() { - this.hasModifier("unsafe") or - this.(Parameterizable).getAParameter().getType() instanceof PointerType or - this.(Property).getType() instanceof PointerType or - this.(Callable).getReturnType() instanceof PointerType + this.hasModifier("unsafe") + or + exists(Type t, Type child | + t = this.(Parameterizable).getAParameter().getType() or + t = this.(Property).getType() or + t = this.(Callable).getReturnType() or + t = this.(DelegateType).getReturnType() + | + child = t.getAChild*() and + ( + child instanceof PointerType + or + child instanceof FunctionPointerType + ) + ) } /** Holds if this declaration is `async`. */ diff --git a/csharp/ql/lib/semmle/code/csharp/Property.qll b/csharp/ql/lib/semmle/code/csharp/Property.qll index 94aecf65637..15c707321c8 100644 --- a/csharp/ql/lib/semmle/code/csharp/Property.qll +++ b/csharp/ql/lib/semmle/code/csharp/Property.qll @@ -15,7 +15,8 @@ private import TypeRef * (`Property`), or an indexer (`Indexer`). */ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attributable, - @declaration_with_accessors { + @declaration_with_accessors +{ /** Gets an accessor of this declaration. */ Accessor getAnAccessor() { result.getDeclaration() = this } @@ -49,7 +50,8 @@ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attribut * property (`Property`) or an indexer (`Indexer`). */ class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelExprParent, - @assignable_with_accessors { + @assignable_with_accessors +{ /** Gets the `get` accessor of this declaration, if any. */ Getter getGetter() { result = this.getAnAccessor() } diff --git a/csharp/ql/lib/semmle/code/csharp/Variable.qll b/csharp/ql/lib/semmle/code/csharp/Variable.qll index e5ccba59794..13254c90867 100644 --- a/csharp/ql/lib/semmle/code/csharp/Variable.qll +++ b/csharp/ql/lib/semmle/code/csharp/Variable.qll @@ -90,7 +90,8 @@ class LocalScopeVariable extends Variable, @local_scope_variable { * ``` */ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, TopLevelExprParent, - @parameter { + @parameter +{ /** * Gets the position of this parameter. For example, the position of `x` is * 0 and the position of `y` is 1 in @@ -376,7 +377,8 @@ class LocalConstant extends LocalVariable, @local_constant { * ``` */ class Field extends Variable, AssignableMember, Attributable, TopLevelExprParent, DotNet::Field, - @field { + @field +{ /** * Gets the initial value of this field, if any. For example, the initial * value of `F` on line 2 is `20` in diff --git a/csharp/ql/lib/semmle/code/csharp/XML.qll b/csharp/ql/lib/semmle/code/csharp/XML.qll index d74129d425e..33f4cd9e9e6 100644 --- a/csharp/ql/lib/semmle/code/csharp/XML.qll +++ b/csharp/ql/lib/semmle/code/csharp/XML.qll @@ -108,20 +108,6 @@ class XmlFile extends XmlParent, File { /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } - /** - * DEPRECATED: Use `getAbsolutePath()` instead. - * - * Gets the path of this XML file. - */ - deprecated string getPath() { result = this.getAbsolutePath() } - - /** - * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. - * - * Gets the path of the folder that contains this XML file. - */ - deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } - /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll index f35b10ac934..2c81702e7e9 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Assertions.qll @@ -37,26 +37,6 @@ abstract class AssertMethod extends Method { /** Gets the index of a parameter being asserted. */ abstract int getAnAssertionIndex(); - /** - * DEPRECATED: Use `getAnAssertionIndex()` instead. - * - * Gets the index of a parameter being asserted. - */ - deprecated final int getAssertionIndex() { result = this.getAnAssertionIndex() } - - /** Gets the parameter at position `i` being asserted. */ - final Parameter getAssertedParameter(int i) { - result = this.getParameter(i) and - i = this.getAnAssertionIndex() - } - - /** - * DEPRECATED: Use `getAssertedParameter(_)` instead. - * - * Gets a parameter being asserted. - */ - deprecated final Parameter getAssertedParameter() { result = this.getAssertedParameter(_) } - /** Gets the failure type if the assertion fails for argument `i`, if any. */ abstract AssertionFailure getAssertionFailure(int i); } @@ -172,7 +152,8 @@ private predicate isDoesNotReturnIfAttributeParameter(Parameter p, boolean value * A method with a parameter that is annotated with * `System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)`. */ -class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod extends BooleanAssertMethod { +class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod extends BooleanAssertMethod +{ private int i_; SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod() { @@ -190,7 +171,8 @@ class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertTrueMethod exte * A method with a parameter that is annotated with * `System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(true)`. */ -class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertFalseMethod extends BooleanAssertMethod { +class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertFalseMethod extends BooleanAssertMethod +{ private int i_; SystemDiagnosticsCodeAnalysisDoesNotReturnIfAnnotatedAssertFalseMethod() { diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlow.qll index 1d3d53e2316..847aa850d35 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/DataFlow.qll @@ -6,5 +6,6 @@ import csharp module DataFlow { - import semmle.code.csharp.dataflow.internal.DataFlowImpl + import semmle.code.csharp.dataflow.internal.DataFlow + import semmle.code.csharp.dataflow.internal.DataFlowImpl1 } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll index 65b63958cb9..0fcbe39c462 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll @@ -143,7 +143,8 @@ private class RecordConstructorFlow extends SummarizedCallable { class RequiredSummaryComponentStack = Impl::Public::RequiredSummaryComponentStack; -private class RecordConstructorFlowRequiredSummaryComponentStack extends RequiredSummaryComponentStack { +private class RecordConstructorFlowRequiredSummaryComponentStack extends RequiredSummaryComponentStack +{ override predicate required(SummaryComponent head, SummaryComponentStack tail) { exists(Property p | recordConstructorFlow(_, _, p) and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll index 8764da0a784..e692721f058 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/SSA.qll @@ -110,7 +110,8 @@ module Ssa { /** A plain field or property. */ class PlainFieldOrPropSourceVariable extends FieldOrPropSourceVariable, - SsaImpl::TPlainFieldOrProp { + SsaImpl::TPlainFieldOrProp + { override Callable getEnclosingCallable() { this = SsaImpl::TPlainFieldOrProp(result, _) } override string toString() { @@ -127,7 +128,8 @@ module Ssa { /** A qualified field or property. */ class QualifiedFieldOrPropSourceVariable extends FieldOrPropSourceVariable, - SsaImpl::TQualifiedFieldOrProp { + SsaImpl::TQualifiedFieldOrProp + { override Callable getEnclosingCallable() { this = SsaImpl::TQualifiedFieldOrProp(result, _, _) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll index 97f5073cab0..57f499ffa21 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/TaintTracking.qll @@ -6,5 +6,6 @@ import csharp module TaintTracking { + import semmle.code.csharp.dataflow.internal.tainttracking1.TaintTracking import semmle.code.csharp.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll index 787f2f614f7..0259c748ec3 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/ContentDataFlow.qll @@ -16,8 +16,7 @@ module ContentDataFlow { class ContentSet = DF::ContentSet; - predicate stageStats = DF::stageStats/8; - + // predicate stageStats = DF::stageStats/8; /** * A configuration of interprocedural data flow analysis. This defines * sources, sinks, and any other configurable aspect of the analysis. Each diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll new file mode 100644 index 00000000000..617362ab4f0 --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlow.qll @@ -0,0 +1,353 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Make` and `MakeWithState` modules. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic +private import DataFlowImpl + +/** An input configuration for data flow. */ +signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** An input configuration for data flow using flow state. */ +signature module StateConfigSig { + bindingset[this] + class FlowState; + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state); + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state); + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ +signature int explorationLimitSig(); + +/** + * The output of a data flow computation. + */ +signature module DataFlowSig { + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode; + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink); + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink); +} + +/** + * Constructs a standard data flow computation. + */ +module Make implements DataFlowSig { + private module C implements FullStateConfigSig { + import DefaultState + import Config + } + + import Impl +} + +/** + * Constructs a data flow computation using flow state. + */ +module MakeWithState implements DataFlowSig { + private module C implements FullStateConfigSig { + import Config + } + + import Impl +} + +signature class PathNodeSig { + /** Gets a textual representation of this element. */ + string toString(); + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); + + /** Gets the underlying `Node`. */ + Node getNode(); +} + +signature module PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + predicate edges(PathNode a, PathNode b); + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + predicate nodes(PathNode n, string key, string val); + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); +} + +/** + * Constructs a `PathGraph` from two `PathGraph`s by disjoint union. + */ +module MergePathGraph< + PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig Graph1, + PathGraphSig Graph2> +{ + private newtype TPathNode = + TPathNode1(PathNode1 p) or + TPathNode2(PathNode2 p) + + /** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */ + class PathNode extends TPathNode { + /** Gets this as a projection on the first given `PathGraph`. */ + PathNode1 asPathNode1() { this = TPathNode1(result) } + + /** Gets this as a projection on the second given `PathGraph`. */ + PathNode2 asPathNode2() { this = TPathNode2(result) } + + /** Gets a textual representation of this element. */ + string toString() { + result = this.asPathNode1().toString() or + result = this.asPathNode2().toString() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + Node getNode() { + result = this.asPathNode1().getNode() or + result = this.asPathNode2().getNode() + } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph implements PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + Graph1::edges(a.asPathNode1(), b.asPathNode1()) or + Graph2::edges(a.asPathNode2(), b.asPathNode2()) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + Graph1::nodes(n.asPathNode1(), key, val) or + Graph2::nodes(n.asPathNode2(), key, val) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or + Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2()) + } + } +} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 1b969756b09..b7cb98deaf9 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1,135 +1,75 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * INTERNAL: Do not use. + * + * Provides an implementation of global (interprocedural) data flow. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic +private import DataFlowImplSpecific::Public +private import DataFlowImplCommonPublic +import DataFlow /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + * An input configuration for data flow using flow state. This signature equals + * `StateConfigSig`, but requires explicit implementation of all predicates. */ -abstract class Configuration extends string { +signature module FullStateConfigSig { bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } + class FlowState; /** * Holds if `source` is a relevant data flow source with the given initial * `state`. */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } + predicate isSource(Node source, FlowState state); /** * Holds if `sink` is a relevant data flow sink accepting `state`. */ - predicate isSink(Node sink, FlowState state) { none() } + predicate isSink(Node sink, FlowState state); /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. */ - predicate isBarrier(Node node) { none() } + predicate isBarrier(Node node); /** * Holds if data flow through `node` is prohibited when the flow state is * `state`. */ - predicate isBarrier(Node node, FlowState state) { none() } + predicate isBarrier(Node node, FlowState state); /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } + predicate isBarrierIn(Node node); /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + predicate isBarrierOut(Node node); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + predicate isAdditionalFlowStep(Node node1, Node node2); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); /** * Holds if an arbitrary number of implicit read steps of content `c` may be * taken at `node`. */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } + predicate allowImplicitRead(Node node, ContentSet c); /** * Gets the virtual dispatch branching limit when calculating field flow. * This can be overridden to a smaller value to improve performance (a * value of 0 disables field flow), or a larger value to get more results. */ - int fieldFlowBranchLimit() { result = 2 } + int fieldFlowBranchLimit(); /** * Gets a data flow configuration feature to add restrictions to the set of @@ -144,1720 +84,685 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ - FlowFeature getAFeature() { none() } + FlowFeature getAFeature(); /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } + predicate sourceGrouping(Node source, string sourceGroup); /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } + predicate sinkGrouping(Node sink, string sinkGroup); /** * Holds if hidden nodes should be included in the data flow graph. * * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). + * is not visualized (as it is in a `path-problem` query). */ - predicate includeHiddenNodes() { none() } + predicate includeHiddenNodes(); +} - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } +/** + * Provides default `FlowState` implementations given a `StateConfigSig`. + */ +module DefaultState { + class FlowState = Unit; - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() + predicate isSource(Node source, FlowState state) { Config::isSource(source) and exists(state) } + + predicate isSink(Node sink, FlowState state) { Config::isSink(sink) and exists(state) } + + predicate isBarrier(Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() } } /** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. + * Constructs a data flow computation given a full input configuration. */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } +module Impl { + private class FlowState = Config::FlowState; - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} + private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + Config::allowImplicitRead(n, _) and hasRead = [false, true] + } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false + private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") } - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) } pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) } pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } + } + + private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + } + + private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + } + + private predicate inBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierIn(n) and + Config::isSource(n, _) + ) + } + + private predicate outBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierOut(n) and + Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate fullBarrier(NodeEx node) { + exists(Node n | node.asNode() = n | + Config::isBarrier(n) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + Config::isBarrierIn(n) and + not Config::isSource(n, _) + or + Config::isBarrierOut(n) and + not Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate stateBarrier(NodeEx node, FlowState state) { + exists(Node n | node.asNode() = n | Config::isBarrier(n, state)) + } + + pragma[nomagic] + private predicate sourceNode(NodeEx node, FlowState state) { + Config::isSource(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + pragma[nomagic] + private predicate sinkNode(NodeEx node, FlowState state) { + Config::isSink(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + /** Provides the relevant barriers for a step from `node1` to `node2`. */ + pragma[inline] + private predicate stepFilter(NodeEx node1, NodeEx node2) { + not outBarrier(node1) and + not inBarrier(node2) and + not fullBarrier(node1) and + not fullBarrier(node2) + } + + /** + * Holds if data can flow in one local step from `node1` to `node2`. + */ + private predicate localFlowStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1) + ) + } + + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2) + ) + } + + private predicate additionalLocalStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) + ) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ + private predicate jumpStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ + private predicate additionalJumpStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate additionalJumpStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + pragma[nomagic] + private predicate readSetEx(NodeEx node1, ContentSet c, NodeEx node2) { + readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and + stepFilter(node1, node2) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + Config::allowImplicitRead(n, c) + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate read(NodeEx node1, Content c, NodeEx node2) { + exists(ContentSet cs | + readSetEx(node1, cs, node2) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate clearsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + clearsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate expectsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + expectsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + pragma[nomagic] + private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } + + pragma[nomagic] + private predicate hasReadStep(Content c) { read(_, c, _) } + + pragma[nomagic] + private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { + store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), + contentType) and + hasReadStep(tc.getContent()) and + stepFilter(node1, node2) + } + + pragma[nomagic] + private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) + } + + pragma[nomagic] + private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) + } + + /** + * Holds if field flow should be used for the given configuration. + */ + private predicate useFieldFlow() { Config::fieldFlowBranchLimit() >= 1 } + + private predicate hasSourceCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate sourceCallCtx(CallContext cc) { + if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny + } + + private predicate hasSinkCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if flow from `p` to a return node of kind `kind` is allowed. + * + * We don't expect a parameter to return stored in itself, unless + * explicitly allowed + */ + bindingset[p, kind] + private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { + exists(ParameterPosition pos | p.isParameterOf(_, pos) | + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + allowParameterReturnInSelfCached(p.asNode()) + ) + } + + private module Stage1 implements StageSig { + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } + + private class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + pragma[assume_small_delta] + private predicate fwdFlow(NodeEx node, Cc cc) { + sourceNode(node, _) and + if hasSourceCallCtx() then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc) | + localFlowStepEx(mid, node) or + additionalLocalFlowStep(mid, node) or + additionalLocalStateStep(mid, _, node, _) ) or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + exists(NodeEx mid | fwdFlow(mid, _) and cc = false | + jumpStepEx(mid, node) or + additionalJumpStep(mid, node) or + additionalJumpStateStep(mid, _, node, _) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) + exists(NodeEx mid | + useFieldFlow() and + fwdFlow(mid, cc) and + storeEx(mid, _, node, _) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) + exists(ContentSet c | + fwdFlowReadSet(c, node, cc) and + fwdFlowConsCandSet(c, _) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) + fwdFlowIn(_, _, _, node) and + cc = true or // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) + fwdFlowOut(_, node, false) and + cc = false or // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) + exists(DataFlowCall call | + fwdFlowOutFromArg(call, node) and + fwdFlowIsEntered(call, cc) ) } + // inline to reduce the number of iterations pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and + private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { + // call context cannot help reduce virtual dispatch + fwdFlow(arg, cc) and + viableParamArgEx(call, p, arg) and + not fullBarrier(p) and ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) + cc = false + or + cc = true and + not reducedViableImplInCallContext(call, _, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil + // call context may help reduce virtual dispatch + exists(DataFlowCallable target | + fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and + target = viableImplInSomeFwdFlowCallContextExt(call) and + cc = true ) - or + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc) { fwdFlowIn(call, _, cc, _) } + + pragma[nomagic] + private predicate fwdFlowInReducedViableImplInSomeCallContext( + DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target + ) { + fwdFlow(arg, true) and + viableParamArgEx(call, p, arg) and + reducedViableImplInCallContext(call, _, _) and + target = p.getEnclosingCallable() and + not fullBarrier(p) + } + + /** + * Gets a viable dispatch target of `call` in the context `ctx`. This is + * restricted to those `call`s for which a context might make a difference, + * and to `ctx`s that are reachable in `fwdFlow`. + */ + pragma[nomagic] + private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { + exists(DataFlowCall ctx | + fwdFlowIsEntered(ctx, _) and + result = viableImplInCallContextExt(call, ctx) + ) + } + + private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + + pragma[nomagic] + private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() + fwdFlow(mid, cc) and + readSetEx(mid, c, node) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node) and + useFieldFlow() and + fwdFlow(mid, _) and + storeEx(mid, tc, node, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `cs` may be interpreted in a read as the target of some store + * into `c`, in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCandSet(ContentSet cs, Content c) { + fwdFlowConsCand(c) and + c = cs.getAReadContent() + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc) { + exists(RetNodeEx ret | + fwdFlow(ret, cc) and + ret.getReturnPosition() = pos + ) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out) { + fwdFlowOut(call, out, true) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2) or + additionalJumpStateStep(node1, state1, _, state2) + | + fwdFlow(node1) + ) + } + + private predicate fwdFlowState(FlowState state) { + sourceNode(_, state) + or + exists(FlowState state0 | + fwdFlowState(state0) and + stateStepFwd(state0, state) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + private predicate revFlow(NodeEx node, boolean toReturn) { + revFlow0(node, toReturn) and + fwdFlow(node) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn) { + exists(FlowState state | + fwdFlow(node) and + sinkNode(node, state) and + fwdFlowState(state) and + if hasSinkCallCtx() then toReturn = true else toReturn = false ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, toReturn) | + localFlowStepEx(node, mid) or + additionalLocalFlowStep(node, mid) or + additionalLocalStateStep(node, _, mid, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, _) and toReturn = false | + jumpStepEx(node, mid) or + additionalJumpStep(node, mid) or + additionalJumpStateStep(node, _, mid, _) ) or // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) + exists(Content c | + revFlowStore(c, node, toReturn) and + revFlowConsCand(c) ) or // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) + exists(NodeEx mid, ContentSet c | + readSetEx(node, c, mid) and + fwdFlowConsCandSet(c, _) and + revFlow(mid, toReturn) ) or // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) + revFlowIn(_, node, false) and + toReturn = false or // flow out of a callable exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) + revFlowOut(pos) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + or + // flow through a callable + exists(DataFlowCall call | + revFlowInToReturn(call, node) and + revFlowIsReturned(call, toReturn) ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c } /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. + * Holds if `c` is the target of a read in the flow covered by `revFlow`. */ pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) + private predicate revFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, ContentSet cs | + fwdFlow(node) and + readSetEx(node, cs, mid) and + fwdFlowConsCandSet(cs, c) and + revFlow(pragma[only_bind_into](mid), _) ) } pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn) and + fwdFlowConsCand(c) and + storeEx(node, tc, mid, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + pragma[nomagic] + additional predicate revFlowIsReadAndStored(Content c) { + revFlowConsCand(c) and + revFlowStore(c, _, _) + } + + pragma[nomagic] + additional predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + fwdFlowReturnPosition(pos, _) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos) { + exists(NodeEx out | + revFlow(out, _) and + viableReturnPosOutNodeCandFwd1(_, pos, out) ) } pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) + additional predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + fwdFlowIn(call, arg, _, p) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate revFlowIn(DataFlowCall call, ArgNodeEx arg, boolean toReturn) { + exists(ParamNodeEx p | + revFlow(p, toReturn) and + viableParamArgNodeCandFwd1(call, p, arg) + ) } pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg) { + revFlowIn(call, arg, true) } /** @@ -1866,896 +771,1717 @@ private module MkStage { * reaching an argument of `call`. */ pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn) { + exists(NodeEx out | + revFlow(out, toReturn) and + fwdFlowOutFromArg(call, out) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2) or + additionalJumpStateStep(node1, state1, node2, state2) + | + revFlow(node1, _) and + revFlow(node2, _) and + fwdFlowState(state1) and + fwdFlowState(state2) + ) + } + + pragma[nomagic] + additional predicate revFlowState(FlowState state) { + exists(NodeEx node | + sinkNode(node, state) and + revFlow(node, _) and + fwdFlowState(state) + ) + or + exists(FlowState state0 | + revFlowState(state0) and + stateStepRev(state, state0) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) + exists(Content c | + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, node2, contentType) and + c = tc.getContent() and + exists(ap1) ) } pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() + predicate readStepCand(NodeEx n1, Content c, NodeEx n2) { + revFlowIsReadAndStored(c) and + read(n1, c, n2) and + revFlow(n2) + } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { + revFlow(node) and + exists(ap) + } + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap) { + revFlow(node, _) and + exists(state) and + exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node) { + revFlow(node, true) and + fwdFlow(node, true) and + not inBarrier(node) and + not outBarrier(node) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(DataFlowCallable c, ReturnKindExt kind | + throughFlowNodeCand(p) and + returnFlowCallableNodeCand(c, kind) and + p.getEnclosingCallable() = c and + exists(ap) and + parameterFlowThroughAllowed(p, kind) ) } pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + throughFlowNodeCand(ret) and + kind = ret.getKind() and + exists(argAp) and + exists(ap) } pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn) and + revFlowInToReturn(call, arg) and + revFlowIsReturned(call, toReturn) ) } additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) + nodes = count(NodeEx node | fwdFlow(node)) and + fields = count(Content f0 | fwdFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b)) or fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) + nodes = count(NodeEx node | revFlow(node, _)) and + fields = count(Content f0 | revFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b)) } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } + /* End: Stage 1 logic. */ } - class CcCall extends Cc { - CcCall() { this = true } + pragma[noinline] + private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + localFlowStepEx(node1, node2) } - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + additionalLocalFlowStep(node1, node2) } - Cc ccNone() { result = false } + pragma[nomagic] + private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { + Stage1::revFlow(out) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) + } - CcCall ccSomeCall() { result = true } + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out + ) { + exists(ReturnPosition pos | + viableReturnPosOutNodeCand1(call, pos, out) and + pos = ret.getReturnPosition() and + kind = pos.getKind() and + Stage1::revFlow(ret) and + not outBarrier(ret) and + not inBarrier(out) + ) + } - class LocalCc = Unit; + pragma[nomagic] + private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg) and + Stage1::revFlow(arg) + } - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { + viableParamArgNodeCand1(call, p, arg) and + Stage1::revFlow(p) and + not outBarrier(arg) and + not inBarrier(p) + } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} + /** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int branch(NodeEx n1) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) + } -private module Level1CallContext { - class Cc = CallContext; + /** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int join(NodeEx n2) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) + } - class CcCall = CallContextCall; + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, ret, kind, out) and + exists(int b, int j | + b = branch(ret) and + j = join(out) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, arg, p) and + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - class CcNoCall = CallContextNoCall; + private signature module StageSig { + class Ap; - Cc ccNone() { result instanceof CallContextAny } + predicate revFlow(NodeEx node); - CcCall ccSomeCall() { result instanceof CallContextSomeCall } + predicate revFlowAp(NodeEx node, Ap ap); + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap); + + predicate callMayFlowThroughRev(DataFlowCall call); + + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap); + + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ); + + predicate readStepCand(NodeEx n1, Content c, NodeEx n2); + } + + private module MkStage { + class ApApprox = PrevStage::Ap; + + signature module StageParam { + class Ap; + + class ApNil extends Ap; + + bindingset[result, ap] + ApApprox getApprox(Ap ap); + + ApNil getApNil(NodeEx node); + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail); + + /** + * An approximation of `Content` that corresponds to the precision level of + * `Ap`, such that the mappings from both `Ap` and `Content` to this type + * are functional. + */ + class ApHeadContent; + + ApHeadContent getHeadContent(Ap ap); + + ApHeadContent projectToHeadContent(Content c); + + class ApOption; + + ApOption apNone(); + + ApOption apSome(Ap ap); + + class Cc; + + class CcCall extends Cc; + + // TODO: member predicate on CcCall + predicate matchesCall(CcCall cc, DataFlowCall call); + + class CcNoCall extends Cc; + + Cc ccNone(); + + CcCall ccSomeCall(); + + class LocalCc; + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc); + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ); + + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ); + + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ); + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap); + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType); + } + + module Stage implements StageSig { + import Param + + /* Begin: Stage logic. */ + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + private predicate revFlowApAlias(NodeEx node, ApApprox apa) { + PrevStage::revFlowAp(node, apa) + } + + pragma[nomagic] + private predicate flowIntoCallApa( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa + ) { + flowIntoCall(call, arg, p, allowsFieldFlow) and + PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and + revFlowApAlias(arg, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowOutOfCallApa( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + ApApprox apa + ) { + flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and + PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and + revFlowApAlias(ret, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + ApApprox argApa, ApApprox apa + ) { + exists(ReturnKindExt kind | + flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + ) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `summaryCtx` and `argAp` record the + * corresponding parameter position and access path of that argument, respectively. + */ + pragma[nomagic] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, ap) + } + + pragma[inline] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + ) { + fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + sourceNode(node, state) and + (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + summaryCtx = TParamNodeNone() and + ap = getApNil(node) and + apa = getApprox(ap) + or + exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + localCc = getLocalCc(mid, cc) + | + localStep(mid, state0, node, state, true, _, localCc) and + ap = ap0 and + apa = apa0 + or + localStep(mid, state0, node, state, false, ap, localCc) and + ap0 instanceof ApNil and + apa = getApprox(ap) + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + jumpStepEx(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, _, nil) and + additionalJumpStep(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, _, nil) and + additionalJumpStateStep(mid, state0, node, state) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + ap = apCons(tc, ap0) and + apa = getApprox(ap) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(ap0, c, ap) and + apa = getApprox(ap) + ) + or + // flow into a callable + fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + if PrevStage::parameterMayFlowThrough(node, apa) + then ( + summaryCtx = TParamNodeSome(node.asNode()) and + argAp = apSome(ap) + ) else ( + summaryCtx = TParamNodeNone() and argAp = apNone() + ) + or + // flow out of a callable + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and + inner = ret.getEnclosingCallable() and + cc = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + or + // flow through a callable + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(DataFlowType contentType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, _) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate readStepCand(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + PrevStage::readStepCand(node1, c, node2) and + apc = projectToHeadContent(c) + } + + bindingset[node1, apc] + pragma[inline_late] + private predicate readStepCand0(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + readStepCand(node1, apc, c, node2) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + apc = getHeadContent(ap) and + readStepCand0(node1, apc, c, node2) + ) + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg( + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + ApApprox argApa, Ap ap, ApApprox apa + ) { + exists(ReturnKindExt kind | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + + pragma[inline] + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + } + + pragma[nomagic] + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap + ) { + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa)) and + PrevStage::parameterMayFlowThrough(p, apa) and + PrevStage::callMayFlowThroughRev(call) + ) + } + + pragma[nomagic] + private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + } + + private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(ap1, c, ap2) + } + + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa) + } + + pragma[nomagic] + private predicate returnFlowsThrough( + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + Ap ap + ) { + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap + ) { + exists(ApApprox argApa | + flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), + allowsFieldFlow, argApa) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + if allowsFieldFlow = false then argAp instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowIntoCallAp( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap + ) { + exists(ApApprox apa | + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + fwdFlow(arg, _, _, _, _, ap, apa) + ) + } + + pragma[nomagic] + private predicate flowOutOfCallAp( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, + Ap ap + ) { + exists(ApApprox apa | + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and + fwdFlow(ret, _, _, _, _, ap, apa) and + pos = ret.getReturnPosition() + ) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink. + * + * The parameter `returnCtx` records whether (and how) the node must be returned + * from the enclosing callable in order to reach a sink, and if so, `returnAp` + * records the access path of the returned value. + */ + pragma[nomagic] + additional predicate revFlow( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + revFlow0(node, state, returnCtx, returnAp, ap) and + fwdFlow(node, state, _, _, _, ap) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + fwdFlow(node, state, _, _, _, ap) and + sinkNode(node, state) and + ( + if hasSinkCallCtx() + then returnCtx = TReturnCtxNoFlowThrough() + else returnCtx = TReturnCtxNone() + ) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, nil) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStepEx(node, mid) and + revFlow(mid, state, _, _, ap) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStep(node, mid) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStateStep(node, state, mid, state0) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowConsCand(ap0, c, ap) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, returnCtx, returnAp, ap0) and + readStepFwd(node, ap, _, mid, ap0) + ) + or + // flow into a callable + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, TReturnCtxNone(), returnAp, ap) and + flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and + (if allowsFieldFlow = false then ap instanceof ApNil else any()) and + returnCtx = TReturnCtxNone() + ) + or + // flow through a callable + exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap) and + if returnFlowsThrough(node, pos, state, _, _, _, ap) + then ( + returnCtx = TReturnCtxMaybeFlowThrough(pos) and + returnAp = apSome(ap) + ) else ( + returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() + ) + ) + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + ReturnCtx returnCtx, ApOption returnAp + ) { + revFlow(mid, state, returnCtx, returnAp, ap0) and + storeStepFwd(node, ap, tc, mid, ap0) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, + ApOption returnAp, Ap ap + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, returnCtx, returnAp, ap) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowParamToReturn( + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap + ) { + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap)) + } + + pragma[nomagic] + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp + ) { + revFlowParamToReturn(p, state, pos, innerReturnAp, ap) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + matchesCall(ccc, call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ) { + exists(Ap ap2, Content c | + PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowConsCand(ap2, c, ap1) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and + readStepFwd(node1, ap1, c, node2, ap2) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + ) + } + + additional predicate revFlow(NodeEx node, FlowState state) { revFlow(node, state, _, _, _) } + + predicate revFlow(NodeEx node, FlowState state, Ap ap) { revFlow(node, state, _, _, ap) } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _, _, _, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) { + revFlow(node, state, ap) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + + private predicate validAp(Ap ap) { + revFlow(_, _, _, _, ap) and ap instanceof ApNil + or + exists(TypedContent head, Ap tail | + consCand(head, tail) and + ap = apCons(head, tail) + ) + } + + additional predicate consCand(TypedContent tc, Ap ap) { + revConsCand(tc, ap) and + validAp(ap) + } + + pragma[nomagic] + private predicate parameterFlowsThroughRev( + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp + ) { + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap) and + parameterFlowThroughAllowed(p, pos.getKind()) + } + + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(ReturnPosition pos | + returnFlowsThrough(_, pos, _, _, p, ap, _) and + parameterFlowsThroughRev(p, ap, pos, _) + ) + } + + pragma[nomagic] + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + parameterFlowsThroughRev(p, argAp, pos, ap) and + kind = pos.getKind() + ) + } + + pragma[nomagic] + private predicate revFlowThroughArg( + DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, + Ap ap + ) { + exists(ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(arg, state, returnCtx, returnAp, ap) and + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap) + ) + } + + additional predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and + fields = count(TypedContent f0 | consCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + states = count(FlowState state | revFlow(_, state, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | + revFlow(n, state, returnCtx, retAp, ap) + ) + } + /* End: Stage logic. */ + } + } + + private module BooleanCallContext { + class Cc extends boolean { + Cc() { this in [true, false] } + } + + class CcCall extends Cc { + CcCall() { this = true } + } + + /** Holds if the call context may be `call`. */ + predicate matchesCall(CcCall cc, DataFlowCall call) { any() } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } - module NoLocalCallContext { class LocalCc = Unit; bindingset[node, cc] LocalCc getLocalCc(NodeEx node, Cc cc) { any() } bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + } + + private module Level1CallContext { + class Cc = CallContext; + + class CcCall = CallContextCall; + + pragma[inline] + predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + module NoLocalCallContext { + class LocalCc = Unit; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + module LocalCallContext { + class LocalCc = LocalCallContext; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() } } - module LocalCallContext { - class LocalCc = LocalCallContext; + private module Stage2Param implements MkStage::StageParam { + private module PrevStage = Stage1; - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) + class Ap extends boolean { + Ap() { this in [true, false] } } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + class ApNil extends Ap { + ApNil() { this = false } } + + bindingset[result, ap] + PrevStage::Ap getApprox(Ap ap) { any() } + + ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + class ApHeadContent = Unit; + + pragma[inline] + ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + + ApHeadContent projectToHeadContent(Content c) { any() } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2) + ) and + exists(ap) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + predicate flowIntoCall = flowIntoCallNodeCand1/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::revFlowIsReadAndStored(c) and + expectsContentEx(node, c) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + PrevStage::revFlowState(state) and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + ap = true and + expectsContentCand(node) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + private module Stage2 implements StageSig { + import MkStage::Stage } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) + private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) + pragma[nomagic] + private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) + private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) or + expectsContentCached(this.asNode(), _) + } } - } - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowEntry(NodeEx node, FlowState state) { + Stage2::revFlow(node, state) and + ( + sourceNode(node, state) + or + jumpStepEx(_, node) + or + additionalJumpStep(_, node) + or + additionalJumpStateStep(_, _, node, state) + or + node instanceof ParamNodeEx + or + node.asNode() instanceof OutNodeExt + or + Stage2::storeStepCand(_, _, _, node, _) + or + Stage2::readStepCand(_, _, node) + or + node instanceof FlowCheckNode + or + exists(FlowState s | + additionalLocalStateStep(_, s, node, state) and + s != state + ) + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state) { + exists(NodeEx next | Stage2::revFlow(next, state) | + jumpStepEx(node, next) or + additionalJumpStep(node, next) or + flowIntoCallNodeCand2(_, node, next, _) or + flowOutOfCallNodeCand2(_, node, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _) or + Stage2::readStepCand(node, _, next) + ) or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s) | + additionalJumpStateStep(node, state, next, s) + or + additionalLocalStateStep(node, state, next, s) and s != state ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } + Stage2::revFlow(node, state) and + node instanceof FlowCheckNode + or + sinkNode(node, state) + } - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false) + or + additionalLocalStateStep(node1, state1, node2, state2) and + Stage2::revFlow(node1, state1, false) and + Stage2::revFlowAlias(node2, state2, false) + } - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, + LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + localFlowEntry(node1, pragma[only_bind_into](state)) and + ( + localFlowStepNodeCand1(node1, node2) and + preservesValue = true and + t = node1.getDataFlowType() and // irrelevant dummy value + Stage2::revFlow(node2, pragma[only_bind_into](state)) + or + additionalLocalFlowStepNodeCand2(node1, state, node2, state) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + exists(NodeEx mid | + localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and + localFlowStepNodeCand1(mid, node2) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state)) + ) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state, mid, _, _, cc) and + additionalLocalFlowStepNodeCand2(mid, state, node2, state) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() + ) ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and + localFlowExit(node2, state1) and + state1 = state2 or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and + state1 != state2 and + preservesValue = false and + t = node2.getDataFlowType() and + callContext.relevantFor(node1.getEnclosingCallable()) and + not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | + isUnreachableInCallCached(node1.asNode(), call) or + isUnreachableInCallCached(node2.asNode(), call) ) + } + } + + private import LocalFlowBigStep + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + predicate projectToHeadContent = getContentApprox/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + import BooleanCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApproxAccessPathFrontNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + predicate flowIntoCall = flowIntoCallNodeCand2/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage3 implements StageSig { + import MkStage::Stage + } + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import BooleanCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and + exists(lcc) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + not clear(node, ap) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage4 implements StageSig { + import MkStage::Stage + } + + /** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ + private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { + exists(AccessPathFront apf | + Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) ) } /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() + private predicate expensiveLen2unfolding(TypedContent tc) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage4::consCand(tc, TFrontNil(t)) and + not expensiveLen2unfolding(tc) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage4::consCand(tc1, TFrontHead(tc2)) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc) + } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) + /** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ + abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} + private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; -private module Stage3 implements StageSig { - import MkStage::Stage -} + AccessPathApproxNil() { this = TNil(t) } -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; + override string toString() { result = concat(": " + ppReprType(t)) } - class Ap = AccessPathFront; + override TypedContent getHead() { none() } - class ApNil = AccessPathFrontNil; + override int len() { result = 0 } - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + override DataFlowType getType() { result = t } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + abstract private class AccessPathApproxCons extends AccessPathApprox { } - class ApHeadContent = Content; + private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + AccessPathApproxConsNil() { this = TConsNil(tc, t) } - ApHeadContent projectToHeadContent(Content c) { result = c } + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } - class ApOption = AccessPathFrontOption; + override TypedContent getHead() { result = tc } - ApOption apNone() { result = TAccessPathFrontNone() } + override int len() { result = 1 } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + override DataFlowType getType() { result = tc.getContainerType() } - import BooleanCallContext + override AccessPathFront getFront() { result = TFrontHead(tc) } - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } } - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } + override TypedContent getHead() { result = tc1 } - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } + override int len() { result = len } - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } + override DataFlowType getType() { result = tc1.getContainerType() } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + override AccessPathFront getFront() { result = TFrontHead(tc1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( result = TConsCons(tc2, _, len - 1) or len = 2 and @@ -2763,1561 +2489,581 @@ private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { or result = TCons1(tc2, len - 1) ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) + } + } + + private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage4::consCand(tc, TFrontNil(t)) and + result = TNil(t) + ) ) - ) + } } -} -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + /** Gets the access path obtained by popping `tc` from `ap`, if any. */ + private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto `ap`. */ + private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) + private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } } -} -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; + private module Stage5Param implements MkStage::StageParam { + private module PrevStage = Stage4; - class Ap = AccessPathApprox; + class Ap = AccessPathApprox; - class ApNil = AccessPathApproxNil; + class ApNil = AccessPathApproxNil; + + pragma[nomagic] + PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + import Level1CallContext + import LocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + } + + private module Stage5 = MkStage::Stage; pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc + private predicate nodeMayUseSummary0( + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + exists(AccessPathApprox apa0 | + Stage5::parameterMayFlowThrough(p, _) and + Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + TAccessPathApproxSome(apa), apa0) ) } pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + private predicate nodeMayUseSummary(NodeEx n, FlowState state, AccessPathApprox apa) { + exists(ParamNodeEx p | + Stage5::parameterMayFlowThrough(p, apa) and + nodeMayUseSummary0(n, p, state, apa) ) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + Stage5::parameterMayFlowThrough(p, ap.getApprox()) and + Stage5::revFlow(p, state, _) + } - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} + /** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ + abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); + } -private module Stage5 = MkStage::Stage; + /** A summary context from which no flow summary can be generated. */ + private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } + } -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} + /** A summary context from which a flow summary can be generated. */ + private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ + private int count1to2unfold(AccessPathApproxCons1 apa) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + ) ) } -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and + private int countNodesUsingAccessPath(AccessPathApprox apa) { result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) + strictcount(NodeEx n, FlowState state | + Stage5::revFlow(n, state, apa) or nodeMayUseSummary(n, state, apa) ) - ) -} + } -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else + /** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ + private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa) { exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and + aps = count1to2unfold(apa) and + nodes = countNodesUsingAccessPath(apa) and accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() + apLimit < aps and + tupleLimit < (aps - 1) * nodes ) } -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() + private AccessPathApprox getATail(AccessPathApprox apa) { + exists(TypedContent head | + apa.pop(head) = result and + Stage5::consCand(head, result) ) } -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" + /** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ + private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { + if apa.getHead().forceHighPrecision() + then unfold = true else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa) and + nodes = countNodesUsingAccessPath(apa) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) + /** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ + pragma[assume_small_delta] + private int countAps(AccessPathApprox apa) { + evalUnfold(apa, false) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa)) or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" + evalUnfold(apa, false) and + result = count1to2unfold(apa) and + not expensiveLen1to2unfolding(apa) or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) + evalUnfold(apa, true) and + result = countPotentialAps(apa) } - private string ppCtx() { - this instanceof PathNodeSink and result = "" + /** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ + language[monotonicAggregates] + pragma[assume_small_delta] + private int countPotentialAps(AccessPathApprox apa) { + apa instanceof AccessPathApproxNil and result = 1 or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) + private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false) and + head = apa.getHead() and + tail.getApprox() = getATail(apa) + ) } or - TCallableSrc() or - TCallableSink() + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + not expensiveLen1to2unfolding(apa) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + expensiveLen1to2unfolding(apa) and + apa.len() = len and + head = apa.getHead() + ) + } - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + private newtype TPathNode = + pragma[assume_small_delta] + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + // A PathNode is introduced by a source ... + Stage5::revFlow(node, state) and + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + pathStep(_, node, state, cc, sc, ap) and + Stage5::revFlow(node, state, ap.getApprox()) + } or + TPathNodeSink(NodeEx node, FlowState state) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() + ) + } or + TPathNodeSourceGroup(string sourceGroup) { + exists(PathNodeImpl source | sourceGroup = source.getSourceGroup()) + } or + TPathNodeSinkGroup(string sinkGroup) { + exists(PathNodeSink sink | sinkGroup = sink.getSinkGroup()) + } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the * tracked object. The final type indicates the type of the tracked object. */ - private class PartialAccessPath extends TPartialAccessPath { + private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() } - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } } - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } } - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + pragma[assume_small_delta] + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + pragma[assume_small_delta] + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } - } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) } } - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) + private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage5::consCand(head1, result.getApprox()) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = + "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } } - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) + private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } + AccessPathCons1() { this = TAccessPathCons1(head, len) } - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + override TypedContent getHead() { result = head } - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) + override AccessPath getTail() { + Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + } - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + override AccessPathFrontHead getFront() { result = TFrontHead(head) } - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } + } + + abstract private class PathNodeImpl extends TPathNode { + /** Gets the `FlowState` of this node. */ + abstract FlowState getState(); + + /** Holds if this node is a source. */ + abstract predicate isSource(); + + abstract PathNodeImpl getASuccessorImpl(); + + private PathNodeImpl getASuccessorIfHidden() { + this.isHidden() and + result = this.getASuccessorImpl() + } + + pragma[nomagic] + private PathNodeImpl getANonHiddenSuccessor0() { + result = this.getASuccessorIfHidden*() and + not result.isHidden() + } + + final PathNodeImpl getANonHiddenSuccessor() { + result = this.getASuccessorImpl().getANonHiddenSuccessor0() and + not this.isHidden() + } + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + not Config::includeHiddenNodes() and ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + ) } - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } + string getSourceGroup() { + this.isSource() and + Config::sourceGrouping(this.getNodeEx().asNode(), result) + } + + predicate isFlowSource() { + this.isSource() and not exists(this.getSourceGroup()) + or + this instanceof PathNodeSourceGroup + } + + predicate isFlowSink() { + this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or + this instanceof PathNodeSinkGroup + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { /** Gets a textual representation of this element. */ string toString() { result = this.getNodeEx().toString() + this.ppAp() } @@ -4341,305 +3087,335 @@ private module FlowExploration { ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + } + + /** Holds if `n` can reach a sink. */ + private predicate directReach(PathNodeImpl n) { + n instanceof PathNodeSink or + n instanceof PathNodeSinkGroup or + directReach(n.getANonHiddenSuccessor()) + } + + /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ + private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } + + /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ + private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { + n1.getANonHiddenSuccessor() = n2 and directReach(n2) + } + + private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } + final Node getNode() { super.getNodeEx().projectToNode() = result } - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) } - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group) } } /** * Provides the query predicates needed to include a graph in a path-problem query. */ - module PartialPathGraph { + module PathGraph implements PathGraphSig { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) + } } - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + /** + * An intermediate flow graph node. This is a tuple consisting of a `Node`, + * a `FlowState`, a `CallContext`, a `SummaryCtx`, and an `AccessPath`. + */ + private class PathNodeMid extends PathNodeImpl, TPathNodeMid { NodeEx node; FlowState state; CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; + SummaryCtx sc; + AccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } CallContext getCallContext() { result = cc } - TSummaryCtx1 getSummaryCtx1() { result = sc1 } + SummaryCtx getSummaryCtx() { result = sc } - TSummaryCtx2 getSummaryCtx2() { result = sc2 } + AccessPath getAp() { result = ap } - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) } - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + } + + predicate isAtSink() { + sinkNode(node, state) and + ap instanceof AccessPathNil and + if hasSinkCallCtx() + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state } } - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + /** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ + private class PathNodeSink extends PathNodeImpl, TPathNodeSink { NodeEx node; FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + PathNodeSink() { this = TPathNodeSink(node, state) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) } - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + override predicate isSource() { sourceNode(node, state) } - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) } + } - RevPartialAccessPath getAp() { result = ap } + private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { + string sourceGroup; - override Configuration getConfiguration() { result = config } + PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup) } - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } + override NodeEx getNodeEx() { none() } - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup } + + override predicate isSource() { none() } + + override string toString() { result = sourceGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 } } - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { + string sinkGroup; + + PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup) } + + override NodeEx getNodeEx() { none() } + + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { none() } + + override predicate isSource() { none() } + + override string toString() { result = sinkGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 + } + } + + private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + LocalCallContext localCC ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and + midnode = mid.getNodeEx() and state = mid.getState() and cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() } - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + /** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) + or + exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + state = mid.getState() and + cc = mid.getCallContext() } pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config + private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + state = mid.getState() and + cc = mid.getCallContext() } - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() + apa = mid.getAp().getApprox() } pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + pathOutOfCallable0(mid, pos, state, innercc, apa) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4648,53 +3424,86 @@ private module FlowExploration { ) } - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) + pragma[noinline] + private NodeEx getAnOutNodeFlow(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa) { + result.asNode() = kind.getAnOutNode(call) and + Stage5::revFlow(result, _, apa) + } + + /** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ + pragma[noinline] + private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa | + pathOutOfCallable1(mid, call, kind, state, cc, apa) and + out = getAnOutNodeFlow(kind, call, apa) ) } + /** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and parameterMatch(ppos, apos) ) } pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) + exists(ParamNodeEx p | + Stage5::revFlow(p, _, apa) and + p.isParameterOf(callable, pos) + ) } - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config + pragma[nomagic] + private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) + ) + } + + /** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ + pragma[nomagic] + private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call + ) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4702,252 +3511,1108 @@ private module FlowExploration { ) } + /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and + exists(RetNodeEx ret | + pathNode(_, ret, state, cc, sc, ap, _) and kind = ret.getKind() and + apa = ap.getApprox() and + parameterFlowThroughAllowed(sc.getParamNode(), kind) + ) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa + ) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa) + ) + } + + /** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ + pragma[noinline] + private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + out = getAnOutNodeFlow(kind, call, apa) + ) + } + + private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _) and + not arg.isHidden() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, + AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _) or + storeEx(n1, _, n2, _) or + readSetEx(n1, _, n2) + ) + } + + pragma[nomagic] + private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { + succ = pred.getANonHiddenSuccessor() and + succNode = succ.getNodeEx() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + hasSuccessor(pragma[only_bind_into](arg), par, p) and + not ret.isHidden() and + pathNode(out0, o, sout, _, _, apout, _) + | + out = out0 or out = out0.projectToSink() + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNodeImpl n) { + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNodeImpl mid | + retReach(mid) and + n.getANonHiddenSuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } + } + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { + exists(PathNodeImpl flowsource, PathNodeImpl flowsink | + source = flowsource and sink = flowsink + | + flowsource.isFlowSource() and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.isFlowSink() + ) + } + + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { + flowsource.isSource() and + flowsource.getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink + } + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + + private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNodeImpl pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = + count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn) + } + + /** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ + predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples + ) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "5 Fwd" and + n = 50 and + Stage5::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and + n = 55 and + Stage5::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) + } + + module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { + exists(NodeEx node1, NodeEx node2 | + jumpStepEx(node1, node2) + or + additionalJumpStep(node1, node2) + or + additionalJumpStateStep(node1, _, node2, _) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c) { + exists(Node n | Config::isSource(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) + } + + private predicate interestingCallableSink(DataFlowCallable c) { + exists(Node n | Config::isSink(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c) { + interestingCallableSrc(c) or + interestingCallableSink(c) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2 | + callableStep(c1, c2) and + ce1 = TCallable(c1) and + ce2 = TCallable(c2) + ) + or + exists(Node n | + ce1 = TCallableSrc() and + Config::isSource(n, _) and + ce2 = TCallable(getNodeEnclosingCallable(n)) + ) + or + exists(Node n | + ce2 = TCallableSink() and + Config::isSink(n, _) and + ce1 = TCallable(getNodeEnclosingCallable(n)) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } + + private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state) or + sinkNode(_, state) or + additionalLocalStateStep(_, state, _, _) or + additionalLocalStateStep(_, _, _, state) or + additionalJumpStateStep(_, state, _, _) or + additionalJumpStateStep(_, _, _, state) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + distSrc(node.getEnclosingCallable()) <= explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap + ) { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(explorationLimit()) + or + revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and + not clearsContentEx(node, ap.getHead()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead()) + ) and + not fullBarrier(node) and + not stateBarrier(node, state) and + distSink(node.getEnclosingCallable()) <= explorationLimit() + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + not fullBarrier(node) and + not stateBarrier(node, state) and + not clearsContentEx(node, ap.getHead().getContent()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead().getContent()) + ) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { result = distSrc(this.getNodeEx().getEnclosingCallable()) } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { result = distSink(this.getNodeEx().getEnclosingCallable()) } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + } + + predicate isSource() { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp()) + } + + predicate isSink() { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + or + additionalLocalFlowStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + partialPathStoreStep(mid, _, _, node, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and + sc3 = mid.getSummaryCtx3() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + or + partialPathOutOfCallable(mid, node, state, cc, ap) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + storeEx(midNode, tc, node, contentType) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { + partialPathStoreStep(_, ap1, tc, _, ap2) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node) and + ap.getHead() = tc and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and ap = mid.getAp() - ) - } + } - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + | + out.asNode() = kind.getAnOutNode(call) + ) + } - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[nomagic] + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + ) { + localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and + ap = mid.getAp() + or + additionalLocalFlowStep(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + jumpStepEx(node, mid.getNodeEx()) and + state = mid.getState() and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and + ap = mid.getAp() + or + additionalJumpStep(node, mid.getNodeEx()) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } + sc3 = mid.getSummaryCtx3() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) + pragma[nomagic] + private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + revPartialPathReadStep(_, ap1, c, _, ap2) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + storeEx(node, tc, midNode, _) and + ap.getHead() = c and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } + + private predicate partialFlow(PartialPathNode source, PartialPathNode node) { + source.isFwdSource() and + node = source.getASuccessor+() + } + + private predicate revPartialFlow(PartialPathNode node, PartialPathNode sink) { + sink.isRevSink() and + node.getASuccessor+() = sink + } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink) and + dist = node.getSinkDistance() + } } } - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll new file mode 100644 index 00000000000..e6bdc74cceb --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl1.qll @@ -0,0 +1,396 @@ +/** + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +private import DataFlowImpl +import DataFlowImplCommonPublic +import FlowStateString + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited. + */ + deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited when + * the flow state is `state` + */ + deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * DEPRECATED: Use `FlowExploration` instead. + * + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + deprecated int explorationLimit() { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (for example in a `path-problem` query). + */ + predicate includeHiddenNodes() { none() } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +/** A bridge class to access the deprecated `isBarrierGuard`. */ +private class BarrierGuardGuardedNodeBridge extends Unit { + abstract predicate guardedNode(Node n, Configuration config); + + abstract predicate guardedNode(Node n, FlowState state, Configuration config); +} + +private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { + deprecated override predicate guardedNode(Node n, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + } + + deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g, state) and + n = g.getAGuardedNode() + ) + } +} + +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) + or + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) + or + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) + or + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 + } + + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) + } + + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } + + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } + + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) + } + + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) + } + + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } +} + +private import Impl as I +import I + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof I::PathNode { + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { result = super.getNode() } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = getState(super.getState()) } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = getConfig(super.getState()) } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getASuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } + + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } + + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } +} + +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink + ) +} + +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config +} + +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } + +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 1b969756b09..e6bdc74cceb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 1b969756b09..e6bdc74cceb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 1b969756b09..e6bdc74cceb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 1b969756b09..e6bdc74cceb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 5d3becc8078..d09fdcfca3e 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -3,15 +3,18 @@ private import DataFlowImplSpecific::Public import Cached module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; + /** Provides `FlowState = string`. */ + module FlowStateString { + /** A state value to track during data flow. */ + class FlowState = string; - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } + /** + * The default state, which is used when the state is unspecified for a source + * or a sink. + */ + class FlowStateEmpty extends FlowState { + FlowStateEmpty() { this = "" } + } } private newtype TFlowFeature = @@ -179,6 +182,7 @@ private module LambdaFlow { boolean toJump, DataFlowCallOption lastCall ) { revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and + not expectsContent(node, _) and if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode then compatibleTypes(t, getNodeDataFlowType(node)) else any() diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll index 9bbc70fbdf9..7da63f6c4fa 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplConsistency.qll @@ -18,6 +18,9 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ predicate uniqueEnclosingCallableExclude(Node n) { none() } + /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ + predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ predicate uniqueNodeLocationExclude(Node n) { none() } @@ -86,6 +89,15 @@ module Consistency { ) } + query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) { + exists(int c | + c = count(call.getEnclosingCallable()) and + c != 1 and + not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and + msg = "Call should have one enclosing callable but has " + c + "." + ) + } + query predicate uniqueType(Node n, string msg) { exists(int c | n instanceof RelevantNode and diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index 1b969756b09..e6bdc74cceb 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 8a355d3416a..a7fc72d0c17 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -1215,7 +1215,8 @@ private module ArgumentNodes { * ``` */ class ImplicitCapturedArgumentNode extends ArgumentNodeImpl, NodeImpl, - TImplicitCapturedArgumentNode { + TImplicitCapturedArgumentNode + { private LocalScopeVariable v; private ControlFlow::Nodes::ElementNode cfn; @@ -2034,7 +2035,8 @@ private module PostUpdateNodes { * a pre-update node for the `ObjectCreationNode`. */ class ObjectInitializerNode extends PostUpdateNode, NodeImpl, ArgumentNodeImpl, - TObjectInitializerNode { + TObjectInitializerNode + { private ObjectCreation oc; private ControlFlow::Nodes::ElementNode cfn; @@ -2374,3 +2376,12 @@ module Csv { ) } } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll index 468ed73e81a..e485a5be522 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImpl.qll @@ -301,8 +301,8 @@ module Private { TWithoutContentSummaryComponent(ContentSet c) or TWithContentSummaryComponent(ContentSet c) - private TParameterSummaryComponent thisParam() { - result = TParameterSummaryComponent(instanceParameterPosition()) + private TParameterSummaryComponent callbackSelfParam() { + result = TParameterSummaryComponent(callbackSelfParameterPosition()) } newtype TSummaryComponentStack = @@ -311,7 +311,7 @@ module Private { any(RequiredSummaryComponentStack x).required(head, tail) or any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and - head = thisParam() + head = callbackSelfParam() or derivedFluentFlowPush(_, _, _, head, tail, _) } @@ -336,7 +336,7 @@ module Private { callbackRef = s.drop(_) and (isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and input = callbackRef.tail() and - output = TConsSummaryComponentStack(thisParam(), input) and + output = TConsSummaryComponentStack(callbackSelfParam(), input) and preservesValue = true ) or @@ -439,6 +439,9 @@ module Private { out.head() = TParameterSummaryComponent(_) and s = out.tail() ) + or + // Add the post-update node corresponding to the requested argument node + outputState(c, s) and isCallbackParameter(s) } private newtype TSummaryNodeState = @@ -1012,7 +1015,7 @@ module Private { private predicate relevantSummaryElementGenerated( AccessPath inSpec, AccessPath outSpec, string kind ) { - summaryElement(this, inSpec, outSpec, kind, "generated") and + summaryElement(this, inSpec, outSpec, kind, ["generated", "ai-generated"]) and not summaryElement(this, _, _, _, "manual") } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll index 01637d912b7..e8aa0fd9243 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/FlowSummaryImplSpecific.qll @@ -22,7 +22,7 @@ class SummarizedCallableBase extends Callable { DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c } /** Gets the parameter position of the instance parameter. */ -ArgumentPosition instanceParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks +ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks /** Gets the synthesized summary data-flow node for the given values. */ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) } diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll new file mode 100644 index 00000000000..7f96fe5e6fb --- /dev/null +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTracking.qll @@ -0,0 +1,64 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ + +import TaintTrackingParameter::Public +private import TaintTrackingParameter::Private + +private module AddTaintDefaults implements + DataFlowInternal::FullStateConfigSig +{ + import Config + + predicate isBarrier(DataFlow::Node node) { + Config::isBarrier(node) or defaultTaintSanitizer(node) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + Config::isAdditionalFlowStep(node1, node2) or + defaultAdditionalTaintStep(node1, node2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + Config::allowImplicitRead(node, c) + or + ( + Config::isSink(node, _) or + Config::isAdditionalFlowStep(node, _) or + Config::isAdditionalFlowStep(node, _, _, _) + ) and + defaultImplicitTaintRead(node, c) + } +} + +/** + * Constructs a standard taint tracking computation. + */ +module Make implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import DataFlowInternal::DefaultState + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} + +/** + * Constructs a taint tracking computation using flow state. + */ +module MakeWithState implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll index 275149a07d4..6fa484bea77 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/tainttracking1/TaintTrackingParameter.qll @@ -2,5 +2,6 @@ import semmle.code.csharp.dataflow.internal.TaintTrackingPublic as Public module Private { import semmle.code.csharp.dataflow.DataFlow::DataFlow as DataFlow + import semmle.code.csharp.dataflow.internal.DataFlowImpl as DataFlowInternal import semmle.code.csharp.dataflow.internal.TaintTrackingPrivate } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 4d994ed2afb..3acf6e4ed3a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -72,6 +72,7 @@ private module Internal { not mc.isLateBound() } or TDispatchAccessorCall(AccessorCall ac) or + TDispatchOperatorCall(OperatorCall oc) { not oc.isLateBound() } or TDispatchReflectionCall(MethodCall mc, string name, Expr object, Expr qualifier, int args) { isReflectionCall(mc, name, object, qualifier, args) } or @@ -90,8 +91,6 @@ private module Internal { or c instanceof ConstructorInitializer or - c = any(OperatorCall oc | not oc.isLateBound()) - or c instanceof LocalFunctionCall } @@ -113,12 +112,12 @@ private module Internal { } cached - predicate mayBenefitFromCallContext(DispatchMethodOrAccessorCall dc) { + predicate mayBenefitFromCallContext(DispatchOverridableCall dc) { dc.mayBenefitFromCallContext(_, _) } cached - RuntimeCallable getADynamicTargetInCallContext(DispatchMethodOrAccessorCall dc, DispatchCall ctx) { + RuntimeCallable getADynamicTargetInCallContext(DispatchOverridableCall dc, DispatchCall ctx) { result = dc.getADynamicTargetInCallContext(ctx) } } @@ -214,6 +213,9 @@ private module Internal { /** Gets the qualifier of this call, if any. */ abstract Expr getQualifier(); + /** Gets the qualifier or another expression that can be used for typing purposes, if any. */ + Expr getSyntheticQualifier() { result = this.getQualifier() } + /** Gets a static (compile-time) target of this call. */ abstract Callable getAStaticTarget(); @@ -241,7 +243,7 @@ private module Internal { private predicate hasCallable0(Gvn::GvnType t, OverridableCallable c, OverridableCallable source) { c.getUnboundDeclaration() = source and any(ValueOrRefType t0 | Gvn::getGlobalValueNumber(t0) = t).hasCallable(c) and - source = any(DispatchMethodOrAccessorCall call).getAStaticTargetExt() + source = any(DispatchOverridableCall call).getAStaticTargetExt() } pragma[noinline] @@ -250,7 +252,7 @@ private module Internal { hasOverrider(t, c) } - abstract private class DispatchMethodOrAccessorCall extends DispatchCallImpl { + abstract private class DispatchOverridableCall extends DispatchCallImpl { pragma[noinline] OverridableCallable getAStaticTargetExt() { exists(OverridableCallable target | this.getAStaticTarget() = target | @@ -261,13 +263,15 @@ private module Internal { } pragma[nomagic] - predicate hasQualifierTypeInherited(Type t) { t = getAPossibleType(this.getQualifier(), _) } + predicate hasQualifierTypeInherited(Type t) { + t = getAPossibleType(this.getSyntheticQualifier(), _) + } pragma[noinline] private predicate hasSubsumedQualifierType(Gvn::GvnType t) { hasOverrider(t, _) and exists(Type t0 | - t0 = getAPossibleType(this.getQualifier(), false) and + t0 = getAPossibleType(this.getSyntheticQualifier(), false) and not t0 instanceof TypeParameter | t = Gvn::getGlobalValueNumber(t0) @@ -280,12 +284,12 @@ private module Internal { private predicate hasConstrainedTypeParameterQualifierType( Unification::ConstrainedTypeParameter tp ) { - tp = getAPossibleType(this.getQualifier(), false) + tp = getAPossibleType(this.getSyntheticQualifier(), false) } pragma[noinline] private predicate hasUnconstrainedTypeParameterQualifierType() { - getAPossibleType(this.getQualifier(), false) instanceof + getAPossibleType(this.getSyntheticQualifier(), false) instanceof Unification::UnconstrainedTypeParameter } @@ -313,7 +317,7 @@ private module Internal { | pdef = def.getDefinition() and p = pdef.getTarget() and - this.getQualifier() = def.getARead() and + this.getSyntheticQualifier() = def.getARead() and p.getPosition() = i and c.getAParameter() = p and not p.isParams() @@ -446,7 +450,7 @@ private module Internal { pragma[noinline] NonConstructedOverridableCallable getAViableOverrider0() { - getAPossibleType(this.getQualifier(), false) instanceof TypeParameter and + getAPossibleType(this.getSyntheticQualifier(), false) instanceof TypeParameter and result.getAConstructingCallableOrSelf() = this.getAStaticTargetExt() } @@ -497,9 +501,10 @@ private module Internal { result = c.getAnOverrider(t) ) or - exists(NonConstructedOverridableCallable c | + exists(NonConstructedOverridableCallable c, NonConstructedOverridableCallable mid | c = this.getAViableOverrider0() and - result = c.getAnOverrider(_) + c = mid.getUnboundDeclaration() and + result = mid.getAnOverrider(_) | this.hasUnconstrainedTypeParameterQualifierType() or @@ -774,7 +779,7 @@ private module Internal { * The set of viable targets is determined by taking virtual dispatch * into account. */ - private class DispatchMethodCall extends DispatchMethodOrAccessorCall, TDispatchMethodCall { + private class DispatchMethodCall extends DispatchOverridableCall, TDispatchMethodCall { override MethodCall getCall() { this = TDispatchMethodCall(result) } override Expr getArgument(int i) { @@ -789,13 +794,35 @@ private module Internal { override Method getAStaticTarget() { result = this.getCall().getTarget() } } + /** + * An ordinary operator call. + * + * The set of viable targets is determined by taking virtual dispatch + * into account. + */ + private class DispatchOperatorCall extends DispatchOverridableCall, TDispatchOperatorCall { + override OperatorCall getCall() { this = TDispatchOperatorCall(result) } + + override Expr getArgument(int i) { result = this.getCall().getArgument(i) } + + /** + * Gets the first child expression of an operator call, which can be considered the qualifier + * expression for the dispatch call use-cases. + */ + override Expr getSyntheticQualifier() { result = this.getCall().getChildExpr(0) } + + override Expr getQualifier() { none() } + + override Operator getAStaticTarget() { result = this.getCall().getTarget() } + } + /** * A call to an accessor. * * The set of viable targets is determined by taking virtual dispatch * into account. */ - private class DispatchAccessorCall extends DispatchMethodOrAccessorCall, TDispatchAccessorCall { + private class DispatchAccessorCall extends DispatchOverridableCall, TDispatchAccessorCall { override AccessorCall getCall() { this = TDispatchAccessorCall(result) } override Expr getArgument(int i) { result = this.getCall().getArgument(i) } @@ -805,7 +832,7 @@ private module Internal { override Accessor getAStaticTarget() { result = this.getCall().getTarget() } override RuntimeAccessor getADynamicTarget() { - result = DispatchMethodOrAccessorCall.super.getADynamicTarget() and + result = DispatchOverridableCall.super.getADynamicTarget() and // Calls to accessors may have `dynamic` expression arguments, // so we need to check that the types match forall(Type argumentType, int i | this.hasDynamicArg(i, argumentType) | @@ -829,7 +856,7 @@ private module Internal { pragma[nomagic] private predicate hasQualifierType(Type qualifierType, boolean isExactType) { - exists(Type t | t = getAPossibleType(this.getQualifier(), isExactType) | + exists(Type t | t = getAPossibleType(this.getSyntheticQualifier(), isExactType) | qualifierType = t and not t instanceof TypeParameter or @@ -1115,7 +1142,8 @@ private module Internal { /** A call using reflection. */ private class DispatchReflectionCall extends DispatchReflectionOrDynamicCall, - TDispatchReflectionCall { + TDispatchReflectionCall + { override MethodCall getCall() { this = TDispatchReflectionCall(result, _, _, _, _) } override string getName() { this = TDispatchReflectionCall(_, result, _, _, _) } @@ -1163,7 +1191,8 @@ private module Internal { /** A method call using dynamic types. */ private class DispatchDynamicMethodCall extends DispatchReflectionOrDynamicCall, - TDispatchDynamicMethodCall { + TDispatchDynamicMethodCall + { override DynamicMethodCall getCall() { this = TDispatchDynamicMethodCall(result) } override string getName() { result = this.getCall().getLateBoundTargetName() } @@ -1184,7 +1213,8 @@ private module Internal { /** An operator call using dynamic types. */ private class DispatchDynamicOperatorCall extends DispatchReflectionOrDynamicCall, - TDispatchDynamicOperatorCall { + TDispatchDynamicOperatorCall + { override DynamicOperatorCall getCall() { this = TDispatchDynamicOperatorCall(result) } override string getName() { @@ -1201,7 +1231,8 @@ private module Internal { /** A (potential) call to a property accessor using dynamic types. */ private class DispatchDynamicMemberAccess extends DispatchReflectionOrDynamicCall, - TDispatchDynamicMemberAccess { + TDispatchDynamicMemberAccess + { override DynamicMemberAccess getCall() { this = TDispatchDynamicMemberAccess(result) } override string getName() { @@ -1225,7 +1256,8 @@ private module Internal { /** A (potential) call to an indexer accessor using dynamic types. */ private class DispatchDynamicElementAccess extends DispatchReflectionOrDynamicCall, - TDispatchDynamicElementAccess { + TDispatchDynamicElementAccess + { override DynamicElementAccess getCall() { this = TDispatchDynamicElementAccess(result) } override string getName() { @@ -1251,7 +1283,8 @@ private module Internal { /** A (potential) call to an event accessor using dynamic types. */ private class DispatchDynamicEventAccess extends DispatchReflectionOrDynamicCall, - TDispatchDynamicEventAccess { + TDispatchDynamicEventAccess + { override AssignArithmeticOperation getCall() { this = TDispatchDynamicEventAccess(result, _, _) } @@ -1268,7 +1301,8 @@ private module Internal { /** A call to a constructor using dynamic types. */ private class DispatchDynamicObjectCreation extends DispatchReflectionOrDynamicCall, - TDispatchDynamicObjectCreation { + TDispatchDynamicObjectCreation + { override DynamicObjectCreation getCall() { this = TDispatchDynamicObjectCreation(result) } override string getName() { none() } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll index ffb14f1e915..9905f4939b3 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/OverridableCallable.qll @@ -162,12 +162,6 @@ class OverridableCallable extends Callable, Overridable { } } -/** An overridable method. */ -deprecated class OverridableMethod extends Method, OverridableCallable { } - -/** An overridable accessor. */ -deprecated class OverridableAccessor extends Accessor, OverridableCallable { } - /** An unbound type. */ class UnboundDeclarationType extends Type { UnboundDeclarationType() { this.isUnboundDeclaration() } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll index eda31432f38..04ea9f062a5 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Dynamic.qll @@ -190,7 +190,8 @@ class DynamicAccess extends DynamicExpr { * property, or an event). */ class DynamicMemberAccess extends DynamicAccess, MemberAccess, AssignableAccess, - @dynamic_member_access_expr { + @dynamic_member_access_expr +{ override string toString() { result = "dynamic access to member " + this.getLateBoundTargetName() } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll index c35db06d214..77022bc4ab3 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/EntityFramework.qll @@ -432,7 +432,8 @@ module EntityFramework { } } - private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack { + private class DbContextSaveChangesRequiredSummaryComponentStack extends RequiredSummaryComponentStack + { override predicate required(SummaryComponent head, SummaryComponentStack tail) { exists(Content c | head = SummaryComponent::content(c) | any(DbContextClass cls).requiresComponentStackIn(c, _, tail, _) diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/Diagnostics.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/Diagnostics.qll index 81a620c9e7c..14d7497ec33 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/Diagnostics.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/Diagnostics.qll @@ -74,7 +74,8 @@ class SystemDiagnosticsProcessClass extends SystemDiagnosticsClass { } /** The `System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute` class. */ -class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAttributeClass extends SystemDiagnosticsCodeAnalysisClass { +class SystemDiagnosticsCodeAnalysisDoesNotReturnIfAttributeClass extends SystemDiagnosticsCodeAnalysisClass +{ SystemDiagnosticsCodeAnalysisDoesNotReturnIfAttributeClass() { this.hasName("DoesNotReturnIfAttribute") } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll index 260fe6d0318..bc1b514e0d1 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Generic.qll @@ -33,7 +33,8 @@ class SystemCollectionsGenericUnboundGenericStruct extends UnboundGenericStruct } /** The `System.Collections.Generic.IComparer<>` interface. */ -class SystemCollectionsGenericIComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIComparerTInterface() { this.hasName("IComparer<>") } /** Gets the `int Compare(T, T)` method. */ @@ -48,7 +49,8 @@ class SystemCollectionsGenericIComparerTInterface extends SystemCollectionsGener } /** The `System.Collections.Generic.IEqualityComparer<>` interface. */ -class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIEqualityComparerTInterface() { this.hasName("IEqualityComparer<>") } /** Gets the `bool Equals(T, T)` method. */ @@ -63,7 +65,8 @@ class SystemCollectionsGenericIEqualityComparerTInterface extends SystemCollecti } /** The `System.Collections.Generic.IEnumerable<>` interface. */ -class SystemCollectionsGenericIEnumerableTInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIEnumerableTInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIEnumerableTInterface() { this.hasName("IEnumerable<>") and this.getNumberOfTypeParameters() = 1 @@ -71,7 +74,8 @@ class SystemCollectionsGenericIEnumerableTInterface extends SystemCollectionsGen } /** The `System.Collections.Generic.IEnumerator<>` interface. */ -class SystemCollectionsGenericIEnumeratorInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIEnumeratorInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIEnumeratorInterface() { this.hasName("IEnumerator<>") and this.getNumberOfTypeParameters() = 1 @@ -86,7 +90,8 @@ class SystemCollectionsGenericIEnumeratorInterface extends SystemCollectionsGene } /** The `System.Collections.Generic.IList<>` interface. */ -class SystemCollectionsGenericIListTInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIListTInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIListTInterface() { this.hasName("IList<>") and this.getNumberOfTypeParameters() = 1 @@ -102,7 +107,8 @@ class SystemCollectionsGenericListClass extends SystemCollectionsGenericUnboundG } /** The `System.Collections.Generic.KeyValuePair<,>` structure. */ -class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGenericUnboundGenericStruct { +class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGenericUnboundGenericStruct +{ SystemCollectionsGenericKeyValuePairStruct() { this.hasName("KeyValuePair<,>") and this.getNumberOfTypeParameters() = 2 @@ -124,7 +130,8 @@ class SystemCollectionsGenericKeyValuePairStruct extends SystemCollectionsGeneri } /** The `System.Collections.Generic.ICollection<>` interface. */ -class SystemCollectionsGenericICollectionInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericICollectionInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericICollectionInterface() { this.hasName("ICollection<>") } /** Gets the `Count` property. */ @@ -138,12 +145,14 @@ class SystemCollectionsGenericICollectionInterface extends SystemCollectionsGene } /** The `System.Collections.Generic.IList<>` interface. */ -class SystemCollectionsGenericIListInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIListInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIListInterface() { this.hasName("IList<>") } } /** The `System.Collections.Generic.IDictionary<>` interface. */ -class SystemCollectionsGenericIDictionaryInterface extends SystemCollectionsGenericUnboundGenericInterface { +class SystemCollectionsGenericIDictionaryInterface extends SystemCollectionsGenericUnboundGenericInterface +{ SystemCollectionsGenericIDictionaryInterface() { this.hasName("IDictionary<,>") and this.getNumberOfTypeParameters() = 2 diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Specialized.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Specialized.qll index 2ddac761c4b..07ec6b1213c 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Specialized.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/collections/Specialized.qll @@ -19,6 +19,7 @@ class SystemCollectionsSpecializedClass extends Class { } /** The `System.Collections.Specialized.NameValueCollection` class. */ -class SystemCollectionsSpecializedNameValueCollectionClass extends SystemCollectionsSpecializedClass { +class SystemCollectionsSpecializedNameValueCollectionClass extends SystemCollectionsSpecializedClass +{ SystemCollectionsSpecializedNameValueCollectionClass() { this.hasName("NameValueCollection") } } diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll index 9ae5ec90b24..f8d6139d30d 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/runtime/CompilerServices.qll @@ -20,7 +20,8 @@ class SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct extends Unbound } /** The `System.Runtime.CompilerServices.TaskAwaiter<>` struct. */ -class SystemRuntimeCompilerServicesTaskAwaiterStruct extends SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct { +class SystemRuntimeCompilerServicesTaskAwaiterStruct extends SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct +{ SystemRuntimeCompilerServicesTaskAwaiterStruct() { this.hasName("TaskAwaiter<>") } /** Gets the `GetResult` method. */ @@ -31,7 +32,8 @@ class SystemRuntimeCompilerServicesTaskAwaiterStruct extends SystemRuntimeCompil } /** The `System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>` struct. */ -class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTStruct extends SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct { +class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTStruct extends SystemRuntimeCompilerServicesNamespaceUnboundGenericStruct +{ SystemRuntimeCompilerServicesConfiguredTaskAwaitableTStruct() { this.hasName("ConfiguredTaskAwaitable<>") } @@ -55,7 +57,8 @@ private class SyntheticConfiguredTaskAwaiterField extends SyntheticField { } /** The `System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>.ConfiguredTaskAwaiter` struct. */ -class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTConfiguredTaskAwaiterStruct extends Struct { +class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTConfiguredTaskAwaiterStruct extends Struct +{ SystemRuntimeCompilerServicesConfiguredTaskAwaitableTConfiguredTaskAwaiterStruct() { this = any(SystemRuntimeCompilerServicesConfiguredTaskAwaitableTStruct n).getANestedType() and this.hasName("ConfiguredTaskAwaiter") diff --git a/csharp/ql/lib/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll b/csharp/ql/lib/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll index 54cc8d11864..5e7bcd2b5d7 100644 --- a/csharp/ql/lib/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll +++ b/csharp/ql/lib/semmle/code/csharp/frameworks/system/security/cryptography/X509Certificates.qll @@ -22,7 +22,8 @@ class SystemSecurityCryptographyX509CertificatesClass extends Class { * The `X509Certificate` or `X509Certificate2` class in the namespace * `System.Security.Cryptography.X509Certificates`. */ -class SystemSecurityCryptographyX509CertificatesX509CertificateClass extends SystemSecurityCryptographyX509CertificatesClass { +class SystemSecurityCryptographyX509CertificatesX509CertificateClass extends SystemSecurityCryptographyX509CertificatesClass +{ SystemSecurityCryptographyX509CertificatesX509CertificateClass() { this.hasName("X509Certificate") or this.hasName("X509Certificate2") diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll index 9f1deaa3854..3ccc1f64fd4 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/UnsafeDeserializationQuery.qll @@ -299,7 +299,8 @@ private predicate isDataContractJsonSerializerCall(MethodCall mc, Method m) { abstract private class DataContractJsonSerializerSink extends InstanceMethodSink { } -private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink { +private class DataContractJsonSerializerDeserializeMethodSink extends DataContractJsonSerializerSink +{ DataContractJsonSerializerDeserializeMethodSink() { exists(MethodCall mc | isDataContractJsonSerializerCall(mc, _) and @@ -308,7 +309,8 @@ private class DataContractJsonSerializerDeserializeMethodSink extends DataContra } } -private class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class DataContractJsonSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ DataContractJsonSafeConstructorTrackingConfiguration() { this = "DataContractJsonSafeConstructorTrackingConfiguration" } @@ -357,7 +359,8 @@ private class JavaScriptSerializerDeserializeMethodSink extends JavaScriptSerial } } -private class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class JavaScriptSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ JavaScriptSerializerSafeConstructorTrackingConfiguration() { this = "JavaScriptSerializerSafeConstructorTrackingConfiguration" } @@ -400,7 +403,8 @@ private class XmlObjectSerializerDeserializeMethodSink extends XmlObjectSerializ } } -private class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class XmlObjectSerializerDerivedConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ XmlObjectSerializerDerivedConstructorTrackingConfiguration() { this = "XmlObjectSerializerDerivedConstructorTrackingConfiguration" } @@ -445,7 +449,8 @@ private class XmlSerializerDeserializeMethodSink extends XmlSerializerSink { } } -private class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class XmlSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ XmlSerializerSafeConstructorTrackingConfiguration() { this = "XmlSerializerSafeConstructorTrackingConfiguration" } @@ -492,7 +497,8 @@ private class DataContractSerializerDeserializeMethodSink extends DataContractSe } } -private class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class DataContractSerializerSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ DataContractSerializerSafeConstructorTrackingConfiguration() { this = "DataContractSerializerSafeConstructorTrackingConfiguration" } @@ -535,7 +541,8 @@ private class XmlMessageFormatterDeserializeMethodSink extends XmlMessageFormatt } } -private class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig { +private class XmlMessageFormatterSafeConstructorTrackingConfiguration extends SafeConstructorTrackingConfig +{ XmlMessageFormatterSafeConstructorTrackingConfiguration() { this = "XmlMessageFormatterSafeConstructorTrackingConfiguration" } @@ -717,7 +724,8 @@ private class SweetJaysonDeserializeMethodSink extends SweetJaysonSink { /** ServiceStack.Text.JsonSerializer */ abstract private class ServiceStackTextJsonSerializerSink extends ConstructorOrStaticMethodSink { } -private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink { +private class ServiceStackTextJsonSerializerDeserializeMethodSink extends ServiceStackTextJsonSerializerSink +{ ServiceStackTextJsonSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -741,7 +749,8 @@ private class ServiceStackTextJsonSerializerDeserializeMethodSink extends Servic /** ServiceStack.Text.TypeSerializer */ abstract private class ServiceStackTextTypeSerializerSink extends ConstructorOrStaticMethodSink { } -private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink { +private class ServiceStackTextTypeSerializerDeserializeMethodSink extends ServiceStackTextTypeSerializerSink +{ ServiceStackTextTypeSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -765,7 +774,8 @@ private class ServiceStackTextTypeSerializerDeserializeMethodSink extends Servic /** ServiceStack.Text.CsvSerializer */ abstract private class ServiceStackTextCsvSerializerSink extends ConstructorOrStaticMethodSink { } -private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink { +private class ServiceStackTextCsvSerializerDeserializeMethodSink extends ServiceStackTextCsvSerializerSink +{ ServiceStackTextCsvSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and @@ -789,7 +799,8 @@ private class ServiceStackTextCsvSerializerDeserializeMethodSink extends Service /** ServiceStack.Text.XmlSerializer */ abstract private class ServiceStackTextXmlSerializerSink extends ConstructorOrStaticMethodSink { } -private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink { +private class ServiceStackTextXmlSerializerDeserializeMethodSink extends ServiceStackTextXmlSerializerSink +{ ServiceStackTextXmlSerializerDeserializeMethodSink() { exists(MethodCall mc, Method m | m = mc.getTarget() and diff --git a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll index 6243074cf17..404730ac4c4 100644 --- a/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll +++ b/csharp/ql/lib/semmle/code/csharp/security/dataflow/flowsources/Remote.qll @@ -75,7 +75,8 @@ class AspNetQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, DataFlow /** A data flow source of remote user input (ASP.NET unvalidated request data). */ class AspNetUnvalidatedQueryStringRemoteFlowSource extends AspNetRemoteFlowSource, - DataFlow::ExprNode { + DataFlow::ExprNode +{ AspNetUnvalidatedQueryStringRemoteFlowSource() { this.getExpr() = any(SystemWebUnvalidatedRequestValues c).getAProperty().getGetter().getACall() or this.getExpr() = diff --git a/csharp/ql/src/CHANGELOG.md b/csharp/ql/src/CHANGELOG.md index 15b14e1e20d..b75d77162f4 100644 --- a/csharp/ql/src/CHANGELOG.md +++ b/csharp/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.4 + +No user-facing changes. + ## 0.5.3 No user-facing changes. diff --git a/csharp/ql/src/Stubs/Stubs.qll b/csharp/ql/src/Stubs/Stubs.qll index e4787a9b5ce..78cd18c34ec 100644 --- a/csharp/ql/src/Stubs/Stubs.qll +++ b/csharp/ql/src/Stubs/Stubs.qll @@ -120,15 +120,6 @@ abstract private class GeneratedType extends Type, GeneratedElement { else result = "" } - private string stubComment() { - exists(string qualifier, string name | - this.hasQualifiedName(qualifier, name) and - result = - "// Generated from `" + getQualifiedName(qualifier, name) + "` in `" + - concat(this.getALocation().toString(), "; ") + "`\n" - ) - } - /** Gets the entire C# stub code for this type. */ pragma[nomagic] final string getStub(Assembly assembly) { @@ -141,17 +132,16 @@ abstract private class GeneratedType extends Type, GeneratedElement { else ( not this instanceof DelegateType and result = - this.stubComment() + this.stubAttributes() + stubAccessibility(this) + + this.stubAttributes() + stubUnsafe(this) + stubAccessibility(this) + this.stubAbstractModifier() + this.stubStaticModifier() + this.stubPartialModifier() + this.stubKeyword() + " " + this.getUndecoratedName() + stubGenericArguments(this) + this.stubBaseTypesString() + stubTypeParametersConstraints(this) + "\n{\n" + this.stubPrivateConstructor() + this.stubMembers(assembly) + "}\n\n" or result = - this.stubComment() + this.stubAttributes() + stubUnsafe(this) + stubAccessibility(this) + - this.stubKeyword() + " " + stubClassName(this.(DelegateType).getReturnType()) + " " + - this.getUndecoratedName() + stubGenericArguments(this) + "(" + stubParameters(this) + - ");\n\n" + this.stubAttributes() + stubUnsafe(this) + stubAccessibility(this) + this.stubKeyword() + + " " + stubClassName(this.(DelegateType).getReturnType()) + " " + this.getUndecoratedName() + + stubGenericArguments(this) + "(" + stubParameters(this) + ");\n\n" ) } @@ -400,7 +390,7 @@ private string stubAccessibility(Member m) { if m.getDeclaringType() instanceof Interface or - exists(m.(Virtualizable).getExplicitlyImplementedInterface()) + exists(getExplicitImplementedInterface(m)) or m instanceof Constructor and m.isStatic() then result = "" @@ -443,7 +433,7 @@ private string stubStaticOrConst(Member m) { } private string stubOverride(Member m) { - if m.getDeclaringType() instanceof Interface + if m.getDeclaringType() instanceof Interface and not m.isStatic() then result = "" else if m.(Virtualizable).isVirtual() @@ -713,9 +703,49 @@ private string stubEventAccessors(Event e) { else result = ";" } +/** + * Returns an interface that `c` explicitly implements, if either of the + * following also holds. + * (1) `c` is not static. + * (2) `c` is static and an implementation of a generic with type constraints. + * (3) `c` is static and there is another member with the same name + * but different return type. + * + * We use these rules as explicit interfaces are needed in some cases + * for compilation purposes (both to distinguish members but also to ensure + * type constraints are satisfied). We can't always use explicit interface + * implementation due to the generic math support, because then in some cases + * we will only be able to access a static via a type variable with type + * constraints (C# 11 language feature). + */ +private Interface getExplicitImplementedInterface(Virtualizable c) { + result = unique(Interface i | i = c.getExplicitlyImplementedInterface()) and + ( + not c.isStatic() + or + c.isStatic() and + ( + not c instanceof Method + or + c instanceof Method and + ( + exists(TypeParameter t | t = c.getImplementee().(UnboundGeneric).getATypeParameter() | + exists(t.getConstraints().getATypeConstraint()) + ) + or + exists(Member m | + (not m.isStatic() or m.(Method).getReturnType() != c.(Method).getReturnType()) and + m.getName() = c.getName() and + m.getDeclaringType() = c.getDeclaringType() + ) + ) + ) + ) +} + private string stubExplicitImplementation(Member c) { - if exists(c.(Virtualizable).getExplicitlyImplementedInterface()) - then result = stubClassName(c.(Virtualizable).getExplicitlyImplementedInterface()) + "." + if exists(getExplicitImplementedInterface(c)) + then result = stubClassName(getExplicitImplementedInterface(c)) + "." else result = "" } @@ -740,14 +770,16 @@ private string stubOperator(Operator o, Assembly assembly) { if o instanceof ConversionOperator then result = - " " + stubModifiers(o) + stubExplicit(o) + "operator " + stubClassName(o.getReturnType()) + - "(" + stubParameters(o) + ") => throw null;\n" + " " + stubModifiers(o) + stubExplicit(o) + stubExplicitImplementation(o) + "operator " + + stubChecked(o) + stubClassName(o.getReturnType()) + "(" + stubParameters(o) + ")" + + stubImplementation(o) + ";\n" else if not o.getDeclaringType() instanceof Enum then result = - " " + stubModifiers(o) + stubClassName(o.getReturnType()) + " operator " + o.getName() + - "(" + stubParameters(o) + ") => throw null;\n" + " " + stubModifiers(o) + stubClassName(o.getReturnType()) + " " + + stubExplicitImplementation(o) + "operator " + o.getName() + "(" + stubParameters(o) + ")" + + stubImplementation(o) + ";\n" else result = " // Stub generator skipped operator: " + o.getName() + "\n" } @@ -888,7 +920,16 @@ private string stubConstructorInitializer(Constructor c) { private string stubExplicit(ConversionOperator op) { op instanceof ImplicitConversionOperator and result = "implicit " or - op instanceof ExplicitConversionOperator and result = "explicit " + ( + op instanceof ExplicitConversionOperator + or + op instanceof CheckedExplicitConversionOperator + ) and + result = "explicit " +} + +private string stubChecked(Operator o) { + if o instanceof CheckedExplicitConversionOperator then result = "checked " else result = "" } private string stubGetter(DeclarationWithGetSetAccessors p) { @@ -917,6 +958,8 @@ private string stubSemmleExtractorOptions() { /** Gets the generated C# code. */ string generatedCode(Assembly assembly) { result = - "// This file contains auto-generated code.\n" + stubSemmleExtractorOptions() + "\n" + - any(GeneratedNamespace ns | ns.isGlobalNamespace()).getStubs(assembly) + "// This file contains auto-generated code.\n" // + + "// Generated from `" + assembly.getFullName() + "`.\n" // + + stubSemmleExtractorOptions() + "\n" // + + any(GeneratedNamespace ns | ns.isGlobalNamespace()).getStubs(assembly) } diff --git a/csharp/ql/src/Stubs/make_stubs_nuget.py b/csharp/ql/src/Stubs/make_stubs_nuget.py index 2e7d093beba..09aadc366fc 100644 --- a/csharp/ql/src/Stubs/make_stubs_nuget.py +++ b/csharp/ql/src/Stubs/make_stubs_nuget.py @@ -109,7 +109,7 @@ with open(jsonFile) as json_data: print("\n --> Generated stub files: " + rawSrcOutputDir) print("\n* Formatting files") -run_cmd(['dotnet', 'format', rawSrcOutputDir]) +run_cmd(['dotnet', 'format', 'whitespace', rawSrcOutputDir]) print("\n --> Generated (formatted) stub files: " + rawSrcOutputDir) diff --git a/csharp/ql/src/change-notes/released/0.5.4.md b/csharp/ql/src/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..1686ab4354d --- /dev/null +++ b/csharp/ql/src/change-notes/released/0.5.4.md @@ -0,0 +1,3 @@ +## 0.5.4 + +No user-facing changes. diff --git a/csharp/ql/src/codeql-pack.release.yml b/csharp/ql/src/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/csharp/ql/src/codeql-pack.release.yml +++ b/csharp/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/JsonWebTokenHandlerLib.qll b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/JsonWebTokenHandlerLib.qll index 636400ceb33..8b2c28a4a06 100644 --- a/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/JsonWebTokenHandlerLib.qll +++ b/csharp/ql/src/experimental/Security Features/JsonWebTokenHandler/JsonWebTokenHandlerLib.qll @@ -21,7 +21,8 @@ class TokenValidationParametersPropertySensitiveValidation extends Property { /** * A dataflow from a `false` value to a write sensitive property for `TokenValidationParameters`. */ -class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation extends DataFlow::Configuration { +class FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation extends DataFlow::Configuration +{ FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation() { this = "FalseValueFlowsToTokenValidationParametersPropertyWriteToBypassValidation" } @@ -219,7 +220,8 @@ class CallableAlwaysReturnsParameter0 extends CallableReturnsStringAndArg0IsStri /** * A Callable that always return the 1st argument, both of `string` type. Higher precision */ -class CallableAlwaysReturnsParameter0MayThrowExceptions extends CallableReturnsStringAndArg0IsString { +class CallableAlwaysReturnsParameter0MayThrowExceptions extends CallableReturnsStringAndArg0IsString +{ CallableAlwaysReturnsParameter0MayThrowExceptions() { forex(Expr ret | this.canReturn(ret) | ret = this.getParameter(0).getAnAccess() diff --git a/csharp/ql/src/experimental/Security Features/backdoor/PotentialTimeBomb.ql b/csharp/ql/src/experimental/Security Features/backdoor/PotentialTimeBomb.ql index 7f1d48788db..d493bdd7e27 100644 --- a/csharp/ql/src/experimental/Security Features/backdoor/PotentialTimeBomb.ql +++ b/csharp/ql/src/experimental/Security Features/backdoor/PotentialTimeBomb.ql @@ -80,7 +80,8 @@ class DateTimeStruct extends Struct { /** * Dataflow configuration to find flow from a GetLastWriteTime source to a DateTime arithmetic operation */ -private class FlowsFromGetLastWriteTimeConfigToTimeSpanArithmeticCallable extends TaintTracking::Configuration { +private class FlowsFromGetLastWriteTimeConfigToTimeSpanArithmeticCallable extends TaintTracking::Configuration +{ FlowsFromGetLastWriteTimeConfigToTimeSpanArithmeticCallable() { this = "FlowsFromGetLastWriteTimeConfigToTimeSpanArithmeticCallable" } @@ -103,7 +104,8 @@ private class FlowsFromGetLastWriteTimeConfigToTimeSpanArithmeticCallable extend /** * Dataflow configuration to find flow from a DateTime arithmetic operation to a DateTime comparison operation */ -private class FlowsFromTimeSpanArithmeticToTimeComparisonCallable extends TaintTracking::Configuration { +private class FlowsFromTimeSpanArithmeticToTimeComparisonCallable extends TaintTracking::Configuration +{ FlowsFromTimeSpanArithmeticToTimeComparisonCallable() { this = "FlowsFromTimeSpanArithmeticToTimeComparisonCallable" } @@ -125,7 +127,8 @@ private class FlowsFromTimeSpanArithmeticToTimeComparisonCallable extends TaintT /** * Dataflow configuration to find flow from a DateTime comparison operation to a Selection Statement (such as an If) */ -private class FlowsFromTimeComparisonCallableToSelectionStatementCondition extends TaintTracking::Configuration { +private class FlowsFromTimeComparisonCallableToSelectionStatementCondition extends TaintTracking::Configuration +{ FlowsFromTimeComparisonCallableToSelectionStatementCondition() { this = "FlowsFromTimeComparisonCallableToSelectionStatementCondition" } diff --git a/csharp/ql/src/experimental/ir/implementation/Opcode.qll b/csharp/ql/src/experimental/ir/implementation/Opcode.qll index b4def7fe4ae..7b064340ffe 100644 --- a/csharp/ql/src/experimental/ir/implementation/Opcode.qll +++ b/csharp/ql/src/experimental/ir/implementation/Opcode.qll @@ -1082,7 +1082,8 @@ module Opcode { * See the `CallSideEffectInstruction` documentation for more details. */ class CallSideEffect extends WriteSideEffectOpcode, EscapedWriteOpcode, MayWriteOpcode, - ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect { + ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, TCallSideEffect + { final override string toString() { result = "CallSideEffect" } } @@ -1092,7 +1093,8 @@ module Opcode { * See the `CallReadSideEffectInstruction` documentation for more details. */ class CallReadSideEffect extends ReadSideEffectOpcode, EscapedReadOpcode, MayReadOpcode, - TCallReadSideEffect { + TCallReadSideEffect + { final override string toString() { result = "CallReadSideEffect" } } @@ -1102,7 +1104,8 @@ module Opcode { * See the `IndirectReadSideEffectInstruction` documentation for more details. */ class IndirectReadSideEffect extends ReadSideEffectOpcode, IndirectReadOpcode, - TIndirectReadSideEffect { + TIndirectReadSideEffect + { final override string toString() { result = "IndirectReadSideEffect" } } @@ -1112,7 +1115,8 @@ module Opcode { * See the `IndirectMustWriteSideEffectInstruction` documentation for more details. */ class IndirectMustWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, - TIndirectMustWriteSideEffect { + TIndirectMustWriteSideEffect + { final override string toString() { result = "IndirectMustWriteSideEffect" } } @@ -1122,7 +1126,8 @@ module Opcode { * See the `IndirectMayWriteSideEffectInstruction` documentation for more details. */ class IndirectMayWriteSideEffect extends WriteSideEffectOpcode, IndirectWriteOpcode, - MayWriteOpcode, TIndirectMayWriteSideEffect { + MayWriteOpcode, TIndirectMayWriteSideEffect + { final override string toString() { result = "IndirectMayWriteSideEffect" } } @@ -1132,7 +1137,8 @@ module Opcode { * See the `BufferReadSideEffectInstruction` documentation for more details. */ class BufferReadSideEffect extends ReadSideEffectOpcode, UnsizedBufferReadOpcode, - TBufferReadSideEffect { + TBufferReadSideEffect + { final override string toString() { result = "BufferReadSideEffect" } } @@ -1142,7 +1148,8 @@ module Opcode { * See the `BufferMustWriteSideEffectInstruction` documentation for more details. */ class BufferMustWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, - TBufferMustWriteSideEffect { + TBufferMustWriteSideEffect + { final override string toString() { result = "BufferMustWriteSideEffect" } } @@ -1152,7 +1159,8 @@ module Opcode { * See the `BufferMayWriteSideEffectInstruction` documentation for more details. */ class BufferMayWriteSideEffect extends WriteSideEffectOpcode, UnsizedBufferWriteOpcode, - MayWriteOpcode, TBufferMayWriteSideEffect { + MayWriteOpcode, TBufferMayWriteSideEffect + { final override string toString() { result = "BufferMayWriteSideEffect" } } @@ -1162,7 +1170,8 @@ module Opcode { * See the `SizedBufferReadSideEffectInstruction` documentation for more details. */ class SizedBufferReadSideEffect extends ReadSideEffectOpcode, SizedBufferReadOpcode, - TSizedBufferReadSideEffect { + TSizedBufferReadSideEffect + { final override string toString() { result = "SizedBufferReadSideEffect" } } @@ -1172,7 +1181,8 @@ module Opcode { * See the `SizedBufferMustWriteSideEffectInstruction` documentation for more details. */ class SizedBufferMustWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, - TSizedBufferMustWriteSideEffect { + TSizedBufferMustWriteSideEffect + { final override string toString() { result = "SizedBufferMustWriteSideEffect" } } @@ -1182,7 +1192,8 @@ module Opcode { * See the `SizedBufferMayWriteSideEffectInstruction` documentation for more details. */ class SizedBufferMayWriteSideEffect extends WriteSideEffectOpcode, SizedBufferWriteOpcode, - MayWriteOpcode, TSizedBufferMayWriteSideEffect { + MayWriteOpcode, TSizedBufferMayWriteSideEffect + { final override string toString() { result = "SizedBufferMayWriteSideEffect" } } @@ -1192,7 +1203,8 @@ module Opcode { * See the `InitializeDynamicAllocationInstruction` documentation for more details. */ class InitializeDynamicAllocation extends SideEffectOpcode, EntireAllocationWriteOpcode, - TInitializeDynamicAllocation { + TInitializeDynamicAllocation + { final override string toString() { result = "InitializeDynamicAllocation" } } @@ -1221,7 +1233,8 @@ module Opcode { * See the `InlineAsmInstruction` documentation for more details. */ class InlineAsm extends Opcode, EscapedWriteOpcode, MayWriteOpcode, EscapedReadOpcode, - MayReadOpcode, TInlineAsm { + MayReadOpcode, TInlineAsm + { final override string toString() { result = "InlineAsm" } final override predicate hasOperandInternal(OperandTag tag) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll index 01405b08e80..edc785dfabe 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll @@ -1,6 +1,7 @@ private import IR import InstructionConsistency // module is below import IRTypeConsistency // module is in IRType.qll +import internal.IRConsistencyImports module InstructionConsistency { private import internal.InstructionImports as Imports @@ -28,7 +29,7 @@ module InstructionConsistency { PresentIRFunction() { this = TPresentIRFunction(irFunc) } override string toString() { - result = concat(Language::getIdentityString(irFunc.getFunction()), "; ") + result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ") } override Language::Location getLocation() { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll index 4bd58e6b96a..c1743acdbae 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Operand.qll @@ -87,22 +87,6 @@ class Operand extends TStageOperand { this.getDefinitionOverlap() instanceof MustExactlyOverlap } - /** - * DEPRECATED: renamed to `getUse`. - * - * Gets the `Instruction` that consumes this operand. - */ - deprecated final Instruction getUseInstruction() { result = this.getUse() } - - /** - * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this - * predicate is `getAnyDef`, but most uses of this predicate should probably - * be replaced with `getDef`. - * - * Gets the `Instruction` whose result is the value of the operand. - */ - deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } - /** * Gets the overlap relationship between the operand's definition and its use. */ diff --git a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll index 53cdc75512b..aae12b0047a 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll @@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction override Language::Location getLocation() { result = irFunc.getLocation() } - override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) } + override string getLabel() { + result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction()) + } override int getOrder() { this = diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConsistencyImports.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConsistencyImports.qll new file mode 100644 index 00000000000..f43546fe76d --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConsistencyImports.qll @@ -0,0 +1 @@ +import experimental.ir.internal.IRCSharpLanguageDebug as LanguageDebug diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll index 9a3e4c03646..0c5337d57de 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/PrintIRImports.qll @@ -1 +1,2 @@ import experimental.ir.IRConfiguration as IRConfiguration +import experimental.ir.internal.IRCSharpLanguageDebug as LanguageDebug diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll index fe555344b2f..43db3c90065 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedCondition.qll @@ -28,7 +28,8 @@ abstract class TranslatedCondition extends ConditionBase { } abstract class TranslatedFlexibleCondition extends TranslatedCondition, ConditionContext, - TTranslatedFlexibleCondition { + TTranslatedFlexibleCondition +{ TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) } final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() } @@ -156,7 +157,8 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation { } class TranslatedValueCondition extends TranslatedCondition, ValueConditionBase, - TTranslatedValueCondition { + TTranslatedValueCondition +{ TranslatedValueCondition() { this = TTranslatedValueCondition(expr) } override TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll index 74d72f4f438..20d2b1e3459 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedDeclaration.qll @@ -40,7 +40,8 @@ abstract class TranslatedLocalDeclaration extends TranslatedElement, TTranslated * including its initialization, if any. */ class TranslatedLocalVariableDeclaration extends TranslatedLocalDeclaration, - LocalVariableDeclarationBase, InitializationContext { + LocalVariableDeclarationBase, InitializationContext +{ LocalVariable var; TranslatedLocalVariableDeclaration() { var = expr.getVariable() } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll index 06391c010b4..67ebf19b766 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedExpr.qll @@ -119,7 +119,8 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { } class TranslatedConditionValue extends TranslatedCoreExpr, ConditionContext, - TTranslatedConditionValue { + TTranslatedConditionValue +{ TranslatedConditionValue() { this = TTranslatedConditionValue(expr) } override TranslatedElement getChild(int id) { id = 0 and result = this.getCondition() } @@ -1950,7 +1951,8 @@ class TranslatedDelegateCall extends TranslatedNonConstantExpr { * object is allocated, which is then initialized by the constructor. */ abstract class TranslatedCreation extends TranslatedCoreExpr, TTranslatedCreationExpr, - ConstructorCallContext { + ConstructorCallContext +{ TranslatedCreation() { this = TTranslatedCreationExpr(expr) } override TranslatedElement getChild(int id) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll index d5b287ddbde..bc127680ca4 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -276,7 +276,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement { * an explicit element in an initializer list. */ class TranslatedExplicitElementInitialization extends TranslatedElementInitialization, - TTranslatedExplicitElementInitialization, InitializationContext { + TTranslatedExplicitElementInitialization, InitializationContext +{ int elementIndex; TranslatedExplicitElementInitialization() { @@ -312,7 +313,8 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ // TODO: Possibly refactor into something simpler abstract class TranslatedConstructorCallFromConstructor extends TranslatedElement, - ConstructorCallContext { + ConstructorCallContext +{ Call call; final override Language::AST getAst() { result = call } @@ -344,7 +346,8 @@ TranslatedConstructorInitializer getTranslatedConstructorInitializer(Constructor */ // Review: do we need the conversion instructions in C#? class TranslatedConstructorInitializer extends TranslatedConstructorCallFromConstructor, - TTranslatedConstructorInitializer { + TTranslatedConstructorInitializer +{ TranslatedConstructorInitializer() { this = TTranslatedConstructorInitializer(call) } override string toString() { result = "constructor init: " + call.toString() } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Common.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Common.qll index 19b773c2622..dbc76ec3954 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Common.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Common.qll @@ -126,7 +126,8 @@ abstract class TranslatedCompilerGeneratedBlock extends TranslatedCompilerGenera * the body of the `then` and the body of the `else`. */ abstract class TranslatedCompilerGeneratedIfStmt extends TranslatedCompilerGeneratedStmt, - ConditionContext { + ConditionContext +{ override Instruction getFirstInstruction() { result = getCondition().getFirstInstruction() } override TranslatedElement getChild(int id) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Delegate.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Delegate.qll index 5e51073900e..4ce965aa1f0 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Delegate.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Delegate.qll @@ -45,7 +45,8 @@ module DelegateElements { * The translation of the constructor call that happens as part of the delegate creation. */ private class TranslatedDelegateConstructorCall extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override DelegateCreation generatedBy; TranslatedDelegateConstructorCall() { this = TTranslatedCompilerGeneratedElement(generatedBy, 0) } @@ -80,7 +81,8 @@ private class TranslatedDelegateConstructorCall extends TranslatedCompilerGenera * The translation of the invoke call that happens as part of the desugaring of the delegate call. */ private class TranslatedDelegateInvokeCall extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override DelegateCall generatedBy; TranslatedDelegateInvokeCall() { this = TTranslatedCompilerGeneratedElement(generatedBy, 1) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll index bc8ec748648..9be3c45d418 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Foreach.qll @@ -64,7 +64,8 @@ module ForeachElements { } private class TranslatedForeachTry extends TranslatedCompilerGeneratedTry, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachTry() { this = TTranslatedCompilerGeneratedElement(generatedBy, 0) } @@ -88,7 +89,8 @@ private class TranslatedForeachTry extends TranslatedCompilerGeneratedTry, * The translation of the finally block. */ private class TranslatedForeachFinally extends TranslatedCompilerGeneratedBlock, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachFinally() { this = TTranslatedCompilerGeneratedElement(generatedBy, 1) } @@ -108,7 +110,8 @@ private class TranslatedForeachFinally extends TranslatedCompilerGeneratedBlock, * to correctly mark which edges should be back edges. */ class TranslatedForeachWhile extends TranslatedCompilerGeneratedStmt, ConditionContext, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachWhile() { this = TTranslatedCompilerGeneratedElement(generatedBy, 2) } @@ -164,7 +167,8 @@ class TranslatedForeachWhile extends TranslatedCompilerGeneratedStmt, ConditionC * The translation of the call to the `MoveNext` method, used as a condition for the while. */ private class TranslatedForeachMoveNext extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachMoveNext() { this = TTranslatedCompilerGeneratedElement(generatedBy, 3) } @@ -192,7 +196,8 @@ private class TranslatedForeachMoveNext extends TranslatedCompilerGeneratedCall, * The translation of the call to retrieve the enumerator. */ private class TranslatedForeachGetEnumerator extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachGetEnumerator() { this = TTranslatedCompilerGeneratedElement(generatedBy, 4) } @@ -219,7 +224,8 @@ private class TranslatedForeachGetEnumerator extends TranslatedCompilerGenerated * The translation of the call to the getter method of the `Current` property of the enumerator. */ private class TranslatedForeachCurrent extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachCurrent() { this = TTranslatedCompilerGeneratedElement(generatedBy, 5) } @@ -247,7 +253,8 @@ private class TranslatedForeachCurrent extends TranslatedCompilerGeneratedCall, * The translation of the call to dispose (inside the finally block) */ private class TranslatedForeachDispose extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachDispose() { this = TTranslatedCompilerGeneratedElement(generatedBy, 6) } @@ -275,7 +282,8 @@ private class TranslatedForeachDispose extends TranslatedCompilerGeneratedCall, * The condition for the while, ie. a call to MoveNext. */ private class TranslatedForeachWhileCondition extends TranslatedCompilerGeneratedValueCondition, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachWhileCondition() { this = TTranslatedCompilerGeneratedElement(generatedBy, 7) } @@ -295,7 +303,8 @@ private class TranslatedForeachWhileCondition extends TranslatedCompilerGenerate * declaration of the `temporary` enumerator variable) */ private class TranslatedForeachEnumerator extends TranslatedCompilerGeneratedDeclaration, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachEnumerator() { this = TTranslatedCompilerGeneratedElement(generatedBy, 8) } @@ -323,7 +332,8 @@ private class TranslatedForeachEnumerator extends TranslatedCompilerGeneratedDec * Class that represents that translation of the declaration that's happening inside the body of the while. */ private class TranslatedForeachIterVar extends TranslatedCompilerGeneratedDeclaration, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override ForeachStmt generatedBy; TranslatedForeachIterVar() { this = TTranslatedCompilerGeneratedElement(generatedBy, 9) } @@ -352,7 +362,8 @@ private class TranslatedForeachIterVar extends TranslatedCompilerGeneratedDeclar * for the call to `MoveNext`. */ private class TranslatedMoveNextEnumAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override ForeachStmt generatedBy; TranslatedMoveNextEnumAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 10) } @@ -384,7 +395,8 @@ private class TranslatedMoveNextEnumAcc extends TTranslatedCompilerGeneratedElem * for the call to the getter of the property `Current`. */ private class TranslatedForeachCurrentEnumAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override ForeachStmt generatedBy; TranslatedForeachCurrentEnumAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 11) } @@ -416,7 +428,8 @@ private class TranslatedForeachCurrentEnumAcc extends TTranslatedCompilerGenerat * for the call to `Dispose`. */ private class TranslatedForeachDisposeEnumAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override ForeachStmt generatedBy; TranslatedForeachDisposeEnumAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 12) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Lock.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Lock.qll index bb1ab29e51c..484d11205cd 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Lock.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/Lock.qll @@ -57,7 +57,8 @@ module LockElements { * The translation of the `try` stmt. */ private class TranslatedLockTry extends TranslatedCompilerGeneratedTry, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedLockTry() { this = TTranslatedCompilerGeneratedElement(generatedBy, 0) } @@ -81,7 +82,8 @@ private class TranslatedLockTry extends TranslatedCompilerGeneratedTry, * The translation of the `lock` stmt's body. */ private class TranslatedLockTryBody extends TranslatedCompilerGeneratedBlock, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedLockTryBody() { this = TTranslatedCompilerGeneratedElement(generatedBy, 1) } @@ -102,7 +104,8 @@ private class TranslatedLockTryBody extends TranslatedCompilerGeneratedBlock, * The translation of the finally block. */ private class TranslatedLockFinally extends TranslatedCompilerGeneratedBlock, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedLockFinally() { this = TTranslatedCompilerGeneratedElement(generatedBy, 2) } @@ -120,7 +123,8 @@ private class TranslatedLockFinally extends TranslatedCompilerGeneratedBlock, * The translation of the call to dispose (inside the finally block) */ private class TranslatedMonitorExit extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedMonitorExit() { this = TTranslatedCompilerGeneratedElement(generatedBy, 3) } @@ -152,7 +156,8 @@ private class TranslatedMonitorExit extends TranslatedCompilerGeneratedCall, * The translation of the call to dispose (inside the finally block) */ private class TranslatedMonitorEnter extends TranslatedCompilerGeneratedCall, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedMonitorEnter() { this = TTranslatedCompilerGeneratedElement(generatedBy, 4) } @@ -190,7 +195,8 @@ private class TranslatedMonitorEnter extends TranslatedCompilerGeneratedCall, * The translation of the condition of the `if` present in the `finally` clause. */ private class TranslatedIfCondition extends TranslatedCompilerGeneratedValueCondition, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedIfCondition() { this = TTranslatedCompilerGeneratedElement(generatedBy, 5) } @@ -209,7 +215,8 @@ private class TranslatedIfCondition extends TranslatedCompilerGeneratedValueCond * The translation of the `if` stmt present in the `finally` clause. */ private class TranslatedFinallyIf extends TranslatedCompilerGeneratedIfStmt, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedFinallyIf() { this = TTranslatedCompilerGeneratedElement(generatedBy, 6) } @@ -236,7 +243,8 @@ private class TranslatedFinallyIf extends TranslatedCompilerGeneratedIfStmt, * bool temp variable. */ private class TranslatedWasTakenConst extends TranslatedCompilerGeneratedConstant, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedWasTakenConst() { this = TTranslatedCompilerGeneratedElement(generatedBy, 7) } @@ -255,7 +263,8 @@ private class TranslatedWasTakenConst extends TranslatedCompilerGeneratedConstan * Represents the translation of the `lockWasTaken` temp variable declaration. */ private class TranslatedLockWasTakenDecl extends TranslatedCompilerGeneratedDeclaration, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedLockWasTakenDecl() { this = TTranslatedCompilerGeneratedElement(generatedBy, 8) } @@ -286,7 +295,8 @@ private class TranslatedLockWasTakenDecl extends TranslatedCompilerGeneratedDecl * expression being locked. */ private class TranslatedLockedVarDecl extends TranslatedCompilerGeneratedDeclaration, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ override LockStmt generatedBy; TranslatedLockedVarDecl() { this = TTranslatedCompilerGeneratedElement(generatedBy, 9) } @@ -315,7 +325,8 @@ private class TranslatedLockedVarDecl extends TranslatedCompilerGeneratedDeclara * Used as an argument for the `MonitorEnter` call. */ private class TranslatedMonitorEnterVarAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override LockStmt generatedBy; TranslatedMonitorEnterVarAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 10) } @@ -341,7 +352,8 @@ private class TranslatedMonitorEnterVarAcc extends TTranslatedCompilerGeneratedE * Used as an argument for the `MonitorExit` call. */ private class TranslatedMonitorExitVarAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override LockStmt generatedBy; TranslatedMonitorExitVarAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 11) } @@ -366,7 +378,8 @@ private class TranslatedMonitorExitVarAcc extends TTranslatedCompilerGeneratedEl * Used as an argument for the `MonitorEnter` call. */ private class TranslatedLockWasTakenCondVarAcc extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override LockStmt generatedBy; TranslatedLockWasTakenCondVarAcc() { this = TTranslatedCompilerGeneratedElement(generatedBy, 12) } @@ -391,7 +404,8 @@ private class TranslatedLockWasTakenCondVarAcc extends TTranslatedCompilerGenera * as the `if` condition in the finally clause. */ private class TranslatedLockWasTakenRefArg extends TTranslatedCompilerGeneratedElement, - TranslatedCompilerGeneratedVariableAccess { + TranslatedCompilerGeneratedVariableAccess +{ override LockStmt generatedBy; TranslatedLockWasTakenRefArg() { this = TTranslatedCompilerGeneratedElement(generatedBy, 13) } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCall.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCall.qll index 28dfd2b4cc3..d1834f90c1c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCall.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCall.qll @@ -10,7 +10,8 @@ private import TranslatedCompilerGeneratedElement private import experimental.ir.internal.IRCSharpLanguage as Language abstract class TranslatedCompilerGeneratedCall extends TranslatedCallBase, - TranslatedCompilerGeneratedElement { + TranslatedCompilerGeneratedElement +{ final override string toString() { result = "compiler generated call (" + generatedBy.toString() + ")" } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCondition.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCondition.qll index df0bf1b24c6..57fdc12121c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCondition.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedCondition.qll @@ -9,7 +9,8 @@ private import TranslatedCompilerGeneratedElement private import experimental.ir.internal.IRCSharpLanguage as Language abstract class TranslatedCompilerGeneratedValueCondition extends TranslatedCompilerGeneratedElement, - ValueConditionBase { + ValueConditionBase +{ final override string toString() { result = "compiler generated condition (" + generatedBy.toString() + ")" } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedDeclaration.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedDeclaration.qll index 6757b032424..ead9a38fc5e 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedDeclaration.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedDeclaration.qll @@ -16,7 +16,8 @@ private import experimental.ir.internal.CSharpType private import experimental.ir.internal.IRCSharpLanguage as Language abstract class TranslatedCompilerGeneratedDeclaration extends LocalVariableDeclarationBase, - TranslatedCompilerGeneratedElement { + TranslatedCompilerGeneratedElement +{ final override string toString() { result = "compiler generated declaration (" + generatedBy.toString() + ")" } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedElement.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedElement.qll index ffcc400a9bc..7008187520c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedElement.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedElement.qll @@ -7,7 +7,8 @@ private import experimental.ir.implementation.raw.internal.TranslatedElement private import experimental.ir.internal.IRCSharpLanguage as Language abstract class TranslatedCompilerGeneratedElement extends TranslatedElement, - TTranslatedCompilerGeneratedElement { + TTranslatedCompilerGeneratedElement +{ // The element that generates generated the compiler element can // only be a stmt or an expr ControlFlowElement generatedBy; diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedExpr.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedExpr.qll index b7988c3fde8..3c5a60cf812 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedExpr.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/desugar/internal/TranslatedCompilerGeneratedExpr.qll @@ -10,7 +10,8 @@ private import experimental.ir.implementation.raw.internal.common.TranslatedExpr private import experimental.ir.internal.IRCSharpLanguage as Language abstract class TranslatedCompilerGeneratedExpr extends TranslatedCompilerGeneratedElement, - TranslatedExprBase { + TranslatedExprBase +{ override string toString() { result = "compiler generated expr (" + generatedBy.toString() + ")" } abstract Type getResultType(); diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll index 01405b08e80..edc785dfabe 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll @@ -1,6 +1,7 @@ private import IR import InstructionConsistency // module is below import IRTypeConsistency // module is in IRType.qll +import internal.IRConsistencyImports module InstructionConsistency { private import internal.InstructionImports as Imports @@ -28,7 +29,7 @@ module InstructionConsistency { PresentIRFunction() { this = TPresentIRFunction(irFunc) } override string toString() { - result = concat(Language::getIdentityString(irFunc.getFunction()), "; ") + result = concat(LanguageDebug::getIdentityString(irFunc.getFunction()), "; ") } override Language::Location getLocation() { 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 4bd58e6b96a..c1743acdbae 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Operand.qll @@ -87,22 +87,6 @@ class Operand extends TStageOperand { this.getDefinitionOverlap() instanceof MustExactlyOverlap } - /** - * DEPRECATED: renamed to `getUse`. - * - * Gets the `Instruction` that consumes this operand. - */ - deprecated final Instruction getUseInstruction() { result = this.getUse() } - - /** - * DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this - * predicate is `getAnyDef`, but most uses of this predicate should probably - * be replaced with `getDef`. - * - * Gets the `Instruction` whose result is the value of the operand. - */ - deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() } - /** * Gets the overlap relationship between the operand's definition and its use. */ diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll index 53cdc75512b..aae12b0047a 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll @@ -149,7 +149,9 @@ private class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction override Language::Location getLocation() { result = irFunc.getLocation() } - override string getLabel() { result = Language::getIdentityString(irFunc.getFunction()) } + override string getLabel() { + result = Imports::LanguageDebug::getIdentityString(irFunc.getFunction()) + } override int getOrder() { this = diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll index aaecac058bd..78dcdc95af0 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll @@ -32,12 +32,6 @@ module AliasModels { */ predicate isParameter(ParameterIndex index) { none() } - /** - * Holds if this is the input value of the parameter with index `index`. - * DEPRECATED: Use `isParameter(index)` instead. - */ - deprecated final predicate isInParameter(ParameterIndex index) { this.isParameter(index) } - /** * Holds if this is the input value pointed to by a pointer parameter to a function, or the input * value referred to by a reference parameter to a function, where the parameter has index @@ -71,13 +65,6 @@ module AliasModels { */ predicate isQualifierObject() { none() } - /** - * Holds if this is the input value pointed to by the `this` pointer of an instance member - * function. - * DEPRECATED: Use `isQualifierObject()` instead. - */ - deprecated final predicate isInQualifier() { this.isQualifierObject() } - /** * Holds if this is the input value of the `this` pointer of an instance member function. * @@ -182,13 +169,6 @@ module AliasModels { */ predicate isQualifierObject() { none() } - /** - * Holds if this is the output value pointed to by the `this` pointer of an instance member - * function. - * DEPRECATED: Use `isQualifierObject()` instead. - */ - deprecated final predicate isOutQualifier() { this.isQualifierObject() } - /** * Holds if this is the value returned by a function. * @@ -208,12 +188,6 @@ module AliasModels { */ predicate isReturnValue() { none() } - /** - * Holds if this is the value returned by a function. - * DEPRECATED: Use `isReturnValue()` instead. - */ - deprecated final predicate isOutReturnValue() { this.isReturnValue() } - /** * Holds if this is the output value pointed to by the return value of a function, if the function * returns a pointer, or the output value referred to by the return value of a function, if the @@ -234,14 +208,6 @@ module AliasModels { */ predicate isReturnValueDeref() { none() } - /** - * Holds if this is the output value pointed to by the return value of a function, if the function - * returns a pointer, or the output value referred to by the return value of a function, if the - * function returns a reference. - * DEPRECATED: Use `isReturnValueDeref()` instead. - */ - deprecated final predicate isOutReturnPointer() { this.isReturnValueDeref() } - /** * Holds if `i >= 0` and `isParameterDeref(i)` holds for this is the value, or * if `i = -1` and `isQualifierObject()` holds for this value. diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll new file mode 100644 index 00000000000..f43546fe76d --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/IRConsistencyImports.qll @@ -0,0 +1 @@ +import experimental.ir.internal.IRCSharpLanguageDebug as LanguageDebug diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll index 9a3e4c03646..0c5337d57de 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/PrintIRImports.qll @@ -1 +1,2 @@ import experimental.ir.IRConfiguration as IRConfiguration +import experimental.ir.internal.IRCSharpLanguageDebug as LanguageDebug diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll index 873a3c635f8..0fb108f0b56 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistency.qll @@ -1,2 +1,55 @@ -private import SSAConstruction as Ssa -import Ssa::SsaConsistency +import SsaConsistency +import SSAConsistencyImports + +module SsaConsistency { + /** + * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. + */ + query predicate multipleOperandMemoryLocations( + OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText + ) { + exists(int locationCount | + locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and + locationCount > 1 and + func = operand.getEnclosingIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + + " memory accesses in function '$@': " + + strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") + ) + } + + /** + * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. + */ + query predicate missingVirtualVariableForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + not exists(location.getVirtualVariable()) and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = "Memory location has no virtual variable in function '$@'." + } + + /** + * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. + */ + query predicate multipleVirtualVariablesForMemoryLocation( + Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText + ) { + exists(int vvarCount | + vvarCount = strictcount(location.getVirtualVariable()) and + vvarCount > 1 and + func = location.getIRFunction() and + funcText = LanguageDebug::getIdentityString(func.getFunction()) and + message = + "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + + concat(Alias::VirtualVariable vvar | + vvar = location.getVirtualVariable() + | + vvar.toString(), ", " + ) + ")." + ) + } +} diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll new file mode 100644 index 00000000000..70b803a818e --- /dev/null +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/SSAConsistencyImports.qll @@ -0,0 +1,3 @@ +import experimental.ir.implementation.raw.IR as OldIR +import SimpleSSA as Alias +import experimental.ir.internal.IRCSharpLanguageDebug as LanguageDebug 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 bb07e9e4dd2..233db262118 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 @@ -996,7 +996,7 @@ deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1; /** * Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the - * `DebugSSA` module, which is then imported by PrintSSA. + * `DebugSsa` module, which is then imported by PrintSSA. */ module DebugSsa { import PhiInsertion @@ -1063,62 +1063,6 @@ private module CachedForDebugging { int maxValue() { result = 2147483647 } } -module SsaConsistency { - /** - * Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis. - */ - query predicate multipleOperandMemoryLocations( - OldIR::MemoryOperand operand, string message, OldIR::IRFunction func, string funcText - ) { - exists(int locationCount | - locationCount = strictcount(Alias::getOperandMemoryLocation(operand)) and - locationCount > 1 and - func = operand.getEnclosingIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - operand.getUse().toString() + " " + "Operand has " + locationCount.toString() + - " memory accesses in function '$@': " + - strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ") - ) - } - - /** - * Holds if a `MemoryLocation` does not have an associated `VirtualVariable`. - */ - query predicate missingVirtualVariableForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - not exists(location.getVirtualVariable()) and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = "Memory location has no virtual variable in function '$@'." - } - - /** - * Holds if a `MemoryLocation` is a member of more than one `VirtualVariable`. - */ - query predicate multipleVirtualVariablesForMemoryLocation( - Alias::MemoryLocation location, string message, OldIR::IRFunction func, string funcText - ) { - exists(int vvarCount | - vvarCount = strictcount(location.getVirtualVariable()) and - vvarCount > 1 and - func = location.getIRFunction() and - funcText = Language::getIdentityString(func.getFunction()) and - message = - "Memory location has " + vvarCount.toString() + " virtual variables in function '$@': (" + - concat(Alias::VirtualVariable vvar | - vvar = location.getVirtualVariable() - | - vvar.toString(), ", " - ) + ")." - ) - } -} - -/** DEPRECATED: Alias for SsaConsistency */ -deprecated module SSAConsistency = SsaConsistency; - /** * Provides the portion of the parameterized IR interface that is used to construct the SSA stages * of the IR. The raw stage of the IR does not expose these predicates. diff --git a/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll index f4af09b4815..f0137b9b5ce 100644 --- a/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll @@ -117,8 +117,6 @@ class Expr = CSharp::Expr; class Class = CSharp::ValueOrRefType; // Used for inheritance conversions -string getIdentityString(Function func) { result = func.getLabel() } - predicate hasCaseEdge(string minValue, string maxValue) { // TODO: Need to handle pattern matching hasCaseEdge(_, minValue, maxValue) diff --git a/csharp/ql/src/experimental/ir/internal/IRCSharpLanguageDebug.qll b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguageDebug.qll new file mode 100644 index 00000000000..3ee0328dd90 --- /dev/null +++ b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguageDebug.qll @@ -0,0 +1,5 @@ +private import csharp as CSharp + +class Function = CSharp::Callable; + +string getIdentityString(Function func) { result = func.getLabel() } diff --git a/csharp/ql/src/qlpack.yml b/csharp/ql/src/qlpack.yml index 54179503685..3ed4e37fefc 100644 --- a/csharp/ql/src/qlpack.yml +++ b/csharp/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/csharp-queries -version: 0.5.4-dev +version: 0.5.5-dev groups: - csharp - queries diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index ad09add3853..10ef552105a 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -143,21 +143,25 @@ summary | Microsoft.AspNetCore.Server.IIS.Core;ThrowingWasUpgradedWriteOnlyStream;false;WriteAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[0].Element;Argument[this];taint;manual | | Microsoft.AspNetCore.Server.IIS.Core;WriteOnlyStream;false;Read;(System.Byte[],System.Int32,System.Int32);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.Server.IIS.Core;WriteOnlyStream;false;ReadAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0].Element;taint;manual | +| Microsoft.AspNetCore.Server.IIS.Core;WriteOnlyStream;false;ReadAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;FlushAsync;(System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;Read;(System.Byte[],System.Int32,System.Int32);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;ReadAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;ReadAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;Write;(System.Byte[],System.Int32,System.Int32);;Argument[0].Element;Argument[this];taint;manual | | Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;WriteAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[0].Element;Argument[this];taint;manual | +| Microsoft.AspNetCore.WebUtilities;BufferedReadStream;false;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;CopyToAsync;(System.IO.Stream,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0];taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;Read;(System.Byte[],System.Int32,System.Int32);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;ReadAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;ReadAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;Write;(System.Byte[],System.Int32,System.Int32);;Argument[0].Element;Argument[this];taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;WriteAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[0].Element;Argument[this];taint;manual | +| Microsoft.AspNetCore.WebUtilities;FileBufferingReadStream;false;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;FlushAsync;(System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;Read;(System.Byte[],System.Int32,System.Int32);;Argument[this];Argument[0].Element;taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;ReadAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0].Element;taint;manual | +| Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;ReadAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;Write;(System.Byte[],System.Int32,System.Int32);;Argument[0].Element;Argument[this];taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;WriteAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[0].Element;Argument[this];taint;manual | | Microsoft.AspNetCore.WebUtilities;FileBufferingWriteStream;false;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | @@ -178,9 +182,14 @@ summary | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteAsync;(System.String);;Argument[0];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteAsync;(System.String);;Argument[this];ReturnValue;taint;generated | +| Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.Char);;Argument[this];ReturnValue;taint;generated | +| Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.Char[],System.Int32,System.Int32);;Argument[0].Element;ReturnValue;taint;generated | +| Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.Char[],System.Int32,System.Int32);;Argument[this];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | | Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.String);;Argument[0];ReturnValue;taint;generated | +| Microsoft.AspNetCore.WebUtilities;HttpResponseStreamWriter;false;WriteLineAsync;(System.String);;Argument[this];ReturnValue;taint;generated | | Microsoft.CSharp.RuntimeBinder;Binder;false;BinaryOperation;(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.Linq.Expressions.ExpressionType,System.Type,System.Collections.Generic.IEnumerable);;Argument[2];ReturnValue;taint;generated | | Microsoft.CSharp.RuntimeBinder;Binder;false;BinaryOperation;(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.Linq.Expressions.ExpressionType,System.Type,System.Collections.Generic.IEnumerable);;Argument[3].Element;ReturnValue;taint;generated | | Microsoft.CSharp.RuntimeBinder;Binder;false;Convert;(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags,System.Type,System.Type);;Argument[2];ReturnValue;taint;generated | @@ -781,6 +790,7 @@ summary | System.Buffers;ReadOnlySequence<>;false;get_First;();;Argument[this];ReturnValue;taint;generated | | System.Buffers;ReadOnlySequence<>;false;get_Start;();;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;SequenceReader;(System.Buffers.ReadOnlySequence);;Argument[0];Argument[this];taint;generated | +| System.Buffers;SequenceReader<>;false;TryReadExact;(System.Int32,System.Buffers.ReadOnlySequence);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,System.ReadOnlySpan,System.Boolean);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,T,System.Boolean);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,T,T,System.Boolean);;Argument[this];ReturnValue;taint;generated | @@ -913,6 +923,8 @@ summary | System.Collections.Concurrent;Partitioner;false;Create<>;(System.Collections.Generic.IEnumerable,System.Collections.Concurrent.EnumerablePartitionerOptions);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Concurrent;Partitioner;false;Create<>;(System.Collections.Generic.IList,System.Boolean);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Concurrent;Partitioner;false;Create<>;(TSource[],System.Boolean);;Argument[0].Element;ReturnValue;taint;generated | +| System.Collections.Generic;CollectionExtensions;false;AsReadOnly<,>;(System.Collections.Generic.IDictionary);;Argument[0].Element;ReturnValue;taint;generated | +| System.Collections.Generic;CollectionExtensions;false;AsReadOnly<>;(System.Collections.Generic.IList);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[1];ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[2];ReturnValue;taint;generated | @@ -1174,6 +1186,9 @@ summary | System.Collections.Generic;SortedList<,>;false;CopyTo;(System.Collections.Generic.KeyValuePair[],System.Int32);;Argument[this].Element;Argument[0].Element;value;manual | | System.Collections.Generic;SortedList<,>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual | | System.Collections.Generic;SortedList<,>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual | +| System.Collections.Generic;SortedList<,>;false;GetKeyAtIndex;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Collections.Generic;SortedList<,>;false;GetValueAtIndex;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Collections.Generic;SortedList<,>;false;SetValueAtIndex;(System.Int32,TValue);;Argument[1];Argument[this];taint;generated | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IComparer);;Argument[0];Argument[this];taint;generated | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IDictionary);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IDictionary);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual | @@ -5796,6 +5811,18 @@ summary | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual | | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual | | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;false;get_Item;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_LocalEndPoint;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_NegotiatedApplicationProtocol;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_RemoteEndPoint;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicStream;false;BeginRead;(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object);;Argument[this];Argument[0].Element;taint;manual | +| System.Net.Quic;QuicStream;false;BeginWrite;(System.Byte[],System.Int32,System.Int32,System.AsyncCallback,System.Object);;Argument[0].Element;Argument[this];taint;manual | +| System.Net.Quic;QuicStream;false;FlushAsync;(System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicStream;false;Read;(System.Byte[],System.Int32,System.Int32);;Argument[this];Argument[0].Element;taint;manual | +| System.Net.Quic;QuicStream;false;ReadAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[this];Argument[0].Element;taint;manual | +| System.Net.Quic;QuicStream;false;ReadAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicStream;false;Write;(System.Byte[],System.Int32,System.Int32);;Argument[0].Element;Argument[this];taint;manual | +| System.Net.Quic;QuicStream;false;WriteAsync;(System.Byte[],System.Int32,System.Int32,System.Threading.CancellationToken);;Argument[0].Element;Argument[this];taint;manual | +| System.Net.Quic;QuicStream;false;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Security;AuthenticatedStream;false;AuthenticatedStream;(System.IO.Stream,System.Boolean);;Argument[0];Argument[this];taint;generated | | System.Net.Security;AuthenticatedStream;false;DisposeAsync;();;Argument[this];ReturnValue;taint;generated | | System.Net.Security;AuthenticatedStream;false;get_InnerStream;();;Argument[this];ReturnValue;taint;generated | @@ -5909,6 +5936,9 @@ summary | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[4];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[4];ReturnValue;taint;generated | @@ -5922,7 +5952,12 @@ summary | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -5932,7 +5967,12 @@ summary | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[4];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -5941,6 +5981,8 @@ summary | System.Net.Sockets;Socket;false;SendAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | | System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.ReadOnlyMemory,System.ReadOnlyMemory,System.Net.Sockets.TransmitFileOptions,System.Threading.CancellationToken);;Argument[4];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.ReadOnlyMemory,System.ReadOnlyMemory,System.Net.Sockets.TransmitFileOptions,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | @@ -5952,9 +5994,14 @@ summary | System.Net.Sockets;Socket;false;SendTo;(System.Byte[],System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendTo;(System.ReadOnlySpan,System.Net.EndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendTo;(System.ReadOnlySpan,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[0];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];Argument[this];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -6035,6 +6082,7 @@ summary | System.Net.Sockets;UdpReceiveResult;false;UdpReceiveResult;(System.Byte[],System.Net.IPEndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;UdpReceiveResult;false;get_Buffer;();;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;UdpReceiveResult;false;get_RemoteEndPoint;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;UnixDomainSocketEndPoint;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;SetBuffer;(System.Int32,System.Int32,System.ArraySegment);;Argument[2].Element;Argument[this];taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;get_Cookies;();;Argument[this];ReturnValue;taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;get_Credentials;();;Argument[this];ReturnValue;taint;generated | @@ -7136,6 +7184,7 @@ summary | System.Reflection;TypeDelegator;false;GetInterfaceMap;(System.Type);;Argument[this];ReturnValue;taint;generated | | System.Reflection;TypeDelegator;false;GetInterfaces;();;Argument[this];ReturnValue;taint;generated | | System.Reflection;TypeDelegator;false;GetMember;(System.String,System.Reflection.MemberTypes,System.Reflection.BindingFlags);;Argument[this];ReturnValue;taint;generated | +| System.Reflection;TypeDelegator;false;GetMemberWithSameMetadataDefinitionAs;(System.Reflection.MemberInfo);;Argument[this];ReturnValue;taint;generated | | System.Reflection;TypeDelegator;false;GetMembers;(System.Reflection.BindingFlags);;Argument[this];ReturnValue;taint;generated | | System.Reflection;TypeDelegator;false;GetMethodImpl;(System.String,System.Reflection.BindingFlags,System.Reflection.Binder,System.Reflection.CallingConventions,System.Type[],System.Reflection.ParameterModifier[]);;Argument[this];ReturnValue;taint;generated | | System.Reflection;TypeDelegator;false;GetMethods;(System.Reflection.BindingFlags);;Argument[this];ReturnValue;taint;generated | @@ -7334,10 +7383,13 @@ summary | System.Runtime.InteropServices;SequenceMarshal;false;TryGetArray<>;(System.Buffers.ReadOnlySequence,System.ArraySegment);;Argument[0];ReturnValue;taint;generated | | System.Runtime.InteropServices;SequenceMarshal;false;TryGetReadOnlyMemory<>;(System.Buffers.ReadOnlySequence,System.ReadOnlyMemory);;Argument[0];ReturnValue;taint;generated | | System.Runtime.InteropServices;SequenceMarshal;false;TryGetReadOnlySequenceSegment<>;(System.Buffers.ReadOnlySequence,System.Buffers.ReadOnlySequenceSegment,System.Int32,System.Buffers.ReadOnlySequenceSegment,System.Int32);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector64;false;Abs<>;(System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector64;false;WithElement<>;(System.Runtime.Intrinsics.Vector64,System.Int32,T);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector128;false;Abs<>;(System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithElement<>;(System.Runtime.Intrinsics.Vector128,System.Int32,T);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithLower<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithUpper<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector256;false;Abs<>;(System.Runtime.Intrinsics.Vector256);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithElement<>;(System.Runtime.Intrinsics.Vector256,System.Int32,T);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithLower<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithUpper<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | @@ -8520,6 +8572,14 @@ summary | System.Text;UnicodeEncoding;false;GetDecoder;();;Argument[this];ReturnValue;taint;generated | | System.Text;UnicodeEncoding;false;GetEncoder;();;Argument[this];ReturnValue;taint;generated | | System.Text;UnicodeEncoding;false;GetString;(System.Byte[],System.Int32,System.Int32);;Argument[0].Element;ReturnValue;taint;manual | +| System.Threading.RateLimiting;ConcurrencyLimiter;false;ConcurrencyLimiter;(System.Threading.RateLimiting.ConcurrencyLimiterOptions);;Argument[0];Argument[this];taint;generated | +| System.Threading.RateLimiting;MetadataName;false;Create<>;(System.String);;Argument[0];ReturnValue;taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;MetadataName;(System.String);;Argument[0];Argument[this];taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;ToString;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;get_Name;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;RateLimitLease;false;TryGetMetadata<>;(System.Threading.RateLimiting.MetadataName,T);;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;RateLimitLease;true;GetAllMetadata;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;TokenBucketRateLimiter;false;TokenBucketRateLimiter;(System.Threading.RateLimiting.TokenBucketRateLimiterOptions);;Argument[0];Argument[this];taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;BatchBlock;(System.Int32,System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions);;Argument[1];Argument[this];taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;LinkTo;(System.Threading.Tasks.Dataflow.ITargetBlock,System.Threading.Tasks.Dataflow.DataflowLinkOptions);;Argument[0];ReturnValue;taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;LinkTo;(System.Threading.Tasks.Dataflow.ITargetBlock,System.Threading.Tasks.Dataflow.DataflowLinkOptions);;Argument[this];ReturnValue;taint;generated | @@ -11052,6 +11112,8 @@ summary | System;FormattableString;false;Invariant;(System.FormattableString);;Argument[0];ReturnValue;taint;generated | | System;FormattableString;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System;FormattableString;false;ToString;(System.String,System.IFormatProvider);;Argument[this];ReturnValue;taint;generated | +| System;Half;false;BitDecrement;(System.Half);;Argument[0];ReturnValue;taint;generated | +| System;Half;false;BitIncrement;(System.Half);;Argument[0];ReturnValue;taint;generated | | System;Half;false;ToString;(System.IFormatProvider);;Argument[0];ReturnValue;taint;generated | | System;Half;false;ToString;(System.String,System.IFormatProvider);;Argument[1];ReturnValue;taint;generated | | System;Int32;false;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);;Argument[0].Element;ReturnValue;taint;manual | @@ -11067,7 +11129,17 @@ summary | System;Int32;false;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int32);;Argument[0];ReturnValue;taint;manual | | System;Int32;false;TryParse;(System.String,System.Int32);;Argument[0];Argument[1];taint;manual | | System;Int32;false;TryParse;(System.String,System.Int32);;Argument[0];ReturnValue;taint;manual | +| System;IntPtr;false;Abs;(System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[2];ReturnValue;taint;generated | +| System;IntPtr;false;CreateSaturating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;CreateTruncating<>;(TOther);;Argument[0];ReturnValue;taint;generated | | System;IntPtr;false;IntPtr;(System.Void*);;Argument[0];Argument[this];taint;generated | +| System;IntPtr;false;Max;(System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Max;(System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | +| System;IntPtr;false;Min;(System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Min;(System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | | System;IntPtr;false;ToPointer;();;Argument[this];ReturnValue;taint;generated | | System;Lazy<,>;false;Lazy;(TMetadata);;Argument[0];Argument[this];taint;generated | | System;Lazy<,>;false;Lazy;(TMetadata,System.Boolean);;Argument[0];Argument[this];taint;generated | @@ -11745,6 +11817,16 @@ summary | System;TypeLoadException;false;TypeLoadException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[0];Argument[this];taint;generated | | System;TypeLoadException;false;get_Message;();;Argument[this];ReturnValue;taint;generated | | System;TypeLoadException;false;get_TypeName;();;Argument[this];ReturnValue;taint;generated | +| System;UIntPtr;false;Abs;(System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[2];ReturnValue;taint;generated | +| System;UIntPtr;false;CreateSaturating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;CreateTruncating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Max;(System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Max;(System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | +| System;UIntPtr;false;Min;(System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Min;(System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | | System;UIntPtr;false;ToPointer;();;Argument[this];ReturnValue;taint;generated | | System;UIntPtr;false;UIntPtr;(System.Void*);;Argument[0];Argument[this];taint;generated | | System;UnhandledExceptionEventArgs;false;UnhandledExceptionEventArgs;(System.Object,System.Boolean);;Argument[0];Argument[this];taint;generated | @@ -11985,6 +12067,7 @@ neutral | Microsoft.Extensions.Caching.Memory;IMemoryCache;CreateEntry;(System.Object);generated | | Microsoft.Extensions.Caching.Memory;IMemoryCache;Remove;(System.Object);generated | | Microsoft.Extensions.Caching.Memory;IMemoryCache;TryGetValue;(System.Object,System.Object);generated | +| Microsoft.Extensions.Caching.Memory;MemoryCache;Clear;();generated | | Microsoft.Extensions.Caching.Memory;MemoryCache;Compact;(System.Double);generated | | Microsoft.Extensions.Caching.Memory;MemoryCache;Dispose;();generated | | Microsoft.Extensions.Caching.Memory;MemoryCache;Dispose;(System.Boolean);generated | @@ -11999,9 +12082,11 @@ neutral | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;get_Clock;();generated | | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;get_CompactionPercentage;();generated | | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;get_ExpirationScanFrequency;();generated | +| Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;get_TrackLinkedCacheEntries;();generated | | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;set_Clock;(Microsoft.Extensions.Internal.ISystemClock);generated | | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;set_CompactionPercentage;(System.Double);generated | | Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;set_ExpirationScanFrequency;(System.TimeSpan);generated | +| Microsoft.Extensions.Caching.Memory;MemoryCacheOptions;set_TrackLinkedCacheEntries;(System.Boolean);generated | | Microsoft.Extensions.Caching.Memory;MemoryDistributedCacheOptions;MemoryDistributedCacheOptions;();generated | | Microsoft.Extensions.Caching.Memory;PostEvictionCallbackRegistration;get_EvictionCallback;();generated | | Microsoft.Extensions.Caching.Memory;PostEvictionCallbackRegistration;get_State;();generated | @@ -12064,6 +12149,11 @@ neutral | Microsoft.Extensions.Configuration;ConfigurationBuilder;Build;();generated | | Microsoft.Extensions.Configuration;ConfigurationBuilder;get_Properties;();generated | | Microsoft.Extensions.Configuration;ConfigurationBuilder;get_Sources;();generated | +| Microsoft.Extensions.Configuration;ConfigurationDebugViewContext;ConfigurationDebugViewContext;(System.String,System.String,System.String,Microsoft.Extensions.Configuration.IConfigurationProvider);generated | +| Microsoft.Extensions.Configuration;ConfigurationDebugViewContext;get_ConfigurationProvider;();generated | +| Microsoft.Extensions.Configuration;ConfigurationDebugViewContext;get_Key;();generated | +| Microsoft.Extensions.Configuration;ConfigurationDebugViewContext;get_Path;();generated | +| Microsoft.Extensions.Configuration;ConfigurationDebugViewContext;get_Value;();generated | | Microsoft.Extensions.Configuration;ConfigurationExtensions;AsEnumerable;(Microsoft.Extensions.Configuration.IConfiguration);generated | | Microsoft.Extensions.Configuration;ConfigurationExtensions;AsEnumerable;(Microsoft.Extensions.Configuration.IConfiguration,System.Boolean);generated | | Microsoft.Extensions.Configuration;ConfigurationExtensions;Exists;(Microsoft.Extensions.Configuration.IConfigurationSection);generated | @@ -13570,7 +13660,6 @@ neutral | Microsoft.Win32.SafeHandles;SafeNCryptHandle;ReleaseNativeHandle;();generated | | Microsoft.Win32.SafeHandles;SafeNCryptHandle;SafeNCryptHandle;();generated | | Microsoft.Win32.SafeHandles;SafeNCryptHandle;SafeNCryptHandle;(System.IntPtr,System.Runtime.InteropServices.SafeHandle);generated | -| Microsoft.Win32.SafeHandles;SafeNCryptHandle;get_IsInvalid;();generated | | Microsoft.Win32.SafeHandles;SafeNCryptKeyHandle;ReleaseNativeHandle;();generated | | Microsoft.Win32.SafeHandles;SafeNCryptKeyHandle;SafeNCryptKeyHandle;();generated | | Microsoft.Win32.SafeHandles;SafeNCryptKeyHandle;SafeNCryptKeyHandle;(System.IntPtr,System.Runtime.InteropServices.SafeHandle);generated | @@ -18050,6 +18139,10 @@ neutral | System.Data;VersionNotFoundException;VersionNotFoundException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System.Data;VersionNotFoundException;VersionNotFoundException;(System.String);generated | | System.Data;VersionNotFoundException;VersionNotFoundException;(System.String,System.Exception);generated | +| System.Diagnostics.CodeAnalysis;ConstantExpectedAttribute;get_Max;();generated | +| System.Diagnostics.CodeAnalysis;ConstantExpectedAttribute;get_Min;();generated | +| System.Diagnostics.CodeAnalysis;ConstantExpectedAttribute;set_Max;(System.Object);generated | +| System.Diagnostics.CodeAnalysis;ConstantExpectedAttribute;set_Min;(System.Object);generated | | System.Diagnostics.CodeAnalysis;DoesNotReturnIfAttribute;DoesNotReturnIfAttribute;(System.Boolean);generated | | System.Diagnostics.CodeAnalysis;DoesNotReturnIfAttribute;get_ParameterValue;();generated | | System.Diagnostics.CodeAnalysis;DynamicDependencyAttribute;DynamicDependencyAttribute;(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes,System.String,System.String);generated | @@ -18087,6 +18180,10 @@ neutral | System.Diagnostics.CodeAnalysis;RequiresAssemblyFilesAttribute;get_Message;();generated | | System.Diagnostics.CodeAnalysis;RequiresAssemblyFilesAttribute;get_Url;();generated | | System.Diagnostics.CodeAnalysis;RequiresAssemblyFilesAttribute;set_Url;(System.String);generated | +| System.Diagnostics.CodeAnalysis;RequiresDynamicCodeAttribute;RequiresDynamicCodeAttribute;(System.String);generated | +| System.Diagnostics.CodeAnalysis;RequiresDynamicCodeAttribute;get_Message;();generated | +| System.Diagnostics.CodeAnalysis;RequiresDynamicCodeAttribute;get_Url;();generated | +| System.Diagnostics.CodeAnalysis;RequiresDynamicCodeAttribute;set_Url;(System.String);generated | | System.Diagnostics.CodeAnalysis;RequiresUnreferencedCodeAttribute;RequiresUnreferencedCodeAttribute;(System.String);generated | | System.Diagnostics.CodeAnalysis;RequiresUnreferencedCodeAttribute;get_Message;();generated | | System.Diagnostics.CodeAnalysis;RequiresUnreferencedCodeAttribute;get_Url;();generated | @@ -20603,6 +20700,7 @@ neutral | System.IO.Compression;DeflateStream;Seek;(System.Int64,System.IO.SeekOrigin);generated | | System.IO.Compression;DeflateStream;SetLength;(System.Int64);generated | | System.IO.Compression;DeflateStream;Write;(System.ReadOnlySpan);generated | +| System.IO.Compression;DeflateStream;WriteByte;(System.Byte);generated | | System.IO.Compression;DeflateStream;get_CanRead;();generated | | System.IO.Compression;DeflateStream;get_CanSeek;();generated | | System.IO.Compression;DeflateStream;get_CanWrite;();generated | @@ -20621,6 +20719,7 @@ neutral | System.IO.Compression;GZipStream;Seek;(System.Int64,System.IO.SeekOrigin);generated | | System.IO.Compression;GZipStream;SetLength;(System.Int64);generated | | System.IO.Compression;GZipStream;Write;(System.ReadOnlySpan);generated | +| System.IO.Compression;GZipStream;WriteByte;(System.Byte);generated | | System.IO.Compression;GZipStream;get_CanRead;();generated | | System.IO.Compression;GZipStream;get_CanSeek;();generated | | System.IO.Compression;GZipStream;get_CanWrite;();generated | @@ -22356,6 +22455,12 @@ neutral | System.Net.Http.Json;HttpClientJsonExtensions;GetFromJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,System.Text.Json.JsonSerializerOptions,System.Threading.CancellationToken);generated | | System.Net.Http.Json;HttpClientJsonExtensions;GetFromJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Threading.CancellationToken);generated | | System.Net.Http.Json;HttpClientJsonExtensions;GetFromJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Text.Json.JsonSerializerOptions,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,TValue,System.Text.Json.JsonSerializerOptions,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,TValue,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Threading.CancellationToken);generated | +| System.Net.Http.Json;HttpClientJsonExtensions;PatchAsJsonAsync<>;(System.Net.Http.HttpClient,System.Uri,TValue,System.Threading.CancellationToken);generated | | System.Net.Http.Json;HttpClientJsonExtensions;PostAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Text.Json.JsonSerializerOptions,System.Threading.CancellationToken);generated | | System.Net.Http.Json;HttpClientJsonExtensions;PostAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Text.Json.Serialization.Metadata.JsonTypeInfo,System.Threading.CancellationToken);generated | | System.Net.Http.Json;HttpClientJsonExtensions;PostAsJsonAsync<>;(System.Net.Http.HttpClient,System.String,TValue,System.Threading.CancellationToken);generated | @@ -22997,6 +23102,46 @@ neutral | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;UnicastIPAddressInformationCollection;();generated | | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;get_Count;();generated | | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;get_IsReadOnly;();generated | +| System.Net.Quic;QuicClientConnectionOptions;QuicClientConnectionOptions;();generated | +| System.Net.Quic;QuicClientConnectionOptions;get_ClientAuthenticationOptions;();generated | +| System.Net.Quic;QuicClientConnectionOptions;get_LocalEndPoint;();generated | +| System.Net.Quic;QuicClientConnectionOptions;get_RemoteEndPoint;();generated | +| System.Net.Quic;QuicClientConnectionOptions;set_ClientAuthenticationOptions;(System.Net.Security.SslClientAuthenticationOptions);generated | +| System.Net.Quic;QuicClientConnectionOptions;set_LocalEndPoint;(System.Net.IPEndPoint);generated | +| System.Net.Quic;QuicClientConnectionOptions;set_RemoteEndPoint;(System.Net.EndPoint);generated | +| System.Net.Quic;QuicConnection;CloseAsync;(System.Int64,System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicConnection;get_RemoteCertificate;();generated | +| System.Net.Quic;QuicListener;AcceptConnectionAsync;(System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicListenerOptions;QuicListenerOptions;();generated | +| System.Net.Quic;QuicListenerOptions;get_ListenBacklog;();generated | +| System.Net.Quic;QuicListenerOptions;get_ListenEndPoint;();generated | +| System.Net.Quic;QuicListenerOptions;set_ListenBacklog;(System.Int32);generated | +| System.Net.Quic;QuicListenerOptions;set_ListenEndPoint;(System.Net.IPEndPoint);generated | +| System.Net.Quic;QuicStream;Dispose;(System.Boolean);generated | +| System.Net.Quic;QuicStream;EndRead;(System.IAsyncResult);generated | +| System.Net.Quic;QuicStream;EndWrite;(System.IAsyncResult);generated | +| System.Net.Quic;QuicStream;Flush;();generated | +| System.Net.Quic;QuicStream;FlushAsync;(System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicStream;Read;(System.Span);generated | +| System.Net.Quic;QuicStream;ReadAsync;(System.Memory,System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicStream;ReadByte;();generated | +| System.Net.Quic;QuicStream;Seek;(System.Int64,System.IO.SeekOrigin);generated | +| System.Net.Quic;QuicStream;SetLength;(System.Int64);generated | +| System.Net.Quic;QuicStream;Write;(System.ReadOnlySpan);generated | +| System.Net.Quic;QuicStream;WriteAsync;(System.ReadOnlyMemory,System.Boolean,System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicStream;WriteAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);generated | +| System.Net.Quic;QuicStream;WriteByte;(System.Byte);generated | +| System.Net.Quic;QuicStream;get_CanRead;();generated | +| System.Net.Quic;QuicStream;get_CanSeek;();generated | +| System.Net.Quic;QuicStream;get_CanTimeout;();generated | +| System.Net.Quic;QuicStream;get_CanWrite;();generated | +| System.Net.Quic;QuicStream;get_Length;();generated | +| System.Net.Quic;QuicStream;get_Position;();generated | +| System.Net.Quic;QuicStream;get_ReadTimeout;();generated | +| System.Net.Quic;QuicStream;get_WriteTimeout;();generated | +| System.Net.Quic;QuicStream;set_Position;(System.Int64);generated | +| System.Net.Quic;QuicStream;set_ReadTimeout;(System.Int32);generated | +| System.Net.Quic;QuicStream;set_WriteTimeout;(System.Int32);generated | | System.Net.Security;AuthenticatedStream;Dispose;(System.Boolean);generated | | System.Net.Security;AuthenticatedStream;get_IsAuthenticated;();generated | | System.Net.Security;AuthenticatedStream;get_IsEncrypted;();generated | @@ -23188,6 +23333,7 @@ neutral | System.Net.Sockets;NetworkStream;set_Writeable;(System.Boolean);generated | | System.Net.Sockets;SafeSocketHandle;ReleaseHandle;();generated | | System.Net.Sockets;SafeSocketHandle;SafeSocketHandle;();generated | +| System.Net.Sockets;SafeSocketHandle;get_IsInvalid;();generated | | System.Net.Sockets;SendPacketsElement;SendPacketsElement;(System.Byte[]);generated | | System.Net.Sockets;SendPacketsElement;SendPacketsElement;(System.Byte[],System.Int32,System.Int32);generated | | System.Net.Sockets;SendPacketsElement;SendPacketsElement;(System.Byte[],System.Int32,System.Int32,System.Boolean);generated | @@ -23254,7 +23400,9 @@ neutral | System.Net.Sockets;Socket;Receive;(System.Span);generated | | System.Net.Sockets;Socket;Receive;(System.Span,System.Net.Sockets.SocketFlags);generated | | System.Net.Sockets;Socket;Receive;(System.Span,System.Net.Sockets.SocketFlags,System.Net.Sockets.SocketError);generated | +| System.Net.Sockets;Socket;ReceiveAsync;(System.ArraySegment);generated | | System.Net.Sockets;Socket;ReceiveAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags);generated | +| System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList>);generated | | System.Net.Sockets;Socket;ReceiveAsync;(System.Collections.Generic.IList>,System.Net.Sockets.SocketFlags);generated | | System.Net.Sockets;Socket;Select;(System.Collections.IList,System.Collections.IList,System.Collections.IList,System.Int32);generated | | System.Net.Sockets;Socket;Send;(System.Byte[]);generated | @@ -23268,7 +23416,9 @@ neutral | System.Net.Sockets;Socket;Send;(System.ReadOnlySpan);generated | | System.Net.Sockets;Socket;Send;(System.ReadOnlySpan,System.Net.Sockets.SocketFlags);generated | | System.Net.Sockets;Socket;Send;(System.ReadOnlySpan,System.Net.Sockets.SocketFlags,System.Net.Sockets.SocketError);generated | +| System.Net.Sockets;Socket;SendAsync;(System.ArraySegment);generated | | System.Net.Sockets;Socket;SendAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags);generated | +| System.Net.Sockets;Socket;SendAsync;(System.Collections.Generic.IList>);generated | | System.Net.Sockets;Socket;SendAsync;(System.Collections.Generic.IList>,System.Net.Sockets.SocketFlags);generated | | System.Net.Sockets;Socket;SendFile;(System.String);generated | | System.Net.Sockets;Socket;SendFile;(System.String,System.Byte[],System.Byte[],System.Net.Sockets.TransmitFileOptions);generated | @@ -23449,7 +23599,10 @@ neutral | System.Net.Sockets;UdpReceiveResult;Equals;(System.Net.Sockets.UdpReceiveResult);generated | | System.Net.Sockets;UdpReceiveResult;Equals;(System.Object);generated | | System.Net.Sockets;UdpReceiveResult;GetHashCode;();generated | +| System.Net.Sockets;UnixDomainSocketEndPoint;Create;(System.Net.SocketAddress);generated | +| System.Net.Sockets;UnixDomainSocketEndPoint;Serialize;();generated | | System.Net.Sockets;UnixDomainSocketEndPoint;UnixDomainSocketEndPoint;(System.String);generated | +| System.Net.Sockets;UnixDomainSocketEndPoint;get_AddressFamily;();generated | | System.Net.WebSockets;ClientWebSocket;Abort;();generated | | System.Net.WebSockets;ClientWebSocket;ClientWebSocket;();generated | | System.Net.WebSockets;ClientWebSocket;CloseAsync;(System.Net.WebSockets.WebSocketCloseStatus,System.String,System.Threading.CancellationToken);generated | @@ -24204,24 +24357,34 @@ neutral | System.Numerics;BigInteger;get_Zero;();generated | | System.Numerics;BitOperations;IsPow2;(System.Int32);generated | | System.Numerics;BitOperations;IsPow2;(System.Int64);generated | +| System.Numerics;BitOperations;IsPow2;(System.IntPtr);generated | | System.Numerics;BitOperations;IsPow2;(System.UInt32);generated | | System.Numerics;BitOperations;IsPow2;(System.UInt64);generated | +| System.Numerics;BitOperations;IsPow2;(System.UIntPtr);generated | | System.Numerics;BitOperations;LeadingZeroCount;(System.UInt32);generated | | System.Numerics;BitOperations;LeadingZeroCount;(System.UInt64);generated | +| System.Numerics;BitOperations;LeadingZeroCount;(System.UIntPtr);generated | | System.Numerics;BitOperations;Log2;(System.UInt32);generated | | System.Numerics;BitOperations;Log2;(System.UInt64);generated | +| System.Numerics;BitOperations;Log2;(System.UIntPtr);generated | | System.Numerics;BitOperations;PopCount;(System.UInt32);generated | | System.Numerics;BitOperations;PopCount;(System.UInt64);generated | +| System.Numerics;BitOperations;PopCount;(System.UIntPtr);generated | | System.Numerics;BitOperations;RotateLeft;(System.UInt32,System.Int32);generated | | System.Numerics;BitOperations;RotateLeft;(System.UInt64,System.Int32);generated | +| System.Numerics;BitOperations;RotateLeft;(System.UIntPtr,System.Int32);generated | | System.Numerics;BitOperations;RotateRight;(System.UInt32,System.Int32);generated | | System.Numerics;BitOperations;RotateRight;(System.UInt64,System.Int32);generated | +| System.Numerics;BitOperations;RotateRight;(System.UIntPtr,System.Int32);generated | | System.Numerics;BitOperations;RoundUpToPowerOf2;(System.UInt32);generated | | System.Numerics;BitOperations;RoundUpToPowerOf2;(System.UInt64);generated | +| System.Numerics;BitOperations;RoundUpToPowerOf2;(System.UIntPtr);generated | | System.Numerics;BitOperations;TrailingZeroCount;(System.Int32);generated | | System.Numerics;BitOperations;TrailingZeroCount;(System.Int64);generated | +| System.Numerics;BitOperations;TrailingZeroCount;(System.IntPtr);generated | | System.Numerics;BitOperations;TrailingZeroCount;(System.UInt32);generated | | System.Numerics;BitOperations;TrailingZeroCount;(System.UInt64);generated | +| System.Numerics;BitOperations;TrailingZeroCount;(System.UIntPtr);generated | | System.Numerics;Complex;Abs;(System.Numerics.Complex);generated | | System.Numerics;Complex;Acos;(System.Numerics.Complex);generated | | System.Numerics;Complex;Add;(System.Double,System.Numerics.Complex);generated | @@ -24295,7 +24458,9 @@ neutral | System.Numerics;Matrix3x2;ToString;();generated | | System.Numerics;Matrix3x2;get_Identity;();generated | | System.Numerics;Matrix3x2;get_IsIdentity;();generated | +| System.Numerics;Matrix3x2;get_Item;(System.Int32,System.Int32);generated | | System.Numerics;Matrix3x2;get_Translation;();generated | +| System.Numerics;Matrix3x2;set_Item;(System.Int32,System.Int32,System.Single);generated | | System.Numerics;Matrix3x2;set_Translation;(System.Numerics.Vector2);generated | | System.Numerics;Matrix4x4;CreateBillboard;(System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3);generated | | System.Numerics;Matrix4x4;CreateConstrainedBillboard;(System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3);generated | @@ -24337,7 +24502,9 @@ neutral | System.Numerics;Matrix4x4;Transform;(System.Numerics.Matrix4x4,System.Numerics.Quaternion);generated | | System.Numerics;Matrix4x4;get_Identity;();generated | | System.Numerics;Matrix4x4;get_IsIdentity;();generated | +| System.Numerics;Matrix4x4;get_Item;(System.Int32,System.Int32);generated | | System.Numerics;Matrix4x4;get_Translation;();generated | +| System.Numerics;Matrix4x4;set_Item;(System.Int32,System.Int32,System.Single);generated | | System.Numerics;Matrix4x4;set_Translation;(System.Numerics.Vector3);generated | | System.Numerics;Plane;CreateFromVertices;(System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3);generated | | System.Numerics;Plane;Dot;(System.Numerics.Plane,System.Numerics.Vector4);generated | @@ -24376,6 +24543,9 @@ neutral | System.Numerics;Quaternion;ToString;();generated | | System.Numerics;Quaternion;get_Identity;();generated | | System.Numerics;Quaternion;get_IsIdentity;();generated | +| System.Numerics;Quaternion;get_Item;(System.Int32);generated | +| System.Numerics;Quaternion;get_Zero;();generated | +| System.Numerics;Quaternion;set_Item;(System.Int32,System.Single);generated | | System.Numerics;Vector2;Abs;(System.Numerics.Vector2);generated | | System.Numerics;Vector2;Add;(System.Numerics.Vector2,System.Numerics.Vector2);generated | | System.Numerics;Vector2;Clamp;(System.Numerics.Vector2,System.Numerics.Vector2,System.Numerics.Vector2);generated | @@ -24414,10 +24584,12 @@ neutral | System.Numerics;Vector2;Vector2;(System.ReadOnlySpan);generated | | System.Numerics;Vector2;Vector2;(System.Single);generated | | System.Numerics;Vector2;Vector2;(System.Single,System.Single);generated | +| System.Numerics;Vector2;get_Item;(System.Int32);generated | | System.Numerics;Vector2;get_One;();generated | | System.Numerics;Vector2;get_UnitX;();generated | | System.Numerics;Vector2;get_UnitY;();generated | | System.Numerics;Vector2;get_Zero;();generated | +| System.Numerics;Vector2;set_Item;(System.Int32,System.Single);generated | | System.Numerics;Vector3;Abs;(System.Numerics.Vector3);generated | | System.Numerics;Vector3;Add;(System.Numerics.Vector3,System.Numerics.Vector3);generated | | System.Numerics;Vector3;Clamp;(System.Numerics.Vector3,System.Numerics.Vector3,System.Numerics.Vector3);generated | @@ -24456,11 +24628,13 @@ neutral | System.Numerics;Vector3;Vector3;(System.ReadOnlySpan);generated | | System.Numerics;Vector3;Vector3;(System.Single);generated | | System.Numerics;Vector3;Vector3;(System.Single,System.Single,System.Single);generated | +| System.Numerics;Vector3;get_Item;(System.Int32);generated | | System.Numerics;Vector3;get_One;();generated | | System.Numerics;Vector3;get_UnitX;();generated | | System.Numerics;Vector3;get_UnitY;();generated | | System.Numerics;Vector3;get_UnitZ;();generated | | System.Numerics;Vector3;get_Zero;();generated | +| System.Numerics;Vector3;set_Item;(System.Int32,System.Single);generated | | System.Numerics;Vector4;Abs;(System.Numerics.Vector4);generated | | System.Numerics;Vector4;Add;(System.Numerics.Vector4,System.Numerics.Vector4);generated | | System.Numerics;Vector4;Clamp;(System.Numerics.Vector4,System.Numerics.Vector4,System.Numerics.Vector4);generated | @@ -24501,12 +24675,14 @@ neutral | System.Numerics;Vector4;Vector4;(System.ReadOnlySpan);generated | | System.Numerics;Vector4;Vector4;(System.Single);generated | | System.Numerics;Vector4;Vector4;(System.Single,System.Single,System.Single,System.Single);generated | +| System.Numerics;Vector4;get_Item;(System.Int32);generated | | System.Numerics;Vector4;get_One;();generated | | System.Numerics;Vector4;get_UnitW;();generated | | System.Numerics;Vector4;get_UnitX;();generated | | System.Numerics;Vector4;get_UnitY;();generated | | System.Numerics;Vector4;get_UnitZ;();generated | | System.Numerics;Vector4;get_Zero;();generated | +| System.Numerics;Vector4;set_Item;(System.Int32,System.Single);generated | | System.Numerics;Vector;Add<>;(System.Numerics.Vector,System.Numerics.Vector);generated | | System.Numerics;Vector;AndNot<>;(System.Numerics.Vector,System.Numerics.Vector);generated | | System.Numerics;Vector;As<,>;(System.Numerics.Vector);generated | @@ -25027,6 +25203,7 @@ neutral | System.Reflection.Metadata.Ecma335;ControlFlowBuilder;AddFaultRegion;(System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle);generated | | System.Reflection.Metadata.Ecma335;ControlFlowBuilder;AddFilterRegion;(System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle);generated | | System.Reflection.Metadata.Ecma335;ControlFlowBuilder;AddFinallyRegion;(System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle,System.Reflection.Metadata.Ecma335.LabelHandle);generated | +| System.Reflection.Metadata.Ecma335;ControlFlowBuilder;Clear;();generated | | System.Reflection.Metadata.Ecma335;ControlFlowBuilder;ControlFlowBuilder;();generated | | System.Reflection.Metadata.Ecma335;CustomAttributeArrayTypeEncoder;CustomAttributeArrayTypeEncoder;(System.Reflection.Metadata.BlobBuilder);generated | | System.Reflection.Metadata.Ecma335;CustomAttributeArrayTypeEncoder;ElementType;();generated | @@ -27064,6 +27241,7 @@ neutral | System.Runtime.CompilerServices;RuntimeFeature;get_IsDynamicCodeCompiled;();generated | | System.Runtime.CompilerServices;RuntimeFeature;get_IsDynamicCodeSupported;();generated | | System.Runtime.CompilerServices;RuntimeHelpers;AllocateTypeAssociatedMemory;(System.Type,System.Int32);generated | +| System.Runtime.CompilerServices;RuntimeHelpers;CreateSpan<>;(System.RuntimeFieldHandle);generated | | System.Runtime.CompilerServices;RuntimeHelpers;EnsureSufficientExecutionStack;();generated | | System.Runtime.CompilerServices;RuntimeHelpers;Equals;(System.Object,System.Object);generated | | System.Runtime.CompilerServices;RuntimeHelpers;GetHashCode;(System.Object);generated | @@ -30046,6 +30224,7 @@ neutral | System.Runtime.Intrinsics.Arm;ArmBase;LeadingZeroCount;(System.UInt32);generated | | System.Runtime.Intrinsics.Arm;ArmBase;ReverseElementBits;(System.Int32);generated | | System.Runtime.Intrinsics.Arm;ArmBase;ReverseElementBits;(System.UInt32);generated | +| System.Runtime.Intrinsics.Arm;ArmBase;Yield;();generated | | System.Runtime.Intrinsics.Arm;ArmBase;get_IsSupported;();generated | | System.Runtime.Intrinsics.Arm;Crc32+Arm64;ComputeCrc32;(System.UInt32,System.UInt64);generated | | System.Runtime.Intrinsics.Arm;Crc32+Arm64;ComputeCrc32C;(System.UInt32,System.UInt64);generated | @@ -31457,17 +31636,39 @@ neutral | System.Runtime.Intrinsics.X86;Ssse3;get_IsSupported;();generated | | System.Runtime.Intrinsics.X86;X86Base+X64;get_IsSupported;();generated | | System.Runtime.Intrinsics.X86;X86Base;CpuId;(System.Int32,System.Int32);generated | +| System.Runtime.Intrinsics.X86;X86Base;Pause;();generated | | System.Runtime.Intrinsics.X86;X86Base;get_IsSupported;();generated | +| System.Runtime.Intrinsics;Vector64;Add<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;AndNot<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;As<,>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsByte<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsDouble<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsInt16<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsInt32<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsInt64<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;AsNInt<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;AsNUInt<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsSByte<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsSingle<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsUInt16<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsUInt32<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;AsUInt64<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;BitwiseAnd<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;BitwiseOr<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Ceiling;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Ceiling;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConditionalSelect<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToDouble;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToDouble;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToInt32;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToInt64;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToSingle;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToSingle;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToUInt32;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;ConvertToUInt64;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;CopyTo<>;(System.Runtime.Intrinsics.Vector64,System.Span);generated | +| System.Runtime.Intrinsics;Vector64;CopyTo<>;(System.Runtime.Intrinsics.Vector64,T[]);generated | +| System.Runtime.Intrinsics;Vector64;CopyTo<>;(System.Runtime.Intrinsics.Vector64,T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Byte);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Double);generated | @@ -31476,6 +31677,7 @@ neutral | System.Runtime.Intrinsics;Vector64;Create;(System.Int32);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Int32,System.Int32);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector64;Create;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.SByte);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.SByte,System.SByte,System.SByte,System.SByte,System.SByte,System.SByte,System.SByte,System.SByte);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.Single);generated | @@ -31485,39 +31687,99 @@ neutral | System.Runtime.Intrinsics;Vector64;Create;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.UInt32,System.UInt32);generated | | System.Runtime.Intrinsics;Vector64;Create;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector64;Create;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector64;Create<>;(System.ReadOnlySpan);generated | +| System.Runtime.Intrinsics;Vector64;Create<>;(T);generated | +| System.Runtime.Intrinsics;Vector64;Create<>;(T[]);generated | +| System.Runtime.Intrinsics;Vector64;Create<>;(T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Byte);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Double);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Int16);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Int32);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector64;CreateScalar;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.SByte);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.Single);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector64;CreateScalar;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector64;CreateScalar;(System.UIntPtr);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.Byte);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.Int16);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.Int32);generated | +| System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.SByte);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.Single);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.UInt32);generated | +| System.Runtime.Intrinsics;Vector64;CreateScalarUnsafe;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector64;Divide<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Dot<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Equals<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;EqualsAll<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;EqualsAny<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Floor;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Floor;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;GetElement<>;(System.Runtime.Intrinsics.Vector64,System.Int32);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThan<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThanAll<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThanAny<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThanOrEqual<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;GreaterThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThan<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThanAll<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThanAny<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThanOrEqual<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;LessThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Max<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Min<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Multiply<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Multiply<>;(System.Runtime.Intrinsics.Vector64,T);generated | +| System.Runtime.Intrinsics;Vector64;Multiply<>;(T,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Narrow;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Negate<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;OnesComplement<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Sqrt<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Subtract<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;ToScalar<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;ToVector128<>;(System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector64;ToVector128Unsafe<>;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;TryCopyTo<>;(System.Runtime.Intrinsics.Vector64,System.Span);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Widen;(System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;Xor<>;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | +| System.Runtime.Intrinsics;Vector64;get_IsHardwareAccelerated;();generated | | System.Runtime.Intrinsics;Vector64<>;Equals;(System.Object);generated | | System.Runtime.Intrinsics;Vector64<>;Equals;(System.Runtime.Intrinsics.Vector64<>);generated | | System.Runtime.Intrinsics;Vector64<>;GetHashCode;();generated | | System.Runtime.Intrinsics;Vector64<>;ToString;();generated | | System.Runtime.Intrinsics;Vector64<>;get_AllBitsSet;();generated | | System.Runtime.Intrinsics;Vector64<>;get_Count;();generated | +| System.Runtime.Intrinsics;Vector64<>;get_Item;(System.Int32);generated | | System.Runtime.Intrinsics;Vector64<>;get_Zero;();generated | +| System.Runtime.Intrinsics;Vector128;Add<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;AndNot<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;As<,>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsByte<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsDouble<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsInt16<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsInt32<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsInt64<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;AsNInt<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;AsNUInt<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsSByte<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsSingle<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;AsUInt16<>;(System.Runtime.Intrinsics.Vector128);generated | @@ -31531,6 +31793,22 @@ neutral | System.Runtime.Intrinsics;Vector128;AsVector128;(System.Numerics.Vector4);generated | | System.Runtime.Intrinsics;Vector128;AsVector128<>;(System.Numerics.Vector);generated | | System.Runtime.Intrinsics;Vector128;AsVector<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;BitwiseAnd<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;BitwiseOr<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Ceiling;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Ceiling;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConditionalSelect<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToDouble;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToDouble;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToInt32;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToInt64;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToSingle;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToSingle;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToUInt32;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;ConvertToUInt64;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;CopyTo<>;(System.Runtime.Intrinsics.Vector128,System.Span);generated | +| System.Runtime.Intrinsics;Vector128;CopyTo<>;(System.Runtime.Intrinsics.Vector128,T[]);generated | +| System.Runtime.Intrinsics;Vector128;CopyTo<>;(System.Runtime.Intrinsics.Vector128,T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Byte);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Double);generated | @@ -31541,6 +31819,7 @@ neutral | System.Runtime.Intrinsics;Vector128;Create;(System.Int32,System.Int32,System.Int32,System.Int32);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Int64);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Int64,System.Int64);generated | +| System.Runtime.Intrinsics;Vector128;Create;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.Runtime.Intrinsics.Vector64,System.Runtime.Intrinsics.Vector64);generated | @@ -31561,44 +31840,104 @@ neutral | System.Runtime.Intrinsics;Vector128;Create;(System.UInt32,System.UInt32,System.UInt32,System.UInt32);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.UInt64);generated | | System.Runtime.Intrinsics;Vector128;Create;(System.UInt64,System.UInt64);generated | +| System.Runtime.Intrinsics;Vector128;Create;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector128;Create<>;(System.ReadOnlySpan);generated | +| System.Runtime.Intrinsics;Vector128;Create<>;(T);generated | +| System.Runtime.Intrinsics;Vector128;Create<>;(T[]);generated | +| System.Runtime.Intrinsics;Vector128;Create<>;(T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Byte);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Double);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Int16);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Int32);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector128;CreateScalar;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.SByte);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.Single);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector128;CreateScalar;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector128;CreateScalar;(System.UIntPtr);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Byte);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Double);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Int16);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Int32);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.SByte);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.Single);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector128;CreateScalarUnsafe;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector128;Divide<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Dot<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Equals<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;EqualsAll<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;EqualsAny<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Floor;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Floor;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;GetElement<>;(System.Runtime.Intrinsics.Vector128,System.Int32);generated | | System.Runtime.Intrinsics;Vector128;GetLower<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;GetUpper<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThan<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThanAll<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThanAny<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThanOrEqual<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;GreaterThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThan<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThanAll<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThanAny<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThanOrEqual<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;LessThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Max<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Min<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Multiply<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Multiply<>;(System.Runtime.Intrinsics.Vector128,T);generated | +| System.Runtime.Intrinsics;Vector128;Multiply<>;(T,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Narrow;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Negate<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;OnesComplement<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Sqrt<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Subtract<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;ToScalar<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;ToVector256<>;(System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector128;ToVector256Unsafe<>;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;TryCopyTo<>;(System.Runtime.Intrinsics.Vector128,System.Span);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Widen;(System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;Xor<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | +| System.Runtime.Intrinsics;Vector128;get_IsHardwareAccelerated;();generated | | System.Runtime.Intrinsics;Vector128<>;Equals;(System.Object);generated | | System.Runtime.Intrinsics;Vector128<>;Equals;(System.Runtime.Intrinsics.Vector128<>);generated | | System.Runtime.Intrinsics;Vector128<>;GetHashCode;();generated | | System.Runtime.Intrinsics;Vector128<>;ToString;();generated | | System.Runtime.Intrinsics;Vector128<>;get_AllBitsSet;();generated | | System.Runtime.Intrinsics;Vector128<>;get_Count;();generated | +| System.Runtime.Intrinsics;Vector128<>;get_Item;(System.Int32);generated | | System.Runtime.Intrinsics;Vector128<>;get_Zero;();generated | +| System.Runtime.Intrinsics;Vector256;Add<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;AndNot<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;As<,>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsByte<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsDouble<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsInt16<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsInt32<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsInt64<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;AsNInt<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;AsNUInt<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsSByte<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsSingle<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsUInt16<>;(System.Runtime.Intrinsics.Vector256);generated | @@ -31606,6 +31945,22 @@ neutral | System.Runtime.Intrinsics;Vector256;AsUInt64<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;AsVector256<>;(System.Numerics.Vector);generated | | System.Runtime.Intrinsics;Vector256;AsVector<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;BitwiseAnd<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;BitwiseOr<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Ceiling;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Ceiling;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConditionalSelect<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToDouble;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToDouble;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToInt32;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToInt64;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToSingle;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToSingle;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToUInt32;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;ConvertToUInt64;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;CopyTo<>;(System.Runtime.Intrinsics.Vector256,System.Span);generated | +| System.Runtime.Intrinsics;Vector256;CopyTo<>;(System.Runtime.Intrinsics.Vector256,T[]);generated | +| System.Runtime.Intrinsics;Vector256;CopyTo<>;(System.Runtime.Intrinsics.Vector256,T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Byte);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Double);generated | @@ -31616,6 +31971,7 @@ neutral | System.Runtime.Intrinsics;Vector256;Create;(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32,System.Int32);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Int64);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Int64,System.Int64,System.Int64,System.Int64);generated | +| System.Runtime.Intrinsics;Vector256;Create;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector128);generated | @@ -31636,36 +31992,91 @@ neutral | System.Runtime.Intrinsics;Vector256;Create;(System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.UInt64);generated | | System.Runtime.Intrinsics;Vector256;Create;(System.UInt64,System.UInt64,System.UInt64,System.UInt64);generated | +| System.Runtime.Intrinsics;Vector256;Create;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector256;Create<>;(System.ReadOnlySpan);generated | +| System.Runtime.Intrinsics;Vector256;Create<>;(T);generated | +| System.Runtime.Intrinsics;Vector256;Create<>;(T[]);generated | +| System.Runtime.Intrinsics;Vector256;Create<>;(T[],System.Int32);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Byte);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Double);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Int16);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Int32);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector256;CreateScalar;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.SByte);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.Single);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector256;CreateScalar;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector256;CreateScalar;(System.UIntPtr);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Byte);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Double);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Int16);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Int32);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Int64);generated | +| System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.IntPtr);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.SByte);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.Single);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.UInt16);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.UInt32);generated | | System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.UInt64);generated | +| System.Runtime.Intrinsics;Vector256;CreateScalarUnsafe;(System.UIntPtr);generated | +| System.Runtime.Intrinsics;Vector256;Divide<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Dot<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Equals<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;EqualsAll<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;EqualsAny<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Floor;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Floor;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;GetElement<>;(System.Runtime.Intrinsics.Vector256,System.Int32);generated | | System.Runtime.Intrinsics;Vector256;GetLower<>;(System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;GetUpper<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThan<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThanAll<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThanAny<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThanOrEqual<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;GreaterThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThan<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThanAll<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThanAny<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThanOrEqual<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThanOrEqualAll<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;LessThanOrEqualAny<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Max<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Min<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Multiply<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Multiply<>;(System.Runtime.Intrinsics.Vector256,T);generated | +| System.Runtime.Intrinsics;Vector256;Multiply<>;(T,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Narrow;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Negate<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;OnesComplement<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Sqrt<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Subtract<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | | System.Runtime.Intrinsics;Vector256;ToScalar<>;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;TryCopyTo<>;(System.Runtime.Intrinsics.Vector256,System.Span);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Widen;(System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;Xor<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector256);generated | +| System.Runtime.Intrinsics;Vector256;get_IsHardwareAccelerated;();generated | | System.Runtime.Intrinsics;Vector256<>;Equals;(System.Object);generated | | System.Runtime.Intrinsics;Vector256<>;Equals;(System.Runtime.Intrinsics.Vector256<>);generated | | System.Runtime.Intrinsics;Vector256<>;GetHashCode;();generated | | System.Runtime.Intrinsics;Vector256<>;ToString;();generated | | System.Runtime.Intrinsics;Vector256<>;get_AllBitsSet;();generated | | System.Runtime.Intrinsics;Vector256<>;get_Count;();generated | +| System.Runtime.Intrinsics;Vector256<>;get_Item;(System.Int32);generated | | System.Runtime.Intrinsics;Vector256<>;get_Zero;();generated | | System.Runtime.Loader;AssemblyDependencyResolver;AssemblyDependencyResolver;(System.String);generated | | System.Runtime.Loader;AssemblyLoadContext+ContextualReflectionScope;Dispose;();generated | @@ -32508,6 +32919,7 @@ neutral | System.Security.Cryptography.X509Certificates;X509Certificate2;CreateFromPem;(System.ReadOnlySpan);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;CreateFromPem;(System.ReadOnlySpan,System.ReadOnlySpan);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;CreateFromPemFile;(System.String,System.String);generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2;ExportCertificatePem;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;GetCertContentType;(System.Byte[]);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;GetCertContentType;(System.ReadOnlySpan);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;GetCertContentType;(System.String);generated | @@ -32521,6 +32933,7 @@ neutral | System.Security.Cryptography.X509Certificates;X509Certificate2;Import;(System.String,System.Security.SecureString,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;Import;(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;Reset;();generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2;TryExportCertificatePem;(System.Span,System.Int32);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;Verify;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;X509Certificate2;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;X509Certificate2;(System.Byte[]);generated | @@ -32543,6 +32956,7 @@ neutral | System.Security.Cryptography.X509Certificates;X509Certificate2;get_FriendlyName;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;get_HasPrivateKey;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;get_RawData;();generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2;get_RawDataMemory;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;get_Version;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;set_Archived;(System.Boolean);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2;set_FriendlyName;(System.String);generated | @@ -32550,6 +32964,8 @@ neutral | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Contains;(System.Security.Cryptography.X509Certificates.X509Certificate2);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Export;(System.Security.Cryptography.X509Certificates.X509ContentType);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Export;(System.Security.Cryptography.X509Certificates.X509ContentType,System.String);generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2Collection;ExportCertificatePems;();generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2Collection;ExportPkcs7Pem;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Import;(System.Byte[]);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Import;(System.Byte[],System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Import;(System.ReadOnlySpan);generated | @@ -32560,6 +32976,8 @@ neutral | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;Import;(System.String,System.String,System.Security.Cryptography.X509Certificates.X509KeyStorageFlags);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;ImportFromPem;(System.ReadOnlySpan);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;ImportFromPemFile;(System.String);generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2Collection;TryExportCertificatePems;(System.Span,System.Int32);generated | +| System.Security.Cryptography.X509Certificates;X509Certificate2Collection;TryExportPkcs7Pem;(System.Span,System.Int32);generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Collection;X509Certificate2Collection;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Enumerator;Dispose;();generated | | System.Security.Cryptography.X509Certificates;X509Certificate2Enumerator;MoveNext;();generated | @@ -32983,8 +33401,11 @@ neutral | System.Security.Cryptography;AsymmetricAlgorithm;Dispose;(System.Boolean);generated | | System.Security.Cryptography;AsymmetricAlgorithm;ExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters);generated | | System.Security.Cryptography;AsymmetricAlgorithm;ExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters);generated | +| System.Security.Cryptography;AsymmetricAlgorithm;ExportEncryptedPkcs8PrivateKeyPem;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters);generated | | System.Security.Cryptography;AsymmetricAlgorithm;ExportPkcs8PrivateKey;();generated | +| System.Security.Cryptography;AsymmetricAlgorithm;ExportPkcs8PrivateKeyPem;();generated | | System.Security.Cryptography;AsymmetricAlgorithm;ExportSubjectPublicKeyInfo;();generated | +| System.Security.Cryptography;AsymmetricAlgorithm;ExportSubjectPublicKeyInfoPem;();generated | | System.Security.Cryptography;AsymmetricAlgorithm;FromXmlString;(System.String);generated | | System.Security.Cryptography;AsymmetricAlgorithm;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | | System.Security.Cryptography;AsymmetricAlgorithm;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | @@ -32996,8 +33417,11 @@ neutral | System.Security.Cryptography;AsymmetricAlgorithm;ToXmlString;(System.Boolean);generated | | System.Security.Cryptography;AsymmetricAlgorithm;TryExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | | System.Security.Cryptography;AsymmetricAlgorithm;TryExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | +| System.Security.Cryptography;AsymmetricAlgorithm;TryExportEncryptedPkcs8PrivateKeyPem;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | | System.Security.Cryptography;AsymmetricAlgorithm;TryExportPkcs8PrivateKey;(System.Span,System.Int32);generated | +| System.Security.Cryptography;AsymmetricAlgorithm;TryExportPkcs8PrivateKeyPem;(System.Span,System.Int32);generated | | System.Security.Cryptography;AsymmetricAlgorithm;TryExportSubjectPublicKeyInfo;(System.Span,System.Int32);generated | +| System.Security.Cryptography;AsymmetricAlgorithm;TryExportSubjectPublicKeyInfoPem;(System.Span,System.Int32);generated | | System.Security.Cryptography;AsymmetricAlgorithm;get_KeyExchangeAlgorithm;();generated | | System.Security.Cryptography;AsymmetricAlgorithm;get_KeySize;();generated | | System.Security.Cryptography;AsymmetricAlgorithm;get_LegalKeySizes;();generated | @@ -33289,8 +33713,6 @@ neutral | System.Security.Cryptography;DSACng;DSACng;(System.Security.Cryptography.CngKey);generated | | System.Security.Cryptography;DSACng;Dispose;(System.Boolean);generated | | System.Security.Cryptography;DSACng;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;DSACng;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;DSACng;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;DSACng;ImportParameters;(System.Security.Cryptography.DSAParameters);generated | | System.Security.Cryptography;DSACng;VerifySignature;(System.Byte[],System.Byte[]);generated | | System.Security.Cryptography;DSACng;get_Key;();generated | @@ -33308,6 +33730,8 @@ neutral | System.Security.Cryptography;DSACryptoServiceProvider;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;DSACryptoServiceProvider;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;DSACryptoServiceProvider;ImportCspBlob;(System.Byte[]);generated | +| System.Security.Cryptography;DSACryptoServiceProvider;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;DSACryptoServiceProvider;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | | System.Security.Cryptography;DSACryptoServiceProvider;ImportParameters;(System.Security.Cryptography.DSAParameters);generated | | System.Security.Cryptography;DSACryptoServiceProvider;SignData;(System.Byte[]);generated | | System.Security.Cryptography;DSACryptoServiceProvider;SignData;(System.Byte[],System.Int32,System.Int32);generated | @@ -33332,15 +33756,10 @@ neutral | System.Security.Cryptography;DSAOpenSsl;DSAOpenSsl;(System.IntPtr);generated | | System.Security.Cryptography;DSAOpenSsl;DSAOpenSsl;(System.Security.Cryptography.DSAParameters);generated | | System.Security.Cryptography;DSAOpenSsl;DSAOpenSsl;(System.Security.Cryptography.SafeEvpPKeyHandle);generated | -| System.Security.Cryptography;DSAOpenSsl;Dispose;(System.Boolean);generated | | System.Security.Cryptography;DSAOpenSsl;DuplicateKeyHandle;();generated | | System.Security.Cryptography;DSAOpenSsl;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;DSAOpenSsl;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;DSAOpenSsl;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;DSAOpenSsl;ImportParameters;(System.Security.Cryptography.DSAParameters);generated | | System.Security.Cryptography;DSAOpenSsl;VerifySignature;(System.Byte[],System.Byte[]);generated | -| System.Security.Cryptography;DSAOpenSsl;get_LegalKeySizes;();generated | -| System.Security.Cryptography;DSAOpenSsl;set_KeySize;(System.Int32);generated | | System.Security.Cryptography;DSASignatureDeformatter;DSASignatureDeformatter;();generated | | System.Security.Cryptography;DSASignatureDeformatter;SetHashAlgorithm;(System.String);generated | | System.Security.Cryptography;DSASignatureDeformatter;VerifySignature;(System.Byte[],System.Byte[]);generated | @@ -33351,6 +33770,26 @@ neutral | System.Security.Cryptography;DeriveBytes;Dispose;(System.Boolean);generated | | System.Security.Cryptography;DeriveBytes;GetBytes;(System.Int32);generated | | System.Security.Cryptography;DeriveBytes;Reset;();generated | +| System.Security.Cryptography;ECAlgorithm;ExportECPrivateKey;();generated | +| System.Security.Cryptography;ECAlgorithm;ExportECPrivateKeyPem;();generated | +| System.Security.Cryptography;ECAlgorithm;ExportExplicitParameters;(System.Boolean);generated | +| System.Security.Cryptography;ECAlgorithm;ExportParameters;(System.Boolean);generated | +| System.Security.Cryptography;ECAlgorithm;GenerateKey;(System.Security.Cryptography.ECCurve);generated | +| System.Security.Cryptography;ECAlgorithm;ImportECPrivateKey;(System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;ImportFromEncryptedPem;(System.ReadOnlySpan,System.ReadOnlySpan);generated | +| System.Security.Cryptography;ECAlgorithm;ImportFromEncryptedPem;(System.ReadOnlySpan,System.ReadOnlySpan);generated | +| System.Security.Cryptography;ECAlgorithm;ImportFromPem;(System.ReadOnlySpan);generated | +| System.Security.Cryptography;ECAlgorithm;ImportParameters;(System.Security.Cryptography.ECParameters);generated | +| System.Security.Cryptography;ECAlgorithm;ImportPkcs8PrivateKey;(System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;ImportSubjectPublicKeyInfo;(System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportECPrivateKey;(System.Span,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportECPrivateKeyPem;(System.Span,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportPkcs8PrivateKey;(System.Span,System.Int32);generated | +| System.Security.Cryptography;ECAlgorithm;TryExportSubjectPublicKeyInfo;(System.Span,System.Int32);generated | | System.Security.Cryptography;ECCurve+NamedCurves;get_brainpoolP160r1;();generated | | System.Security.Cryptography;ECCurve+NamedCurves;get_brainpoolP160t1;();generated | | System.Security.Cryptography;ECCurve+NamedCurves;get_brainpoolP192r1;();generated | @@ -33436,19 +33875,13 @@ neutral | System.Security.Cryptography;ECDiffieHellmanCngPublicKey;Import;();generated | | System.Security.Cryptography;ECDiffieHellmanCngPublicKey;ToXmlString;();generated | | System.Security.Cryptography;ECDiffieHellmanCngPublicKey;get_BlobFormat;();generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;DeriveKeyFromHash;(System.Security.Cryptography.ECDiffieHellmanPublicKey,System.Security.Cryptography.HashAlgorithmName,System.Byte[],System.Byte[]);generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;DeriveKeyFromHmac;(System.Security.Cryptography.ECDiffieHellmanPublicKey,System.Security.Cryptography.HashAlgorithmName,System.Byte[],System.Byte[],System.Byte[]);generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;DeriveKeyMaterial;(System.Security.Cryptography.ECDiffieHellmanPublicKey);generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;DeriveKeyTls;(System.Security.Cryptography.ECDiffieHellmanPublicKey,System.Byte[],System.Byte[]);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;DuplicateKeyHandle;();generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ECDiffieHellmanOpenSsl;();generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ECDiffieHellmanOpenSsl;(System.Int32);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ECDiffieHellmanOpenSsl;(System.IntPtr);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ECDiffieHellmanOpenSsl;(System.Security.Cryptography.ECCurve);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ECDiffieHellmanOpenSsl;(System.Security.Cryptography.SafeEvpPKeyHandle);generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;ExportExplicitParameters;(System.Boolean);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;ECDiffieHellmanOpenSsl;GenerateKey;(System.Security.Cryptography.ECCurve);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;ImportParameters;(System.Security.Cryptography.ECParameters);generated | | System.Security.Cryptography;ECDiffieHellmanOpenSsl;get_PublicKey;();generated | | System.Security.Cryptography;ECDiffieHellmanPublicKey;Dispose;();generated | @@ -33515,8 +33948,6 @@ neutral | System.Security.Cryptography;ECDsaCng;ExportParameters;(System.Boolean);generated | | System.Security.Cryptography;ECDsaCng;FromXmlString;(System.String,System.Security.Cryptography.ECKeyXmlFormat);generated | | System.Security.Cryptography;ECDsaCng;GenerateKey;(System.Security.Cryptography.ECCurve);generated | -| System.Security.Cryptography;ECDsaCng;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;ECDsaCng;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;ECDsaCng;ImportParameters;(System.Security.Cryptography.ECParameters);generated | | System.Security.Cryptography;ECDsaCng;SignData;(System.Byte[]);generated | | System.Security.Cryptography;ECDsaCng;SignData;(System.Byte[],System.Int32,System.Int32);generated | @@ -33533,24 +33964,14 @@ neutral | System.Security.Cryptography;ECDsaCng;get_LegalKeySizes;();generated | | System.Security.Cryptography;ECDsaCng;set_HashAlgorithm;(System.Security.Cryptography.CngAlgorithm);generated | | System.Security.Cryptography;ECDsaCng;set_KeySize;(System.Int32);generated | -| System.Security.Cryptography;ECDsaOpenSsl;Dispose;(System.Boolean);generated | | System.Security.Cryptography;ECDsaOpenSsl;DuplicateKeyHandle;();generated | | System.Security.Cryptography;ECDsaOpenSsl;ECDsaOpenSsl;();generated | | System.Security.Cryptography;ECDsaOpenSsl;ECDsaOpenSsl;(System.Int32);generated | | System.Security.Cryptography;ECDsaOpenSsl;ECDsaOpenSsl;(System.IntPtr);generated | | System.Security.Cryptography;ECDsaOpenSsl;ECDsaOpenSsl;(System.Security.Cryptography.ECCurve);generated | | System.Security.Cryptography;ECDsaOpenSsl;ECDsaOpenSsl;(System.Security.Cryptography.SafeEvpPKeyHandle);generated | -| System.Security.Cryptography;ECDsaOpenSsl;ExportExplicitParameters;(System.Boolean);generated | -| System.Security.Cryptography;ECDsaOpenSsl;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;ECDsaOpenSsl;GenerateKey;(System.Security.Cryptography.ECCurve);generated | -| System.Security.Cryptography;ECDsaOpenSsl;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;ECDsaOpenSsl;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;ECDsaOpenSsl;ImportParameters;(System.Security.Cryptography.ECParameters);generated | | System.Security.Cryptography;ECDsaOpenSsl;SignHash;(System.Byte[]);generated | | System.Security.Cryptography;ECDsaOpenSsl;VerifyHash;(System.Byte[],System.Byte[]);generated | -| System.Security.Cryptography;ECDsaOpenSsl;get_KeySize;();generated | -| System.Security.Cryptography;ECDsaOpenSsl;get_LegalKeySizes;();generated | -| System.Security.Cryptography;ECDsaOpenSsl;set_KeySize;(System.Int32);generated | | System.Security.Cryptography;ECParameters;Validate;();generated | | System.Security.Cryptography;FromBase64Transform;Clear;();generated | | System.Security.Cryptography;FromBase64Transform;Dispose;();generated | @@ -33808,7 +34229,9 @@ neutral | System.Security.Cryptography;RSA;EncryptValue;(System.Byte[]);generated | | System.Security.Cryptography;RSA;ExportParameters;(System.Boolean);generated | | System.Security.Cryptography;RSA;ExportRSAPrivateKey;();generated | +| System.Security.Cryptography;RSA;ExportRSAPrivateKeyPem;();generated | | System.Security.Cryptography;RSA;ExportRSAPublicKey;();generated | +| System.Security.Cryptography;RSA;ExportRSAPublicKeyPem;();generated | | System.Security.Cryptography;RSA;FromXmlString;(System.String);generated | | System.Security.Cryptography;RSA;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;RSA;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | @@ -33833,7 +34256,9 @@ neutral | System.Security.Cryptography;RSA;TryExportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.Security.Cryptography.PbeParameters,System.Span,System.Int32);generated | | System.Security.Cryptography;RSA;TryExportPkcs8PrivateKey;(System.Span,System.Int32);generated | | System.Security.Cryptography;RSA;TryExportRSAPrivateKey;(System.Span,System.Int32);generated | +| System.Security.Cryptography;RSA;TryExportRSAPrivateKeyPem;(System.Span,System.Int32);generated | | System.Security.Cryptography;RSA;TryExportRSAPublicKey;(System.Span,System.Int32);generated | +| System.Security.Cryptography;RSA;TryExportRSAPublicKeyPem;(System.Span,System.Int32);generated | | System.Security.Cryptography;RSA;TryExportSubjectPublicKeyInfo;(System.Span,System.Int32);generated | | System.Security.Cryptography;RSA;TryHashData;(System.ReadOnlySpan,System.Span,System.Security.Cryptography.HashAlgorithmName,System.Int32);generated | | System.Security.Cryptography;RSA;TrySignData;(System.ReadOnlySpan,System.Span,System.Security.Cryptography.HashAlgorithmName,System.Security.Cryptography.RSASignaturePadding,System.Int32);generated | @@ -33850,8 +34275,6 @@ neutral | System.Security.Cryptography;RSACng;Dispose;(System.Boolean);generated | | System.Security.Cryptography;RSACng;Encrypt;(System.Byte[],System.Security.Cryptography.RSAEncryptionPadding);generated | | System.Security.Cryptography;RSACng;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;RSACng;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;RSACng;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;RSACng;ImportParameters;(System.Security.Cryptography.RSAParameters);generated | | System.Security.Cryptography;RSACng;RSACng;();generated | | System.Security.Cryptography;RSACng;RSACng;(System.Int32);generated | @@ -33869,9 +34292,9 @@ neutral | System.Security.Cryptography;RSACryptoServiceProvider;EncryptValue;(System.Byte[]);generated | | System.Security.Cryptography;RSACryptoServiceProvider;ExportCspBlob;(System.Boolean);generated | | System.Security.Cryptography;RSACryptoServiceProvider;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;RSACryptoServiceProvider;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;RSACryptoServiceProvider;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;RSACryptoServiceProvider;ImportCspBlob;(System.Byte[]);generated | +| System.Security.Cryptography;RSACryptoServiceProvider;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | +| System.Security.Cryptography;RSACryptoServiceProvider;ImportEncryptedPkcs8PrivateKey;(System.ReadOnlySpan,System.ReadOnlySpan,System.Int32);generated | | System.Security.Cryptography;RSACryptoServiceProvider;ImportParameters;(System.Security.Cryptography.RSAParameters);generated | | System.Security.Cryptography;RSACryptoServiceProvider;RSACryptoServiceProvider;();generated | | System.Security.Cryptography;RSACryptoServiceProvider;RSACryptoServiceProvider;(System.Int32);generated | @@ -33914,23 +34337,14 @@ neutral | System.Security.Cryptography;RSAOAEPKeyExchangeFormatter;get_Parameter;();generated | | System.Security.Cryptography;RSAOAEPKeyExchangeFormatter;get_Parameters;();generated | | System.Security.Cryptography;RSAOAEPKeyExchangeFormatter;set_Parameter;(System.Byte[]);generated | -| System.Security.Cryptography;RSAOpenSsl;Decrypt;(System.Byte[],System.Security.Cryptography.RSAEncryptionPadding);generated | -| System.Security.Cryptography;RSAOpenSsl;Dispose;(System.Boolean);generated | | System.Security.Cryptography;RSAOpenSsl;DuplicateKeyHandle;();generated | -| System.Security.Cryptography;RSAOpenSsl;Encrypt;(System.Byte[],System.Security.Cryptography.RSAEncryptionPadding);generated | | System.Security.Cryptography;RSAOpenSsl;ExportParameters;(System.Boolean);generated | -| System.Security.Cryptography;RSAOpenSsl;HashData;(System.Byte[],System.Int32,System.Int32,System.Security.Cryptography.HashAlgorithmName);generated | -| System.Security.Cryptography;RSAOpenSsl;HashData;(System.IO.Stream,System.Security.Cryptography.HashAlgorithmName);generated | | System.Security.Cryptography;RSAOpenSsl;ImportParameters;(System.Security.Cryptography.RSAParameters);generated | | System.Security.Cryptography;RSAOpenSsl;RSAOpenSsl;();generated | | System.Security.Cryptography;RSAOpenSsl;RSAOpenSsl;(System.Int32);generated | | System.Security.Cryptography;RSAOpenSsl;RSAOpenSsl;(System.IntPtr);generated | | System.Security.Cryptography;RSAOpenSsl;RSAOpenSsl;(System.Security.Cryptography.RSAParameters);generated | | System.Security.Cryptography;RSAOpenSsl;RSAOpenSsl;(System.Security.Cryptography.SafeEvpPKeyHandle);generated | -| System.Security.Cryptography;RSAOpenSsl;SignHash;(System.Byte[],System.Security.Cryptography.HashAlgorithmName,System.Security.Cryptography.RSASignaturePadding);generated | -| System.Security.Cryptography;RSAOpenSsl;VerifyHash;(System.Byte[],System.Byte[],System.Security.Cryptography.HashAlgorithmName,System.Security.Cryptography.RSASignaturePadding);generated | -| System.Security.Cryptography;RSAOpenSsl;get_LegalKeySizes;();generated | -| System.Security.Cryptography;RSAOpenSsl;set_KeySize;(System.Int32);generated | | System.Security.Cryptography;RSAPKCS1KeyExchangeDeformatter;DecryptKeyExchange;(System.Byte[]);generated | | System.Security.Cryptography;RSAPKCS1KeyExchangeDeformatter;RSAPKCS1KeyExchangeDeformatter;();generated | | System.Security.Cryptography;RSAPKCS1KeyExchangeDeformatter;get_Parameters;();generated | @@ -34910,6 +35324,7 @@ neutral | System.Text.Json;JsonSerializerOptions;JsonSerializerOptions;(System.Text.Json.JsonSerializerDefaults);generated | | System.Text.Json;JsonSerializerOptions;get_AllowTrailingCommas;();generated | | System.Text.Json;JsonSerializerOptions;get_Converters;();generated | +| System.Text.Json;JsonSerializerOptions;get_Default;();generated | | System.Text.Json;JsonSerializerOptions;get_DefaultBufferSize;();generated | | System.Text.Json;JsonSerializerOptions;get_DefaultIgnoreCondition;();generated | | System.Text.Json;JsonSerializerOptions;get_IgnoreNullValues;();generated | @@ -34937,9 +35352,11 @@ neutral | System.Text.Json;JsonSerializerOptions;set_WriteIndented;(System.Boolean);generated | | System.Text.Json;JsonWriterOptions;get_Encoder;();generated | | System.Text.Json;JsonWriterOptions;get_Indented;();generated | +| System.Text.Json;JsonWriterOptions;get_MaxDepth;();generated | | System.Text.Json;JsonWriterOptions;get_SkipValidation;();generated | | System.Text.Json;JsonWriterOptions;set_Encoder;(System.Text.Encodings.Web.JavaScriptEncoder);generated | | System.Text.Json;JsonWriterOptions;set_Indented;(System.Boolean);generated | +| System.Text.Json;JsonWriterOptions;set_MaxDepth;(System.Int32);generated | | System.Text.Json;JsonWriterOptions;set_SkipValidation;(System.Boolean);generated | | System.Text.Json;Utf8JsonReader;GetBoolean;();generated | | System.Text.Json;Utf8JsonReader;GetByte;();generated | @@ -35735,6 +36152,34 @@ neutral | System.Threading.Channels;ChannelWriter<>;TryWrite;(T);generated | | System.Threading.Channels;ChannelWriter<>;WaitToWriteAsync;(System.Threading.CancellationToken);generated | | System.Threading.Channels;ChannelWriter<>;WriteAsync;(T,System.Threading.CancellationToken);generated | +| System.Threading.RateLimiting;ConcurrencyLimiter;Dispose;(System.Boolean);generated | +| System.Threading.RateLimiting;ConcurrencyLimiter;DisposeAsyncCore;();generated | +| System.Threading.RateLimiting;ConcurrencyLimiterOptions;get_PermitLimit;();generated | +| System.Threading.RateLimiting;ConcurrencyLimiterOptions;get_QueueLimit;();generated | +| System.Threading.RateLimiting;ConcurrencyLimiterOptions;get_QueueProcessingOrder;();generated | +| System.Threading.RateLimiting;MetadataName;get_ReasonPhrase;();generated | +| System.Threading.RateLimiting;MetadataName;get_RetryAfter;();generated | +| System.Threading.RateLimiting;MetadataName<>;Equals;(System.Object);generated | +| System.Threading.RateLimiting;MetadataName<>;Equals;(System.Threading.RateLimiting.MetadataName<>);generated | +| System.Threading.RateLimiting;MetadataName<>;GetHashCode;();generated | +| System.Threading.RateLimiting;RateLimitLease;Dispose;();generated | +| System.Threading.RateLimiting;RateLimitLease;Dispose;(System.Boolean);generated | +| System.Threading.RateLimiting;RateLimitLease;TryGetMetadata;(System.String,System.Object);generated | +| System.Threading.RateLimiting;RateLimitLease;get_IsAcquired;();generated | +| System.Threading.RateLimiting;RateLimitLease;get_MetadataNames;();generated | +| System.Threading.RateLimiting;RateLimiter;Dispose;();generated | +| System.Threading.RateLimiting;RateLimiter;Dispose;(System.Boolean);generated | +| System.Threading.RateLimiting;RateLimiter;DisposeAsync;();generated | +| System.Threading.RateLimiting;RateLimiter;DisposeAsyncCore;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiter;Dispose;(System.Boolean);generated | +| System.Threading.RateLimiting;TokenBucketRateLimiter;DisposeAsyncCore;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiter;TryReplenish;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_AutoReplenishment;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_QueueLimit;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_QueueProcessingOrder;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_ReplenishmentPeriod;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_TokenLimit;();generated | +| System.Threading.RateLimiting;TokenBucketRateLimiterOptions;get_TokensPerPeriod;();generated | | System.Threading.Tasks.Dataflow;ActionBlock<>;Complete;();generated | | System.Threading.Tasks.Dataflow;ActionBlock<>;Fault;(System.Exception);generated | | System.Threading.Tasks.Dataflow;ActionBlock<>;OfferMessage;(System.Threading.Tasks.Dataflow.DataflowMessageHeader,TInput,System.Threading.Tasks.Dataflow.ISourceBlock,System.Boolean);generated | @@ -35942,6 +36387,7 @@ neutral | System.Threading.Tasks;Task;get_IsFaulted;();generated | | System.Threading.Tasks;Task;get_Status;();generated | | System.Threading.Tasks;Task<>;get_Factory;();generated | +| System.Threading.Tasks;TaskAsyncEnumerableExtensions;ToBlockingEnumerable<>;(System.Collections.Generic.IAsyncEnumerable,System.Threading.CancellationToken);generated | | System.Threading.Tasks;TaskCanceledException;TaskCanceledException;();generated | | System.Threading.Tasks;TaskCanceledException;TaskCanceledException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System.Threading.Tasks;TaskCanceledException;TaskCanceledException;(System.String);generated | @@ -38262,6 +38708,7 @@ neutral | System;AggregateException;Flatten;();generated | | System;AggregateException;get_InnerExceptions;();generated | | System;AppContext;GetData;(System.String);generated | +| System;AppContext;SetData;(System.String,System.Object);generated | | System;AppContext;SetSwitch;(System.String,System.Boolean);generated | | System;AppContext;TryGetSwitch;(System.String,System.Boolean);generated | | System;AppContext;get_BaseDirectory;();generated | @@ -38364,6 +38811,7 @@ neutral | System;ArgumentNullException;ArgumentNullException;(System.String,System.Exception);generated | | System;ArgumentNullException;ArgumentNullException;(System.String,System.String);generated | | System;ArgumentNullException;ThrowIfNull;(System.Object,System.String);generated | +| System;ArgumentNullException;ThrowIfNull;(System.Void*,System.String);generated | | System;ArgumentOutOfRangeException;ArgumentOutOfRangeException;();generated | | System;ArgumentOutOfRangeException;ArgumentOutOfRangeException;(System.String);generated | | System;ArgumentOutOfRangeException;ArgumentOutOfRangeException;(System.String,System.Exception);generated | @@ -38619,17 +39067,32 @@ neutral | System;Buffer;MemoryCopy;(System.Void*,System.Void*,System.Int64,System.Int64);generated | | System;Buffer;MemoryCopy;(System.Void*,System.Void*,System.UInt64,System.UInt64);generated | | System;Buffer;SetByte;(System.Array,System.Int32,System.Byte);generated | +| System;Byte;Abs;(System.Byte);generated | +| System;Byte;Clamp;(System.Byte,System.Byte,System.Byte);generated | | System;Byte;CompareTo;(System.Byte);generated | | System;Byte;CompareTo;(System.Object);generated | +| System;Byte;CreateSaturating<>;(TOther);generated | +| System;Byte;CreateTruncating<>;(TOther);generated | +| System;Byte;DivRem;(System.Byte,System.Byte);generated | | System;Byte;Equals;(System.Byte);generated | | System;Byte;Equals;(System.Object);generated | | System;Byte;GetHashCode;();generated | | System;Byte;GetTypeCode;();generated | +| System;Byte;IsPow2;(System.Byte);generated | +| System;Byte;LeadingZeroCount;(System.Byte);generated | +| System;Byte;Log2;(System.Byte);generated | +| System;Byte;Max;(System.Byte,System.Byte);generated | +| System;Byte;Min;(System.Byte,System.Byte);generated | | System;Byte;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Byte;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Byte;Parse;(System.String);generated | | System;Byte;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Byte;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Byte;Parse;(System.String,System.IFormatProvider);generated | +| System;Byte;PopCount;(System.Byte);generated | +| System;Byte;RotateLeft;(System.Byte,System.Int32);generated | +| System;Byte;RotateRight;(System.Byte,System.Int32);generated | +| System;Byte;Sign;(System.Byte);generated | | System;Byte;ToBoolean;(System.IFormatProvider);generated | | System;Byte;ToByte;(System.IFormatProvider);generated | | System;Byte;ToChar;(System.IFormatProvider);generated | @@ -38649,17 +39112,27 @@ neutral | System;Byte;ToUInt16;(System.IFormatProvider);generated | | System;Byte;ToUInt32;(System.IFormatProvider);generated | | System;Byte;ToUInt64;(System.IFormatProvider);generated | +| System;Byte;TrailingZeroCount;(System.Byte);generated | | System;Byte;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Byte;TryParse;(System.ReadOnlySpan,System.Byte);generated | | System;Byte;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Byte);generated | +| System;Byte;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Byte);generated | | System;Byte;TryParse;(System.String,System.Byte);generated | | System;Byte;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Byte);generated | +| System;Byte;TryParse;(System.String,System.IFormatProvider,System.Byte);generated | +| System;Byte;get_AdditiveIdentity;();generated | +| System;Byte;get_MaxValue;();generated | +| System;Byte;get_MinValue;();generated | +| System;Byte;get_MultiplicativeIdentity;();generated | +| System;Byte;get_One;();generated | +| System;Byte;get_Zero;();generated | | System;CLSCompliantAttribute;CLSCompliantAttribute;(System.Boolean);generated | | System;CLSCompliantAttribute;get_IsCompliant;();generated | | System;CannotUnloadAppDomainException;CannotUnloadAppDomainException;();generated | | System;CannotUnloadAppDomainException;CannotUnloadAppDomainException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;CannotUnloadAppDomainException;CannotUnloadAppDomainException;(System.String);generated | | System;CannotUnloadAppDomainException;CannotUnloadAppDomainException;(System.String,System.Exception);generated | +| System;Char;Abs;(System.Char);generated | | System;Char;CompareTo;(System.Char);generated | | System;Char;CompareTo;(System.Object);generated | | System;Char;ConvertFromUtf32;(System.Int32);generated | @@ -38690,6 +39163,7 @@ neutral | System;Char;IsLower;(System.String,System.Int32);generated | | System;Char;IsNumber;(System.Char);generated | | System;Char;IsNumber;(System.String,System.Int32);generated | +| System;Char;IsPow2;(System.Char);generated | | System;Char;IsPunctuation;(System.Char);generated | | System;Char;IsPunctuation;(System.String,System.Int32);generated | | System;Char;IsSeparator;(System.Char);generated | @@ -38704,7 +39178,16 @@ neutral | System;Char;IsUpper;(System.String,System.Int32);generated | | System;Char;IsWhiteSpace;(System.Char);generated | | System;Char;IsWhiteSpace;(System.String,System.Int32);generated | +| System;Char;LeadingZeroCount;(System.Char);generated | +| System;Char;Log2;(System.Char);generated | +| System;Char;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Char;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Char;Parse;(System.String);generated | +| System;Char;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Char;Parse;(System.String,System.IFormatProvider);generated | +| System;Char;PopCount;(System.Char);generated | +| System;Char;RotateLeft;(System.Char,System.Int32);generated | +| System;Char;RotateRight;(System.Char,System.Int32);generated | | System;Char;ToBoolean;(System.IFormatProvider);generated | | System;Char;ToByte;(System.IFormatProvider);generated | | System;Char;ToChar;(System.IFormatProvider);generated | @@ -38730,8 +39213,19 @@ neutral | System;Char;ToUpper;(System.Char);generated | | System;Char;ToUpper;(System.Char,System.Globalization.CultureInfo);generated | | System;Char;ToUpperInvariant;(System.Char);generated | +| System;Char;TrailingZeroCount;(System.Char);generated | | System;Char;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | +| System;Char;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Char);generated | +| System;Char;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Char);generated | | System;Char;TryParse;(System.String,System.Char);generated | +| System;Char;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Char);generated | +| System;Char;TryParse;(System.String,System.IFormatProvider,System.Char);generated | +| System;Char;get_AdditiveIdentity;();generated | +| System;Char;get_MaxValue;();generated | +| System;Char;get_MinValue;();generated | +| System;Char;get_MultiplicativeIdentity;();generated | +| System;Char;get_One;();generated | +| System;Char;get_Zero;();generated | | System;CharEnumerator;Clone;();generated | | System;CharEnumerator;Dispose;();generated | | System;CharEnumerator;MoveNext;();generated | @@ -38888,8 +39382,10 @@ neutral | System;DateOnly;FromDateTime;(System.DateTime);generated | | System;DateOnly;FromDayNumber;(System.Int32);generated | | System;DateOnly;GetHashCode;();generated | +| System;DateOnly;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateOnly;Parse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;DateOnly;Parse;(System.String);generated | +| System;DateOnly;Parse;(System.String,System.IFormatProvider);generated | | System;DateOnly;Parse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;DateOnly;ParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;DateOnly;ParseExact;(System.ReadOnlySpan,System.String[]);generated | @@ -38906,8 +39402,10 @@ neutral | System;DateOnly;ToString;(System.String);generated | | System;DateOnly;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateOnly;TryParse;(System.ReadOnlySpan,System.DateOnly);generated | +| System;DateOnly;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.DateOnly);generated | | System;DateOnly;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateOnly);generated | | System;DateOnly;TryParse;(System.String,System.DateOnly);generated | +| System;DateOnly;TryParse;(System.String,System.IFormatProvider,System.DateOnly);generated | | System;DateOnly;TryParse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateOnly);generated | | System;DateOnly;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.DateOnly);generated | | System;DateOnly;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateOnly);generated | @@ -38964,6 +39462,7 @@ neutral | System;DateTime;GetTypeCode;();generated | | System;DateTime;IsDaylightSavingTime;();generated | | System;DateTime;IsLeapYear;(System.Int32);generated | +| System;DateTime;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateTime;Parse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;DateTime;Parse;(System.String);generated | | System;DateTime;Parse;(System.String,System.IFormatProvider);generated | @@ -39001,8 +39500,10 @@ neutral | System;DateTime;ToUInt64;(System.IFormatProvider);generated | | System;DateTime;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateTime;TryParse;(System.ReadOnlySpan,System.DateTime);generated | +| System;DateTime;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.DateTime);generated | | System;DateTime;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime);generated | | System;DateTime;TryParse;(System.String,System.DateTime);generated | +| System;DateTime;TryParse;(System.String,System.IFormatProvider,System.DateTime);generated | | System;DateTime;TryParse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime);generated | | System;DateTime;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime);generated | | System;DateTime;TryParseExact;(System.ReadOnlySpan,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTime);generated | @@ -39051,6 +39552,7 @@ neutral | System;DateTimeOffset;FromUnixTimeSeconds;(System.Int64);generated | | System;DateTimeOffset;GetHashCode;();generated | | System;DateTimeOffset;OnDeserialization;(System.Object);generated | +| System;DateTimeOffset;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateTimeOffset;Parse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;DateTimeOffset;Parse;(System.String);generated | | System;DateTimeOffset;Parse;(System.String,System.IFormatProvider);generated | @@ -39072,8 +39574,10 @@ neutral | System;DateTimeOffset;ToUnixTimeSeconds;();generated | | System;DateTimeOffset;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;DateTimeOffset;TryParse;(System.ReadOnlySpan,System.DateTimeOffset);generated | +| System;DateTimeOffset;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.DateTimeOffset);generated | | System;DateTimeOffset;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset);generated | | System;DateTimeOffset;TryParse;(System.String,System.DateTimeOffset);generated | +| System;DateTimeOffset;TryParse;(System.String,System.IFormatProvider,System.DateTimeOffset);generated | | System;DateTimeOffset;TryParse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset);generated | | System;DateTimeOffset;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset);generated | | System;DateTimeOffset;TryParseExact;(System.ReadOnlySpan,System.String[],System.IFormatProvider,System.Globalization.DateTimeStyles,System.DateTimeOffset);generated | @@ -39098,11 +39602,15 @@ neutral | System;DateTimeOffset;get_UtcNow;();generated | | System;DateTimeOffset;get_UtcTicks;();generated | | System;DateTimeOffset;get_Year;();generated | +| System;Decimal;Abs;(System.Decimal);generated | | System;Decimal;Add;(System.Decimal,System.Decimal);generated | | System;Decimal;Ceiling;(System.Decimal);generated | +| System;Decimal;Clamp;(System.Decimal,System.Decimal,System.Decimal);generated | | System;Decimal;Compare;(System.Decimal,System.Decimal);generated | | System;Decimal;CompareTo;(System.Decimal);generated | | System;Decimal;CompareTo;(System.Object);generated | +| System;Decimal;CreateSaturating<>;(TOther);generated | +| System;Decimal;CreateTruncating<>;(TOther);generated | | System;Decimal;Decimal;(System.Double);generated | | System;Decimal;Decimal;(System.Int32);generated | | System;Decimal;Decimal;(System.Int32,System.Int32,System.Int32,System.Boolean,System.Byte);generated | @@ -39123,10 +39631,13 @@ neutral | System;Decimal;GetHashCode;();generated | | System;Decimal;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;Decimal;GetTypeCode;();generated | +| System;Decimal;Max;(System.Decimal,System.Decimal);generated | +| System;Decimal;Min;(System.Decimal,System.Decimal);generated | | System;Decimal;Multiply;(System.Decimal,System.Decimal);generated | | System;Decimal;Negate;(System.Decimal);generated | | System;Decimal;OnDeserialization;(System.Object);generated | | System;Decimal;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Decimal;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Decimal;Parse;(System.String);generated | | System;Decimal;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Decimal;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | @@ -39136,6 +39647,7 @@ neutral | System;Decimal;Round;(System.Decimal,System.Int32);generated | | System;Decimal;Round;(System.Decimal,System.Int32,System.MidpointRounding);generated | | System;Decimal;Round;(System.Decimal,System.MidpointRounding);generated | +| System;Decimal;Sign;(System.Decimal);generated | | System;Decimal;Subtract;(System.Decimal,System.Decimal);generated | | System;Decimal;ToBoolean;(System.IFormatProvider);generated | | System;Decimal;ToByte;(System.Decimal);generated | @@ -39171,8 +39683,17 @@ neutral | System;Decimal;TryGetBits;(System.Decimal,System.Span,System.Int32);generated | | System;Decimal;TryParse;(System.ReadOnlySpan,System.Decimal);generated | | System;Decimal;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Decimal);generated | +| System;Decimal;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Decimal);generated | | System;Decimal;TryParse;(System.String,System.Decimal);generated | | System;Decimal;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Decimal);generated | +| System;Decimal;TryParse;(System.String,System.IFormatProvider,System.Decimal);generated | +| System;Decimal;get_AdditiveIdentity;();generated | +| System;Decimal;get_MaxValue;();generated | +| System;Decimal;get_MinValue;();generated | +| System;Decimal;get_MultiplicativeIdentity;();generated | +| System;Decimal;get_NegativeOne;();generated | +| System;Decimal;get_One;();generated | +| System;Decimal;get_Zero;();generated | | System;Delegate;Clone;();generated | | System;Delegate;CombineImpl;(System.Delegate);generated | | System;Delegate;CreateDelegate;(System.Type,System.Object,System.Reflection.MethodInfo);generated | @@ -39195,10 +39716,31 @@ neutral | System;DllNotFoundException;DllNotFoundException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;DllNotFoundException;DllNotFoundException;(System.String);generated | | System;DllNotFoundException;DllNotFoundException;(System.String,System.Exception);generated | +| System;Double;Abs;(System.Double);generated | +| System;Double;Acos;(System.Double);generated | +| System;Double;Acosh;(System.Double);generated | +| System;Double;Asin;(System.Double);generated | +| System;Double;Asinh;(System.Double);generated | +| System;Double;Atan2;(System.Double,System.Double);generated | +| System;Double;Atan;(System.Double);generated | +| System;Double;Atanh;(System.Double);generated | +| System;Double;BitDecrement;(System.Double);generated | +| System;Double;BitIncrement;(System.Double);generated | +| System;Double;Cbrt;(System.Double);generated | +| System;Double;Ceiling;(System.Double);generated | +| System;Double;Clamp;(System.Double,System.Double,System.Double);generated | | System;Double;CompareTo;(System.Double);generated | | System;Double;CompareTo;(System.Object);generated | +| System;Double;CopySign;(System.Double,System.Double);generated | +| System;Double;Cos;(System.Double);generated | +| System;Double;Cosh;(System.Double);generated | +| System;Double;CreateSaturating<>;(TOther);generated | +| System;Double;CreateTruncating<>;(TOther);generated | | System;Double;Equals;(System.Double);generated | | System;Double;Equals;(System.Object);generated | +| System;Double;Exp;(System.Double);generated | +| System;Double;Floor;(System.Double);generated | +| System;Double;FusedMultiplyAdd;(System.Double,System.Double,System.Double);generated | | System;Double;GetHashCode;();generated | | System;Double;GetTypeCode;();generated | | System;Double;IsFinite;(System.Double);generated | @@ -39208,12 +39750,31 @@ neutral | System;Double;IsNegativeInfinity;(System.Double);generated | | System;Double;IsNormal;(System.Double);generated | | System;Double;IsPositiveInfinity;(System.Double);generated | +| System;Double;IsPow2;(System.Double);generated | | System;Double;IsSubnormal;(System.Double);generated | +| System;Double;Log2;(System.Double);generated | +| System;Double;Log10;(System.Double);generated | +| System;Double;Log;(System.Double);generated | +| System;Double;Log;(System.Double,System.Double);generated | +| System;Double;Max;(System.Double,System.Double);generated | +| System;Double;MaxMagnitude;(System.Double,System.Double);generated | +| System;Double;Min;(System.Double,System.Double);generated | +| System;Double;MinMagnitude;(System.Double,System.Double);generated | | System;Double;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Double;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Double;Parse;(System.String);generated | | System;Double;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Double;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Double;Parse;(System.String,System.IFormatProvider);generated | +| System;Double;Pow;(System.Double,System.Double);generated | +| System;Double;Round;(System.Double);generated | +| System;Double;Round;(System.Double,System.MidpointRounding);generated | +| System;Double;Sign;(System.Double);generated | +| System;Double;Sin;(System.Double);generated | +| System;Double;Sinh;(System.Double);generated | +| System;Double;Sqrt;(System.Double);generated | +| System;Double;Tan;(System.Double);generated | +| System;Double;Tanh;(System.Double);generated | | System;Double;ToBoolean;(System.IFormatProvider);generated | | System;Double;ToByte;(System.IFormatProvider);generated | | System;Double;ToChar;(System.IFormatProvider);generated | @@ -39230,11 +39791,29 @@ neutral | System;Double;ToUInt16;(System.IFormatProvider);generated | | System;Double;ToUInt32;(System.IFormatProvider);generated | | System;Double;ToUInt64;(System.IFormatProvider);generated | +| System;Double;Truncate;(System.Double);generated | | System;Double;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Double;TryParse;(System.ReadOnlySpan,System.Double);generated | | System;Double;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Double);generated | +| System;Double;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Double);generated | | System;Double;TryParse;(System.String,System.Double);generated | | System;Double;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Double);generated | +| System;Double;TryParse;(System.String,System.IFormatProvider,System.Double);generated | +| System;Double;get_AdditiveIdentity;();generated | +| System;Double;get_E;();generated | +| System;Double;get_Epsilon;();generated | +| System;Double;get_MaxValue;();generated | +| System;Double;get_MinValue;();generated | +| System;Double;get_MultiplicativeIdentity;();generated | +| System;Double;get_NaN;();generated | +| System;Double;get_NegativeInfinity;();generated | +| System;Double;get_NegativeOne;();generated | +| System;Double;get_NegativeZero;();generated | +| System;Double;get_One;();generated | +| System;Double;get_Pi;();generated | +| System;Double;get_PositiveInfinity;();generated | +| System;Double;get_Tau;();generated | +| System;Double;get_Zero;();generated | | System;DuplicateWaitObjectException;DuplicateWaitObjectException;();generated | | System;DuplicateWaitObjectException;DuplicateWaitObjectException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;DuplicateWaitObjectException;DuplicateWaitObjectException;(System.String);generated | @@ -39434,7 +40013,9 @@ neutral | System;Guid;Guid;(System.UInt32,System.UInt16,System.UInt16,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte,System.Byte);generated | | System;Guid;NewGuid;();generated | | System;Guid;Parse;(System.ReadOnlySpan);generated | +| System;Guid;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Guid;Parse;(System.String);generated | +| System;Guid;Parse;(System.String,System.IFormatProvider);generated | | System;Guid;ParseExact;(System.ReadOnlySpan,System.ReadOnlySpan);generated | | System;Guid;ParseExact;(System.String,System.String);generated | | System;Guid;ToByteArray;();generated | @@ -39444,14 +40025,35 @@ neutral | System;Guid;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan);generated | | System;Guid;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Guid;TryParse;(System.ReadOnlySpan,System.Guid);generated | +| System;Guid;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Guid);generated | | System;Guid;TryParse;(System.String,System.Guid);generated | +| System;Guid;TryParse;(System.String,System.IFormatProvider,System.Guid);generated | | System;Guid;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.Guid);generated | | System;Guid;TryParseExact;(System.String,System.String,System.Guid);generated | | System;Guid;TryWriteBytes;(System.Span);generated | +| System;Half;Abs;(System.Half);generated | +| System;Half;Acos;(System.Half);generated | +| System;Half;Acosh;(System.Half);generated | +| System;Half;Asin;(System.Half);generated | +| System;Half;Asinh;(System.Half);generated | +| System;Half;Atan2;(System.Half,System.Half);generated | +| System;Half;Atan;(System.Half);generated | +| System;Half;Atanh;(System.Half);generated | +| System;Half;Cbrt;(System.Half);generated | +| System;Half;Ceiling;(System.Half);generated | +| System;Half;Clamp;(System.Half,System.Half,System.Half);generated | | System;Half;CompareTo;(System.Half);generated | | System;Half;CompareTo;(System.Object);generated | +| System;Half;CopySign;(System.Half,System.Half);generated | +| System;Half;Cos;(System.Half);generated | +| System;Half;Cosh;(System.Half);generated | +| System;Half;CreateSaturating<>;(TOther);generated | +| System;Half;CreateTruncating<>;(TOther);generated | | System;Half;Equals;(System.Half);generated | | System;Half;Equals;(System.Object);generated | +| System;Half;Exp;(System.Half);generated | +| System;Half;Floor;(System.Half);generated | +| System;Half;FusedMultiplyAdd;(System.Half,System.Half,System.Half);generated | | System;Half;GetHashCode;();generated | | System;Half;IsFinite;(System.Half);generated | | System;Half;IsInfinity;(System.Half);generated | @@ -39460,25 +40062,56 @@ neutral | System;Half;IsNegativeInfinity;(System.Half);generated | | System;Half;IsNormal;(System.Half);generated | | System;Half;IsPositiveInfinity;(System.Half);generated | +| System;Half;IsPow2;(System.Half);generated | | System;Half;IsSubnormal;(System.Half);generated | +| System;Half;Log2;(System.Half);generated | +| System;Half;Log10;(System.Half);generated | +| System;Half;Log;(System.Half);generated | +| System;Half;Log;(System.Half,System.Half);generated | +| System;Half;Max;(System.Half,System.Half);generated | +| System;Half;MaxMagnitude;(System.Half,System.Half);generated | +| System;Half;Min;(System.Half,System.Half);generated | +| System;Half;MinMagnitude;(System.Half,System.Half);generated | | System;Half;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Half;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Half;Parse;(System.String);generated | | System;Half;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Half;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Half;Parse;(System.String,System.IFormatProvider);generated | +| System;Half;Pow;(System.Half,System.Half);generated | +| System;Half;Round;(System.Half);generated | +| System;Half;Round;(System.Half,System.MidpointRounding);generated | +| System;Half;Sign;(System.Half);generated | +| System;Half;Sin;(System.Half);generated | +| System;Half;Sinh;(System.Half);generated | +| System;Half;Sqrt;(System.Half);generated | +| System;Half;Tan;(System.Half);generated | +| System;Half;Tanh;(System.Half);generated | | System;Half;ToString;();generated | | System;Half;ToString;(System.String);generated | +| System;Half;Truncate;(System.Half);generated | | System;Half;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Half;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Half);generated | | System;Half;TryParse;(System.ReadOnlySpan,System.Half);generated | +| System;Half;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Half);generated | | System;Half;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Half);generated | | System;Half;TryParse;(System.String,System.Half);generated | +| System;Half;TryParse;(System.String,System.IFormatProvider,System.Half);generated | +| System;Half;get_AdditiveIdentity;();generated | +| System;Half;get_E;();generated | | System;Half;get_Epsilon;();generated | | System;Half;get_MaxValue;();generated | | System;Half;get_MinValue;();generated | +| System;Half;get_MultiplicativeIdentity;();generated | | System;Half;get_NaN;();generated | | System;Half;get_NegativeInfinity;();generated | +| System;Half;get_NegativeOne;();generated | +| System;Half;get_NegativeZero;();generated | +| System;Half;get_One;();generated | +| System;Half;get_Pi;();generated | | System;Half;get_PositiveInfinity;();generated | +| System;Half;get_Tau;();generated | +| System;Half;get_Zero;();generated | | System;HashCode;Add<>;(T);generated | | System;HashCode;Add<>;(T,System.Collections.Generic.IEqualityComparer);generated | | System;HashCode;AddBytes;(System.ReadOnlySpan);generated | @@ -39552,17 +40185,32 @@ neutral | System;InsufficientMemoryException;InsufficientMemoryException;();generated | | System;InsufficientMemoryException;InsufficientMemoryException;(System.String);generated | | System;InsufficientMemoryException;InsufficientMemoryException;(System.String,System.Exception);generated | +| System;Int16;Abs;(System.Int16);generated | +| System;Int16;Clamp;(System.Int16,System.Int16,System.Int16);generated | | System;Int16;CompareTo;(System.Int16);generated | | System;Int16;CompareTo;(System.Object);generated | +| System;Int16;CreateSaturating<>;(TOther);generated | +| System;Int16;CreateTruncating<>;(TOther);generated | +| System;Int16;DivRem;(System.Int16,System.Int16);generated | | System;Int16;Equals;(System.Int16);generated | | System;Int16;Equals;(System.Object);generated | | System;Int16;GetHashCode;();generated | | System;Int16;GetTypeCode;();generated | +| System;Int16;IsPow2;(System.Int16);generated | +| System;Int16;LeadingZeroCount;(System.Int16);generated | +| System;Int16;Log2;(System.Int16);generated | +| System;Int16;Max;(System.Int16,System.Int16);generated | +| System;Int16;Min;(System.Int16,System.Int16);generated | | System;Int16;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Int16;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Int16;Parse;(System.String);generated | | System;Int16;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Int16;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Int16;Parse;(System.String,System.IFormatProvider);generated | +| System;Int16;PopCount;(System.Int16);generated | +| System;Int16;RotateLeft;(System.Int16,System.Int32);generated | +| System;Int16;RotateRight;(System.Int16,System.Int32);generated | +| System;Int16;Sign;(System.Int16);generated | | System;Int16;ToBoolean;(System.IFormatProvider);generated | | System;Int16;ToByte;(System.IFormatProvider);generated | | System;Int16;ToChar;(System.IFormatProvider);generated | @@ -39582,17 +40230,42 @@ neutral | System;Int16;ToUInt16;(System.IFormatProvider);generated | | System;Int16;ToUInt32;(System.IFormatProvider);generated | | System;Int16;ToUInt64;(System.IFormatProvider);generated | +| System;Int16;TrailingZeroCount;(System.Int16);generated | | System;Int16;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Int16;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Int16);generated | +| System;Int16;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Int16);generated | | System;Int16;TryParse;(System.ReadOnlySpan,System.Int16);generated | | System;Int16;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int16);generated | +| System;Int16;TryParse;(System.String,System.IFormatProvider,System.Int16);generated | | System;Int16;TryParse;(System.String,System.Int16);generated | +| System;Int16;get_AdditiveIdentity;();generated | +| System;Int16;get_MaxValue;();generated | +| System;Int16;get_MinValue;();generated | +| System;Int16;get_MultiplicativeIdentity;();generated | +| System;Int16;get_NegativeOne;();generated | +| System;Int16;get_One;();generated | +| System;Int16;get_Zero;();generated | +| System;Int32;Abs;(System.Int32);generated | +| System;Int32;Clamp;(System.Int32,System.Int32,System.Int32);generated | | System;Int32;CompareTo;(System.Int32);generated | | System;Int32;CompareTo;(System.Object);generated | +| System;Int32;CreateSaturating<>;(TOther);generated | +| System;Int32;CreateTruncating<>;(TOther);generated | +| System;Int32;DivRem;(System.Int32,System.Int32);generated | | System;Int32;Equals;(System.Int32);generated | | System;Int32;Equals;(System.Object);generated | | System;Int32;GetHashCode;();generated | | System;Int32;GetTypeCode;();generated | +| System;Int32;IsPow2;(System.Int32);generated | +| System;Int32;LeadingZeroCount;(System.Int32);generated | +| System;Int32;Log2;(System.Int32);generated | +| System;Int32;Max;(System.Int32,System.Int32);generated | +| System;Int32;Min;(System.Int32,System.Int32);generated | +| System;Int32;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | +| System;Int32;PopCount;(System.Int32);generated | +| System;Int32;RotateLeft;(System.Int32,System.Int32);generated | +| System;Int32;RotateRight;(System.Int32,System.Int32);generated | +| System;Int32;Sign;(System.Int32);generated | | System;Int32;ToBoolean;(System.IFormatProvider);generated | | System;Int32;ToByte;(System.IFormatProvider);generated | | System;Int32;ToChar;(System.IFormatProvider);generated | @@ -39612,18 +40285,43 @@ neutral | System;Int32;ToUInt16;(System.IFormatProvider);generated | | System;Int32;ToUInt32;(System.IFormatProvider);generated | | System;Int32;ToUInt64;(System.IFormatProvider);generated | +| System;Int32;TrailingZeroCount;(System.Int32);generated | | System;Int32;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | +| System;Int32;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Int32);generated | +| System;Int32;TryParse;(System.String,System.IFormatProvider,System.Int32);generated | +| System;Int32;get_AdditiveIdentity;();generated | +| System;Int32;get_MaxValue;();generated | +| System;Int32;get_MinValue;();generated | +| System;Int32;get_MultiplicativeIdentity;();generated | +| System;Int32;get_NegativeOne;();generated | +| System;Int32;get_One;();generated | +| System;Int32;get_Zero;();generated | +| System;Int64;Abs;(System.Int64);generated | +| System;Int64;Clamp;(System.Int64,System.Int64,System.Int64);generated | | System;Int64;CompareTo;(System.Int64);generated | | System;Int64;CompareTo;(System.Object);generated | +| System;Int64;CreateSaturating<>;(TOther);generated | +| System;Int64;CreateTruncating<>;(TOther);generated | +| System;Int64;DivRem;(System.Int64,System.Int64);generated | | System;Int64;Equals;(System.Int64);generated | | System;Int64;Equals;(System.Object);generated | | System;Int64;GetHashCode;();generated | | System;Int64;GetTypeCode;();generated | +| System;Int64;IsPow2;(System.Int64);generated | +| System;Int64;LeadingZeroCount;(System.Int64);generated | +| System;Int64;Log2;(System.Int64);generated | +| System;Int64;Max;(System.Int64,System.Int64);generated | +| System;Int64;Min;(System.Int64,System.Int64);generated | | System;Int64;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Int64;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Int64;Parse;(System.String);generated | | System;Int64;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Int64;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Int64;Parse;(System.String,System.IFormatProvider);generated | +| System;Int64;PopCount;(System.Int64);generated | +| System;Int64;RotateLeft;(System.Int64,System.Int32);generated | +| System;Int64;RotateRight;(System.Int64,System.Int32);generated | +| System;Int64;Sign;(System.Int64);generated | | System;Int64;ToBoolean;(System.IFormatProvider);generated | | System;Int64;ToByte;(System.IFormatProvider);generated | | System;Int64;ToChar;(System.IFormatProvider);generated | @@ -39643,25 +40341,44 @@ neutral | System;Int64;ToUInt16;(System.IFormatProvider);generated | | System;Int64;ToUInt32;(System.IFormatProvider);generated | | System;Int64;ToUInt64;(System.IFormatProvider);generated | +| System;Int64;TrailingZeroCount;(System.Int64);generated | | System;Int64;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Int64;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Int64);generated | +| System;Int64;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Int64);generated | | System;Int64;TryParse;(System.ReadOnlySpan,System.Int64);generated | | System;Int64;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int64);generated | +| System;Int64;TryParse;(System.String,System.IFormatProvider,System.Int64);generated | | System;Int64;TryParse;(System.String,System.Int64);generated | +| System;Int64;get_AdditiveIdentity;();generated | +| System;Int64;get_MaxValue;();generated | +| System;Int64;get_MinValue;();generated | +| System;Int64;get_MultiplicativeIdentity;();generated | +| System;Int64;get_NegativeOne;();generated | +| System;Int64;get_One;();generated | +| System;Int64;get_Zero;();generated | | System;IntPtr;Add;(System.IntPtr,System.Int32);generated | | System;IntPtr;CompareTo;(System.IntPtr);generated | | System;IntPtr;CompareTo;(System.Object);generated | +| System;IntPtr;DivRem;(System.IntPtr,System.IntPtr);generated | | System;IntPtr;Equals;(System.IntPtr);generated | | System;IntPtr;Equals;(System.Object);generated | | System;IntPtr;GetHashCode;();generated | | System;IntPtr;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;IntPtr;IntPtr;(System.Int32);generated | | System;IntPtr;IntPtr;(System.Int64);generated | +| System;IntPtr;IsPow2;(System.IntPtr);generated | +| System;IntPtr;LeadingZeroCount;(System.IntPtr);generated | +| System;IntPtr;Log2;(System.IntPtr);generated | | System;IntPtr;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;IntPtr;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;IntPtr;Parse;(System.String);generated | | System;IntPtr;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;IntPtr;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;IntPtr;Parse;(System.String,System.IFormatProvider);generated | +| System;IntPtr;PopCount;(System.IntPtr);generated | +| System;IntPtr;RotateLeft;(System.IntPtr,System.Int32);generated | +| System;IntPtr;RotateRight;(System.IntPtr,System.Int32);generated | +| System;IntPtr;Sign;(System.IntPtr);generated | | System;IntPtr;Subtract;(System.IntPtr,System.Int32);generated | | System;IntPtr;ToInt32;();generated | | System;IntPtr;ToInt64;();generated | @@ -39669,14 +40386,22 @@ neutral | System;IntPtr;ToString;(System.IFormatProvider);generated | | System;IntPtr;ToString;(System.String);generated | | System;IntPtr;ToString;(System.String,System.IFormatProvider);generated | +| System;IntPtr;TrailingZeroCount;(System.IntPtr);generated | | System;IntPtr;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;IntPtr;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.IntPtr);generated | +| System;IntPtr;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.IntPtr);generated | | System;IntPtr;TryParse;(System.ReadOnlySpan,System.IntPtr);generated | | System;IntPtr;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.IntPtr);generated | +| System;IntPtr;TryParse;(System.String,System.IFormatProvider,System.IntPtr);generated | | System;IntPtr;TryParse;(System.String,System.IntPtr);generated | +| System;IntPtr;get_AdditiveIdentity;();generated | | System;IntPtr;get_MaxValue;();generated | | System;IntPtr;get_MinValue;();generated | +| System;IntPtr;get_MultiplicativeIdentity;();generated | +| System;IntPtr;get_NegativeOne;();generated | +| System;IntPtr;get_One;();generated | | System;IntPtr;get_Size;();generated | +| System;IntPtr;get_Zero;();generated | | System;InvalidCastException;InvalidCastException;();generated | | System;InvalidCastException;InvalidCastException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;InvalidCastException;InvalidCastException;(System.String);generated | @@ -40055,6 +40780,8 @@ neutral | System;Object;ToString;();generated | | System;ObjectDisposedException;ObjectDisposedException;(System.String);generated | | System;ObjectDisposedException;ObjectDisposedException;(System.String,System.Exception);generated | +| System;ObjectDisposedException;ThrowIf;(System.Boolean,System.Object);generated | +| System;ObjectDisposedException;ThrowIf;(System.Boolean,System.Type);generated | | System;ObsoleteAttribute;ObsoleteAttribute;();generated | | System;ObsoleteAttribute;ObsoleteAttribute;(System.String);generated | | System;ObsoleteAttribute;ObsoleteAttribute;(System.String,System.Boolean);generated | @@ -40183,17 +40910,32 @@ neutral | System;RuntimeTypeHandle;GetHashCode;();generated | | System;RuntimeTypeHandle;GetModuleHandle;();generated | | System;RuntimeTypeHandle;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | +| System;SByte;Abs;(System.SByte);generated | +| System;SByte;Clamp;(System.SByte,System.SByte,System.SByte);generated | | System;SByte;CompareTo;(System.Object);generated | | System;SByte;CompareTo;(System.SByte);generated | +| System;SByte;CreateSaturating<>;(TOther);generated | +| System;SByte;CreateTruncating<>;(TOther);generated | +| System;SByte;DivRem;(System.SByte,System.SByte);generated | | System;SByte;Equals;(System.Object);generated | | System;SByte;Equals;(System.SByte);generated | | System;SByte;GetHashCode;();generated | | System;SByte;GetTypeCode;();generated | +| System;SByte;IsPow2;(System.SByte);generated | +| System;SByte;LeadingZeroCount;(System.SByte);generated | +| System;SByte;Log2;(System.SByte);generated | +| System;SByte;Max;(System.SByte,System.SByte);generated | +| System;SByte;Min;(System.SByte,System.SByte);generated | | System;SByte;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;SByte;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;SByte;Parse;(System.String);generated | | System;SByte;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;SByte;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;SByte;Parse;(System.String,System.IFormatProvider);generated | +| System;SByte;PopCount;(System.SByte);generated | +| System;SByte;RotateLeft;(System.SByte,System.Int32);generated | +| System;SByte;RotateRight;(System.SByte,System.Int32);generated | +| System;SByte;Sign;(System.SByte);generated | | System;SByte;ToBoolean;(System.IFormatProvider);generated | | System;SByte;ToByte;(System.IFormatProvider);generated | | System;SByte;ToChar;(System.IFormatProvider);generated | @@ -40213,21 +40955,52 @@ neutral | System;SByte;ToUInt16;(System.IFormatProvider);generated | | System;SByte;ToUInt32;(System.IFormatProvider);generated | | System;SByte;ToUInt64;(System.IFormatProvider);generated | +| System;SByte;TrailingZeroCount;(System.SByte);generated | | System;SByte;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;SByte;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.SByte);generated | +| System;SByte;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.SByte);generated | | System;SByte;TryParse;(System.ReadOnlySpan,System.SByte);generated | | System;SByte;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.SByte);generated | +| System;SByte;TryParse;(System.String,System.IFormatProvider,System.SByte);generated | | System;SByte;TryParse;(System.String,System.SByte);generated | +| System;SByte;get_AdditiveIdentity;();generated | +| System;SByte;get_MaxValue;();generated | +| System;SByte;get_MinValue;();generated | +| System;SByte;get_MultiplicativeIdentity;();generated | +| System;SByte;get_NegativeOne;();generated | +| System;SByte;get_One;();generated | +| System;SByte;get_Zero;();generated | | System;STAThreadAttribute;STAThreadAttribute;();generated | | System;SequencePosition;Equals;(System.Object);generated | | System;SequencePosition;Equals;(System.SequencePosition);generated | | System;SequencePosition;GetHashCode;();generated | | System;SequencePosition;GetInteger;();generated | | System;SerializableAttribute;SerializableAttribute;();generated | +| System;Single;Abs;(System.Single);generated | +| System;Single;Acos;(System.Single);generated | +| System;Single;Acosh;(System.Single);generated | +| System;Single;Asin;(System.Single);generated | +| System;Single;Asinh;(System.Single);generated | +| System;Single;Atan2;(System.Single,System.Single);generated | +| System;Single;Atan;(System.Single);generated | +| System;Single;Atanh;(System.Single);generated | +| System;Single;BitDecrement;(System.Single);generated | +| System;Single;BitIncrement;(System.Single);generated | +| System;Single;Cbrt;(System.Single);generated | +| System;Single;Ceiling;(System.Single);generated | +| System;Single;Clamp;(System.Single,System.Single,System.Single);generated | | System;Single;CompareTo;(System.Object);generated | | System;Single;CompareTo;(System.Single);generated | +| System;Single;CopySign;(System.Single,System.Single);generated | +| System;Single;Cos;(System.Single);generated | +| System;Single;Cosh;(System.Single);generated | +| System;Single;CreateSaturating<>;(TOther);generated | +| System;Single;CreateTruncating<>;(TOther);generated | | System;Single;Equals;(System.Object);generated | | System;Single;Equals;(System.Single);generated | +| System;Single;Exp;(System.Single);generated | +| System;Single;Floor;(System.Single);generated | +| System;Single;FusedMultiplyAdd;(System.Single,System.Single,System.Single);generated | | System;Single;GetHashCode;();generated | | System;Single;GetTypeCode;();generated | | System;Single;IsFinite;(System.Single);generated | @@ -40237,12 +41010,31 @@ neutral | System;Single;IsNegativeInfinity;(System.Single);generated | | System;Single;IsNormal;(System.Single);generated | | System;Single;IsPositiveInfinity;(System.Single);generated | +| System;Single;IsPow2;(System.Single);generated | | System;Single;IsSubnormal;(System.Single);generated | +| System;Single;Log2;(System.Single);generated | +| System;Single;Log10;(System.Single);generated | +| System;Single;Log;(System.Single);generated | +| System;Single;Log;(System.Single,System.Single);generated | +| System;Single;Max;(System.Single,System.Single);generated | +| System;Single;MaxMagnitude;(System.Single,System.Single);generated | +| System;Single;Min;(System.Single,System.Single);generated | +| System;Single;MinMagnitude;(System.Single,System.Single);generated | | System;Single;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;Single;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;Single;Parse;(System.String);generated | | System;Single;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;Single;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;Single;Parse;(System.String,System.IFormatProvider);generated | +| System;Single;Pow;(System.Single,System.Single);generated | +| System;Single;Round;(System.Single);generated | +| System;Single;Round;(System.Single,System.MidpointRounding);generated | +| System;Single;Sign;(System.Single);generated | +| System;Single;Sin;(System.Single);generated | +| System;Single;Sinh;(System.Single);generated | +| System;Single;Sqrt;(System.Single);generated | +| System;Single;Tan;(System.Single);generated | +| System;Single;Tanh;(System.Single);generated | | System;Single;ToBoolean;(System.IFormatProvider);generated | | System;Single;ToByte;(System.IFormatProvider);generated | | System;Single;ToChar;(System.IFormatProvider);generated | @@ -40259,11 +41051,29 @@ neutral | System;Single;ToUInt16;(System.IFormatProvider);generated | | System;Single;ToUInt32;(System.IFormatProvider);generated | | System;Single;ToUInt64;(System.IFormatProvider);generated | +| System;Single;Truncate;(System.Single);generated | | System;Single;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;Single;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.Single);generated | +| System;Single;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Single);generated | | System;Single;TryParse;(System.ReadOnlySpan,System.Single);generated | | System;Single;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Single);generated | +| System;Single;TryParse;(System.String,System.IFormatProvider,System.Single);generated | | System;Single;TryParse;(System.String,System.Single);generated | +| System;Single;get_AdditiveIdentity;();generated | +| System;Single;get_E;();generated | +| System;Single;get_Epsilon;();generated | +| System;Single;get_MaxValue;();generated | +| System;Single;get_MinValue;();generated | +| System;Single;get_MultiplicativeIdentity;();generated | +| System;Single;get_NaN;();generated | +| System;Single;get_NegativeInfinity;();generated | +| System;Single;get_NegativeOne;();generated | +| System;Single;get_NegativeZero;();generated | +| System;Single;get_One;();generated | +| System;Single;get_Pi;();generated | +| System;Single;get_PositiveInfinity;();generated | +| System;Single;get_Tau;();generated | +| System;Single;get_Zero;();generated | | System;Span<>+Enumerator;MoveNext;();generated | | System;Span<>+Enumerator;get_Current;();generated | | System;Span<>;Clear;();generated | @@ -40422,8 +41232,10 @@ neutral | System;TimeOnly;FromTimeSpan;(System.TimeSpan);generated | | System;TimeOnly;GetHashCode;();generated | | System;TimeOnly;IsBetween;(System.TimeOnly,System.TimeOnly);generated | +| System;TimeOnly;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;TimeOnly;Parse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;TimeOnly;Parse;(System.String);generated | +| System;TimeOnly;Parse;(System.String,System.IFormatProvider);generated | | System;TimeOnly;Parse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;TimeOnly;ParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles);generated | | System;TimeOnly;ParseExact;(System.ReadOnlySpan,System.String[]);generated | @@ -40443,8 +41255,10 @@ neutral | System;TimeOnly;ToTimeSpan;();generated | | System;TimeOnly;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;TimeOnly;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.TimeOnly);generated | +| System;TimeOnly;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.TimeOnly);generated | | System;TimeOnly;TryParse;(System.ReadOnlySpan,System.TimeOnly);generated | | System;TimeOnly;TryParse;(System.String,System.IFormatProvider,System.Globalization.DateTimeStyles,System.TimeOnly);generated | +| System;TimeOnly;TryParse;(System.String,System.IFormatProvider,System.TimeOnly);generated | | System;TimeOnly;TryParse;(System.String,System.TimeOnly);generated | | System;TimeOnly;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.IFormatProvider,System.Globalization.DateTimeStyles,System.TimeOnly);generated | | System;TimeOnly;TryParseExact;(System.ReadOnlySpan,System.ReadOnlySpan,System.TimeOnly);generated | @@ -40791,17 +41605,32 @@ neutral | System;TypedReference;SetTypedReference;(System.TypedReference,System.Object);generated | | System;TypedReference;TargetTypeToken;(System.TypedReference);generated | | System;TypedReference;ToObject;(System.TypedReference);generated | +| System;UInt16;Abs;(System.UInt16);generated | +| System;UInt16;Clamp;(System.UInt16,System.UInt16,System.UInt16);generated | | System;UInt16;CompareTo;(System.Object);generated | | System;UInt16;CompareTo;(System.UInt16);generated | +| System;UInt16;CreateSaturating<>;(TOther);generated | +| System;UInt16;CreateTruncating<>;(TOther);generated | +| System;UInt16;DivRem;(System.UInt16,System.UInt16);generated | | System;UInt16;Equals;(System.Object);generated | | System;UInt16;Equals;(System.UInt16);generated | | System;UInt16;GetHashCode;();generated | | System;UInt16;GetTypeCode;();generated | +| System;UInt16;IsPow2;(System.UInt16);generated | +| System;UInt16;LeadingZeroCount;(System.UInt16);generated | +| System;UInt16;Log2;(System.UInt16);generated | +| System;UInt16;Max;(System.UInt16,System.UInt16);generated | +| System;UInt16;Min;(System.UInt16,System.UInt16);generated | | System;UInt16;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;UInt16;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt16;Parse;(System.String);generated | | System;UInt16;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;UInt16;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;UInt16;Parse;(System.String,System.IFormatProvider);generated | +| System;UInt16;PopCount;(System.UInt16);generated | +| System;UInt16;RotateLeft;(System.UInt16,System.Int32);generated | +| System;UInt16;RotateRight;(System.UInt16,System.Int32);generated | +| System;UInt16;Sign;(System.UInt16);generated | | System;UInt16;ToBoolean;(System.IFormatProvider);generated | | System;UInt16;ToByte;(System.IFormatProvider);generated | | System;UInt16;ToChar;(System.IFormatProvider);generated | @@ -40821,22 +41650,46 @@ neutral | System;UInt16;ToUInt16;(System.IFormatProvider);generated | | System;UInt16;ToUInt32;(System.IFormatProvider);generated | | System;UInt16;ToUInt64;(System.IFormatProvider);generated | +| System;UInt16;TrailingZeroCount;(System.UInt16);generated | | System;UInt16;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt16;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt16);generated | +| System;UInt16;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.UInt16);generated | | System;UInt16;TryParse;(System.ReadOnlySpan,System.UInt16);generated | | System;UInt16;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt16);generated | +| System;UInt16;TryParse;(System.String,System.IFormatProvider,System.UInt16);generated | | System;UInt16;TryParse;(System.String,System.UInt16);generated | +| System;UInt16;get_AdditiveIdentity;();generated | +| System;UInt16;get_MaxValue;();generated | +| System;UInt16;get_MinValue;();generated | +| System;UInt16;get_MultiplicativeIdentity;();generated | +| System;UInt16;get_One;();generated | +| System;UInt16;get_Zero;();generated | +| System;UInt32;Abs;(System.UInt32);generated | +| System;UInt32;Clamp;(System.UInt32,System.UInt32,System.UInt32);generated | | System;UInt32;CompareTo;(System.Object);generated | | System;UInt32;CompareTo;(System.UInt32);generated | +| System;UInt32;CreateSaturating<>;(TOther);generated | +| System;UInt32;CreateTruncating<>;(TOther);generated | +| System;UInt32;DivRem;(System.UInt32,System.UInt32);generated | | System;UInt32;Equals;(System.Object);generated | | System;UInt32;Equals;(System.UInt32);generated | | System;UInt32;GetHashCode;();generated | | System;UInt32;GetTypeCode;();generated | +| System;UInt32;IsPow2;(System.UInt32);generated | +| System;UInt32;LeadingZeroCount;(System.UInt32);generated | +| System;UInt32;Log2;(System.UInt32);generated | +| System;UInt32;Max;(System.UInt32,System.UInt32);generated | +| System;UInt32;Min;(System.UInt32,System.UInt32);generated | | System;UInt32;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;UInt32;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt32;Parse;(System.String);generated | | System;UInt32;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;UInt32;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;UInt32;Parse;(System.String,System.IFormatProvider);generated | +| System;UInt32;PopCount;(System.UInt32);generated | +| System;UInt32;RotateLeft;(System.UInt32,System.Int32);generated | +| System;UInt32;RotateRight;(System.UInt32,System.Int32);generated | +| System;UInt32;Sign;(System.UInt32);generated | | System;UInt32;ToBoolean;(System.IFormatProvider);generated | | System;UInt32;ToByte;(System.IFormatProvider);generated | | System;UInt32;ToChar;(System.IFormatProvider);generated | @@ -40856,22 +41709,46 @@ neutral | System;UInt32;ToUInt16;(System.IFormatProvider);generated | | System;UInt32;ToUInt32;(System.IFormatProvider);generated | | System;UInt32;ToUInt64;(System.IFormatProvider);generated | +| System;UInt32;TrailingZeroCount;(System.UInt32);generated | | System;UInt32;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt32;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt32);generated | +| System;UInt32;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.UInt32);generated | | System;UInt32;TryParse;(System.ReadOnlySpan,System.UInt32);generated | | System;UInt32;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt32);generated | +| System;UInt32;TryParse;(System.String,System.IFormatProvider,System.UInt32);generated | | System;UInt32;TryParse;(System.String,System.UInt32);generated | +| System;UInt32;get_AdditiveIdentity;();generated | +| System;UInt32;get_MaxValue;();generated | +| System;UInt32;get_MinValue;();generated | +| System;UInt32;get_MultiplicativeIdentity;();generated | +| System;UInt32;get_One;();generated | +| System;UInt32;get_Zero;();generated | +| System;UInt64;Abs;(System.UInt64);generated | +| System;UInt64;Clamp;(System.UInt64,System.UInt64,System.UInt64);generated | | System;UInt64;CompareTo;(System.Object);generated | | System;UInt64;CompareTo;(System.UInt64);generated | +| System;UInt64;CreateSaturating<>;(TOther);generated | +| System;UInt64;CreateTruncating<>;(TOther);generated | +| System;UInt64;DivRem;(System.UInt64,System.UInt64);generated | | System;UInt64;Equals;(System.Object);generated | | System;UInt64;Equals;(System.UInt64);generated | | System;UInt64;GetHashCode;();generated | | System;UInt64;GetTypeCode;();generated | +| System;UInt64;IsPow2;(System.UInt64);generated | +| System;UInt64;LeadingZeroCount;(System.UInt64);generated | +| System;UInt64;Log2;(System.UInt64);generated | +| System;UInt64;Max;(System.UInt64,System.UInt64);generated | +| System;UInt64;Min;(System.UInt64,System.UInt64);generated | | System;UInt64;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;UInt64;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt64;Parse;(System.String);generated | | System;UInt64;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;UInt64;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;UInt64;Parse;(System.String,System.IFormatProvider);generated | +| System;UInt64;PopCount;(System.UInt64);generated | +| System;UInt64;RotateLeft;(System.UInt64,System.Int32);generated | +| System;UInt64;RotateRight;(System.UInt64,System.Int32);generated | +| System;UInt64;Sign;(System.UInt64);generated | | System;UInt64;ToBoolean;(System.IFormatProvider);generated | | System;UInt64;ToByte;(System.IFormatProvider);generated | | System;UInt64;ToChar;(System.IFormatProvider);generated | @@ -40891,23 +41768,41 @@ neutral | System;UInt64;ToUInt16;(System.IFormatProvider);generated | | System;UInt64;ToUInt32;(System.IFormatProvider);generated | | System;UInt64;ToUInt64;(System.IFormatProvider);generated | +| System;UInt64;TrailingZeroCount;(System.UInt64);generated | | System;UInt64;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;UInt64;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt64);generated | +| System;UInt64;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.UInt64);generated | | System;UInt64;TryParse;(System.ReadOnlySpan,System.UInt64);generated | | System;UInt64;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UInt64);generated | +| System;UInt64;TryParse;(System.String,System.IFormatProvider,System.UInt64);generated | | System;UInt64;TryParse;(System.String,System.UInt64);generated | +| System;UInt64;get_AdditiveIdentity;();generated | +| System;UInt64;get_MaxValue;();generated | +| System;UInt64;get_MinValue;();generated | +| System;UInt64;get_MultiplicativeIdentity;();generated | +| System;UInt64;get_One;();generated | +| System;UInt64;get_Zero;();generated | | System;UIntPtr;Add;(System.UIntPtr,System.Int32);generated | | System;UIntPtr;CompareTo;(System.Object);generated | | System;UIntPtr;CompareTo;(System.UIntPtr);generated | +| System;UIntPtr;DivRem;(System.UIntPtr,System.UIntPtr);generated | | System;UIntPtr;Equals;(System.Object);generated | | System;UIntPtr;Equals;(System.UIntPtr);generated | | System;UIntPtr;GetHashCode;();generated | | System;UIntPtr;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | +| System;UIntPtr;IsPow2;(System.UIntPtr);generated | +| System;UIntPtr;LeadingZeroCount;(System.UIntPtr);generated | +| System;UIntPtr;Log2;(System.UIntPtr);generated | | System;UIntPtr;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);generated | +| System;UIntPtr;Parse;(System.ReadOnlySpan,System.IFormatProvider);generated | | System;UIntPtr;Parse;(System.String);generated | | System;UIntPtr;Parse;(System.String,System.Globalization.NumberStyles);generated | | System;UIntPtr;Parse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider);generated | | System;UIntPtr;Parse;(System.String,System.IFormatProvider);generated | +| System;UIntPtr;PopCount;(System.UIntPtr);generated | +| System;UIntPtr;RotateLeft;(System.UIntPtr,System.Int32);generated | +| System;UIntPtr;RotateRight;(System.UIntPtr,System.Int32);generated | +| System;UIntPtr;Sign;(System.UIntPtr);generated | | System;UIntPtr;Subtract;(System.UIntPtr,System.Int32);generated | | System;UIntPtr;ToString;();generated | | System;UIntPtr;ToString;(System.IFormatProvider);generated | @@ -40915,16 +41810,23 @@ neutral | System;UIntPtr;ToString;(System.String,System.IFormatProvider);generated | | System;UIntPtr;ToUInt32;();generated | | System;UIntPtr;ToUInt64;();generated | +| System;UIntPtr;TrailingZeroCount;(System.UIntPtr);generated | | System;UIntPtr;TryFormat;(System.Span,System.Int32,System.ReadOnlySpan,System.IFormatProvider);generated | | System;UIntPtr;TryParse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider,System.UIntPtr);generated | +| System;UIntPtr;TryParse;(System.ReadOnlySpan,System.IFormatProvider,System.UIntPtr);generated | | System;UIntPtr;TryParse;(System.ReadOnlySpan,System.UIntPtr);generated | | System;UIntPtr;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.UIntPtr);generated | +| System;UIntPtr;TryParse;(System.String,System.IFormatProvider,System.UIntPtr);generated | | System;UIntPtr;TryParse;(System.String,System.UIntPtr);generated | | System;UIntPtr;UIntPtr;(System.UInt32);generated | | System;UIntPtr;UIntPtr;(System.UInt64);generated | +| System;UIntPtr;get_AdditiveIdentity;();generated | | System;UIntPtr;get_MaxValue;();generated | | System;UIntPtr;get_MinValue;();generated | +| System;UIntPtr;get_MultiplicativeIdentity;();generated | +| System;UIntPtr;get_One;();generated | | System;UIntPtr;get_Size;();generated | +| System;UIntPtr;get_Zero;();generated | | System;UnauthorizedAccessException;UnauthorizedAccessException;();generated | | System;UnauthorizedAccessException;UnauthorizedAccessException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);generated | | System;UnauthorizedAccessException;UnauthorizedAccessException;(System.String);generated | diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql index eaf4d9d947f..69a03f32893 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.ql @@ -6,7 +6,8 @@ private class IncludeAllSummarizedCallable extends IncludeSummarizedCallable { IncludeAllSummarizedCallable() { exists(this) } } -private class IncludeNeutralCallable extends RelevantNeutralCallable instanceof FlowSummaryImpl::Public::NeutralCallable { +private class IncludeNeutralCallable extends RelevantNeutralCallable instanceof FlowSummaryImpl::Public::NeutralCallable +{ /** Gets a string representing the callable in semi-colon separated format for use in flow summaries. */ final override string getCallableCsv() { result = Csv::asPartialNeutralModel(this) } } diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected index 880a71ca5d0..9a9063ffba9 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected @@ -527,6 +527,7 @@ summary | System.Buffers;ReadOnlySequence<>;false;get_First;();;Argument[this];ReturnValue;taint;generated | | System.Buffers;ReadOnlySequence<>;false;get_Start;();;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;SequenceReader;(System.Buffers.ReadOnlySequence);;Argument[0];Argument[this];taint;generated | +| System.Buffers;SequenceReader<>;false;TryReadExact;(System.Int32,System.Buffers.ReadOnlySequence);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,System.ReadOnlySpan,System.Boolean);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,T,System.Boolean);;Argument[this];ReturnValue;taint;generated | | System.Buffers;SequenceReader<>;false;TryReadTo;(System.Buffers.ReadOnlySequence,T,T,System.Boolean);;Argument[this];ReturnValue;taint;generated | @@ -585,6 +586,8 @@ summary | System.Collections.Concurrent;Partitioner;false;Create<>;(System.Collections.Generic.IEnumerable,System.Collections.Concurrent.EnumerablePartitionerOptions);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Concurrent;Partitioner;false;Create<>;(System.Collections.Generic.IList,System.Boolean);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Concurrent;Partitioner;false;Create<>;(TSource[],System.Boolean);;Argument[0].Element;ReturnValue;taint;generated | +| System.Collections.Generic;CollectionExtensions;false;AsReadOnly<,>;(System.Collections.Generic.IDictionary);;Argument[0].Element;ReturnValue;taint;generated | +| System.Collections.Generic;CollectionExtensions;false;AsReadOnly<>;(System.Collections.Generic.IList);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[0].Element;ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[1];ReturnValue;taint;generated | | System.Collections.Generic;CollectionExtensions;false;GetValueOrDefault<,>;(System.Collections.Generic.IReadOnlyDictionary,TKey,TValue);;Argument[2];ReturnValue;taint;generated | @@ -752,6 +755,9 @@ summary | System.Collections.Generic;SortedList<,>;false;Add;(System.Collections.Generic.KeyValuePair);;Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual | | System.Collections.Generic;SortedList<,>;false;Add;(System.Collections.Generic.KeyValuePair);;Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual | | System.Collections.Generic;SortedList<,>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual | +| System.Collections.Generic;SortedList<,>;false;GetKeyAtIndex;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Collections.Generic;SortedList<,>;false;GetValueAtIndex;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Collections.Generic;SortedList<,>;false;SetValueAtIndex;(System.Int32,TValue);;Argument[1];Argument[this];taint;generated | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IComparer);;Argument[0];Argument[this];taint;generated | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IDictionary);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual | | System.Collections.Generic;SortedList<,>;false;SortedList;(System.Collections.Generic.IDictionary);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual | @@ -4591,6 +4597,9 @@ summary | System.Net.NetworkInformation;MulticastIPAddressInformationCollection;false;get_Item;(System.Int32);;Argument[this];ReturnValue;taint;generated | | System.Net.NetworkInformation;PhysicalAddress;false;PhysicalAddress;(System.Byte[]);;Argument[0].Element;Argument[this];taint;generated | | System.Net.NetworkInformation;UnicastIPAddressInformationCollection;false;get_Item;(System.Int32);;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_LocalEndPoint;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_NegotiatedApplicationProtocol;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Quic;QuicConnection;false;get_RemoteEndPoint;();;Argument[this];ReturnValue;taint;generated | | System.Net.Security;AuthenticatedStream;false;AuthenticatedStream;(System.IO.Stream,System.Boolean);;Argument[0];Argument[this];taint;generated | | System.Net.Security;AuthenticatedStream;false;DisposeAsync;();;Argument[this];ReturnValue;taint;generated | | System.Net.Security;AuthenticatedStream;false;get_InnerStream;();;Argument[this];ReturnValue;taint;generated | @@ -4677,6 +4686,9 @@ summary | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveAsync;(System.Memory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[4];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[4];ReturnValue;taint;generated | @@ -4690,7 +4702,12 @@ summary | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -4700,7 +4717,12 @@ summary | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Byte[],System.Int32,System.Int32,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[4];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFrom;(System.Span,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Net.Sockets.IPPacketInformation);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[0];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;ReceiveMessageFromAsync;(System.Memory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -4709,6 +4731,8 @@ summary | System.Net.Sockets;Socket;false;SendAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | | System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendAsync;(System.ReadOnlyMemory,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.ReadOnlyMemory,System.ReadOnlyMemory,System.Net.Sockets.TransmitFileOptions,System.Threading.CancellationToken);;Argument[4];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.ReadOnlyMemory,System.ReadOnlyMemory,System.Net.Sockets.TransmitFileOptions,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendFileAsync;(System.String,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | @@ -4720,9 +4744,14 @@ summary | System.Net.Sockets;Socket;false;SendTo;(System.Byte[],System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendTo;(System.ReadOnlySpan,System.Net.EndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendTo;(System.ReadOnlySpan,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ArraySegment,System.Net.EndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ArraySegment,System.Net.Sockets.SocketFlags,System.Net.EndPoint);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[0];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.Net.Sockets.SocketAsyncEventArgs);;Argument[this];Argument[0];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];Argument[this];taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[1];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | +| System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];Argument[this];taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[2];ReturnValue;taint;generated | | System.Net.Sockets;Socket;false;SendToAsync;(System.ReadOnlyMemory,System.Net.Sockets.SocketFlags,System.Net.EndPoint,System.Threading.CancellationToken);;Argument[3];ReturnValue;taint;generated | @@ -4803,6 +4832,7 @@ summary | System.Net.Sockets;UdpReceiveResult;false;UdpReceiveResult;(System.Byte[],System.Net.IPEndPoint);;Argument[1];Argument[this];taint;generated | | System.Net.Sockets;UdpReceiveResult;false;get_Buffer;();;Argument[this];ReturnValue;taint;generated | | System.Net.Sockets;UdpReceiveResult;false;get_RemoteEndPoint;();;Argument[this];ReturnValue;taint;generated | +| System.Net.Sockets;UnixDomainSocketEndPoint;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;SetBuffer;(System.Int32,System.Int32,System.ArraySegment);;Argument[2].Element;Argument[this];taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;get_Cookies;();;Argument[this];ReturnValue;taint;generated | | System.Net.WebSockets;ClientWebSocketOptions;false;get_Credentials;();;Argument[this];ReturnValue;taint;generated | @@ -6011,10 +6041,13 @@ summary | System.Runtime.InteropServices;SequenceMarshal;false;TryGetArray<>;(System.Buffers.ReadOnlySequence,System.ArraySegment);;Argument[0];ReturnValue;taint;generated | | System.Runtime.InteropServices;SequenceMarshal;false;TryGetReadOnlyMemory<>;(System.Buffers.ReadOnlySequence,System.ReadOnlyMemory);;Argument[0];ReturnValue;taint;generated | | System.Runtime.InteropServices;SequenceMarshal;false;TryGetReadOnlySequenceSegment<>;(System.Buffers.ReadOnlySequence,System.Buffers.ReadOnlySequenceSegment,System.Int32,System.Buffers.ReadOnlySequenceSegment,System.Int32);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector64;false;Abs<>;(System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector64;false;WithElement<>;(System.Runtime.Intrinsics.Vector64,System.Int32,T);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector128;false;Abs<>;(System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithElement<>;(System.Runtime.Intrinsics.Vector128,System.Int32,T);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithLower<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector128;false;WithUpper<>;(System.Runtime.Intrinsics.Vector128,System.Runtime.Intrinsics.Vector64);;Argument[0];ReturnValue;taint;generated | +| System.Runtime.Intrinsics;Vector256;false;Abs<>;(System.Runtime.Intrinsics.Vector256);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithElement<>;(System.Runtime.Intrinsics.Vector256,System.Int32,T);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithLower<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | | System.Runtime.Intrinsics;Vector256;false;WithUpper<>;(System.Runtime.Intrinsics.Vector256,System.Runtime.Intrinsics.Vector128);;Argument[0];ReturnValue;taint;generated | @@ -7037,6 +7070,14 @@ summary | System.Text;StringBuilder;false;ToString;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue;taint;manual | | System.Text;StringRuneEnumerator;false;GetEnumerator;();;Argument[this];ReturnValue;value;generated | | System.Text;StringRuneEnumerator;false;get_Current;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;ConcurrencyLimiter;false;ConcurrencyLimiter;(System.Threading.RateLimiting.ConcurrencyLimiterOptions);;Argument[0];Argument[this];taint;generated | +| System.Threading.RateLimiting;MetadataName;false;Create<>;(System.String);;Argument[0];ReturnValue;taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;MetadataName;(System.String);;Argument[0];Argument[this];taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;ToString;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;MetadataName<>;false;get_Name;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;RateLimitLease;false;TryGetMetadata<>;(System.Threading.RateLimiting.MetadataName,T);;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;RateLimitLease;true;GetAllMetadata;();;Argument[this];ReturnValue;taint;generated | +| System.Threading.RateLimiting;TokenBucketRateLimiter;false;TokenBucketRateLimiter;(System.Threading.RateLimiting.TokenBucketRateLimiterOptions);;Argument[0];Argument[this];taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;BatchBlock;(System.Int32,System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions);;Argument[1];Argument[this];taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;LinkTo;(System.Threading.Tasks.Dataflow.ITargetBlock,System.Threading.Tasks.Dataflow.DataflowLinkOptions);;Argument[0];ReturnValue;taint;generated | | System.Threading.Tasks.Dataflow;BatchBlock<>;false;LinkTo;(System.Threading.Tasks.Dataflow.ITargetBlock,System.Threading.Tasks.Dataflow.DataflowLinkOptions);;Argument[this];ReturnValue;taint;generated | @@ -9390,6 +9431,8 @@ summary | System;FormattableString;false;Invariant;(System.FormattableString);;Argument[0];ReturnValue;taint;generated | | System;FormattableString;false;ToString;();;Argument[this];ReturnValue;taint;generated | | System;FormattableString;false;ToString;(System.String,System.IFormatProvider);;Argument[this];ReturnValue;taint;generated | +| System;Half;false;BitDecrement;(System.Half);;Argument[0];ReturnValue;taint;generated | +| System;Half;false;BitIncrement;(System.Half);;Argument[0];ReturnValue;taint;generated | | System;Half;false;ToString;(System.IFormatProvider);;Argument[0];ReturnValue;taint;generated | | System;Half;false;ToString;(System.String,System.IFormatProvider);;Argument[1];ReturnValue;taint;generated | | System;Int32;false;Parse;(System.ReadOnlySpan,System.Globalization.NumberStyles,System.IFormatProvider);;Argument[0].Element;ReturnValue;taint;manual | @@ -9405,7 +9448,17 @@ summary | System;Int32;false;TryParse;(System.String,System.Globalization.NumberStyles,System.IFormatProvider,System.Int32);;Argument[0];ReturnValue;taint;manual | | System;Int32;false;TryParse;(System.String,System.Int32);;Argument[0];Argument[1];taint;manual | | System;Int32;false;TryParse;(System.String,System.Int32);;Argument[0];ReturnValue;taint;manual | +| System;IntPtr;false;Abs;(System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | +| System;IntPtr;false;Clamp;(System.IntPtr,System.IntPtr,System.IntPtr);;Argument[2];ReturnValue;taint;generated | +| System;IntPtr;false;CreateSaturating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;CreateTruncating<>;(TOther);;Argument[0];ReturnValue;taint;generated | | System;IntPtr;false;IntPtr;(System.Void*);;Argument[0];Argument[this];taint;generated | +| System;IntPtr;false;Max;(System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Max;(System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | +| System;IntPtr;false;Min;(System.IntPtr,System.IntPtr);;Argument[0];ReturnValue;taint;generated | +| System;IntPtr;false;Min;(System.IntPtr,System.IntPtr);;Argument[1];ReturnValue;taint;generated | | System;IntPtr;false;ToPointer;();;Argument[this];ReturnValue;taint;generated | | System;Lazy<,>;false;Lazy;(TMetadata);;Argument[0];Argument[this];taint;generated | | System;Lazy<,>;false;Lazy;(TMetadata,System.Boolean);;Argument[0];Argument[this];taint;generated | @@ -10079,6 +10132,16 @@ summary | System;TypeLoadException;false;TypeLoadException;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[0];Argument[this];taint;generated | | System;TypeLoadException;false;get_Message;();;Argument[this];ReturnValue;taint;generated | | System;TypeLoadException;false;get_TypeName;();;Argument[this];ReturnValue;taint;generated | +| System;UIntPtr;false;Abs;(System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | +| System;UIntPtr;false;Clamp;(System.UIntPtr,System.UIntPtr,System.UIntPtr);;Argument[2];ReturnValue;taint;generated | +| System;UIntPtr;false;CreateSaturating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;CreateTruncating<>;(TOther);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Max;(System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Max;(System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | +| System;UIntPtr;false;Min;(System.UIntPtr,System.UIntPtr);;Argument[0];ReturnValue;taint;generated | +| System;UIntPtr;false;Min;(System.UIntPtr,System.UIntPtr);;Argument[1];ReturnValue;taint;generated | | System;UIntPtr;false;ToPointer;();;Argument[this];ReturnValue;taint;generated | | System;UIntPtr;false;UIntPtr;(System.Void*);;Argument[0];Argument[this];taint;generated | | System;UnhandledExceptionEventArgs;false;UnhandledExceptionEventArgs;(System.Object,System.Boolean);;Argument[0];Argument[this];taint;generated | diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.ql b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.ql index 82cf263ec9c..c1e093a1f42 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.ql +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.ql @@ -2,7 +2,8 @@ import shared.FlowSummaries private import semmle.code.csharp.dataflow.internal.DataFlowPrivate::Csv private import semmle.code.csharp.dataflow.ExternalFlow -class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable instanceof SummarizedCallable { +class IncludeFilteredSummarizedCallable extends IncludeSummarizedCallable instanceof SummarizedCallable +{ /** * Holds if flow is propagated between `input` and `output` and * if there is no summary for a callable in a `base` class or interface diff --git a/csharp/ql/test/library-tests/dispatch/CallContext.expected b/csharp/ql/test/library-tests/dispatch/CallContext.expected index 9b02bf012df..d51ec513829 100644 --- a/csharp/ql/test/library-tests/dispatch/CallContext.expected +++ b/csharp/ql/test/library-tests/dispatch/CallContext.expected @@ -23,3 +23,6 @@ mayBenefitFromCallContext | ViableCallable.cs:411:9:411:18 | call to method M | | ViableCallable.cs:455:9:455:30 | call to method M2 | | ViableCallable.cs:461:9:461:30 | call to method M2 | +| ViableCallable.cs:563:18:563:22 | call to operator / | +| ViableCallable.cs:566:26:566:30 | call to operator checked / | +| ViableCallable.cs:572:9:572:15 | call to method M12 | diff --git a/csharp/ql/test/library-tests/dispatch/CallGraph.expected b/csharp/ql/test/library-tests/dispatch/CallGraph.expected index 0e52045cbdf..ec3f7f6167d 100644 --- a/csharp/ql/test/library-tests/dispatch/CallGraph.expected +++ b/csharp/ql/test/library-tests/dispatch/CallGraph.expected @@ -242,3 +242,17 @@ | ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:488:40:488:40 | checked + | | ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:489:28:489:35 | explicit conversion | | ViableCallable.cs:492:10:492:12 | Run | ViableCallable.cs:490:28:490:35 | checked explicit conversion | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:514:39:514:39 | checked - | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:516:31:516:31 | * | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:517:39:517:39 | checked * | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:519:31:519:31 | / | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:520:39:520:39 | checked / | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:524:18:524:20 | M12 | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:526:18:526:20 | M13 | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:531:32:531:32 | + | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:532:40:532:40 | checked + | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:534:32:534:32 | - | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:536:32:536:32 | / | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:537:40:537:40 | checked / | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:539:17:539:19 | M11 | +| ViableCallable.cs:542:10:542:15 | Run<> | ViableCallable.cs:540:17:540:19 | M12 | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index 074deaf9dff..490dd3201f3 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -475,3 +475,17 @@ | ViableCallable.cs:498:26:498:30 | call to operator checked + | C19.checked +(C19, C19) | | ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | C19.explicit conversion(C19) | | ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | C19.checked explicit conversion(C19) | +| ViableCallable.cs:545:18:545:22 | call to operator + | C20.+(C20, C20) | +| ViableCallable.cs:548:26:548:30 | call to operator checked + | C20.checked +(C20, C20) | +| ViableCallable.cs:551:18:551:22 | call to operator - | C20.-(C20, C20) | +| ViableCallable.cs:554:26:554:30 | call to operator checked - | I3.checked -(T, T) | +| ViableCallable.cs:557:18:557:22 | call to operator * | I3.*(T, T) | +| ViableCallable.cs:560:26:560:30 | call to operator checked * | I3.checked *(T, T) | +| ViableCallable.cs:563:18:563:22 | call to operator / | C20./(C20, C20) | +| ViableCallable.cs:563:18:563:22 | call to operator / | I3./(T, T) | +| ViableCallable.cs:566:26:566:30 | call to operator checked / | C20.checked /(C20, C20) | +| ViableCallable.cs:566:26:566:30 | call to operator checked / | I3.checked /(T, T) | +| ViableCallable.cs:569:9:569:15 | call to method M11 | C20.M11() | +| ViableCallable.cs:572:9:572:15 | call to method M12 | C20.M12() | +| ViableCallable.cs:572:9:572:15 | call to method M12 | I3.M12() | +| ViableCallable.cs:575:9:575:15 | call to method M13 | I3.M13() | diff --git a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs index 6345bb3510e..0f21421bbd9 100644 --- a/csharp/ql/test/library-tests/dispatch/ViableCallable.cs +++ b/csharp/ql/test/library-tests/dispatch/ViableCallable.cs @@ -503,4 +503,75 @@ class C19 // Viable callables: C19.op_CheckedExplicit() var n2 = checked((int)c); } -} \ No newline at end of file +} + +public interface I3 where T : I3 +{ + static abstract T operator +(T x, T y); + static abstract T operator checked +(T x, T y); + + static abstract T operator -(T x, T y); + static virtual T operator checked -(T x, T y) => throw null; + + static virtual T operator *(T x, T y) => throw null; + static virtual T operator checked *(T x, T y) => throw null; + + static virtual T operator /(T x, T y) => throw null; + static virtual T operator checked /(T x, T y) => throw null; + + void M11(); + + virtual void M12() => throw null; + + virtual void M13() => throw null; +} + +public class C20 : I3 +{ + public static C20 operator +(C20 x, C20 y) => throw null; + public static C20 operator checked +(C20 x, C20 y) => throw null; + + public static C20 operator -(C20 x, C20 y) => throw null; + + public static C20 operator /(C20 x, C20 y) => throw null; + public static C20 operator checked /(C20 x, C20 y) => throw null; + + public void M11() { } + public void M12() { } + + void Run(T c) where T : I3 + { + // Viable callables: C20.op_Addition() + var c1 = c + c; + + // Viable callables: C20.op_CheckedAddition() + var c2 = checked(c + c); + + // Viable callables: C20.op_Subtraction() + var c3 = c - c; + + // Viable callables: I3.op_CheckedSubtraction(). + var c4 = checked(c - c); + + // Viable callables: I3.op_Multiply(). + var c5 = c * c; + + // Viable callables: I3.op_CheckedMultiply(). + var c6 = checked(c * c); + + // Viable callables: {C20,I3}.op_Division() + var c7 = c / c; + + // Viable callables: {C20,I3}.op_CheckedDivision() + var c8 = checked(c / c); + + // Viable callables: C20.M11. + c.M11(); + + // Viable callables: {C20,I3}.M12(). + c.M12(); + + // Viable callables: I3.M13() + c.M13(); + } +} diff --git a/csharp/ql/test/library-tests/dispatch/viableCallable.expected b/csharp/ql/test/library-tests/dispatch/viableCallable.expected index d752fb824da..78027a2cdad 100644 --- a/csharp/ql/test/library-tests/dispatch/viableCallable.expected +++ b/csharp/ql/test/library-tests/dispatch/viableCallable.expected @@ -272,3 +272,17 @@ | ViableCallable.cs:498:26:498:30 | call to operator checked + | checked + | C19 | | ViableCallable.cs:501:18:501:23 | call to operator explicit conversion | explicit conversion | C19 | | ViableCallable.cs:504:26:504:31 | call to operator checked explicit conversion | checked explicit conversion | C19 | +| ViableCallable.cs:545:18:545:22 | call to operator + | + | C20 | +| ViableCallable.cs:548:26:548:30 | call to operator checked + | checked + | C20 | +| ViableCallable.cs:551:18:551:22 | call to operator - | - | C20 | +| ViableCallable.cs:554:26:554:30 | call to operator checked - | checked - | I3<> | +| ViableCallable.cs:557:18:557:22 | call to operator * | * | I3<> | +| ViableCallable.cs:560:26:560:30 | call to operator checked * | checked * | I3<> | +| ViableCallable.cs:563:18:563:22 | call to operator / | / | C20 | +| ViableCallable.cs:563:18:563:22 | call to operator / | / | I3<> | +| ViableCallable.cs:566:26:566:30 | call to operator checked / | checked / | C20 | +| ViableCallable.cs:566:26:566:30 | call to operator checked / | checked / | I3<> | +| ViableCallable.cs:569:9:569:15 | call to method M11 | M11 | C20 | +| ViableCallable.cs:572:9:572:15 | call to method M12 | M12 | C20 | +| ViableCallable.cs:572:9:572:15 | call to method M12 | M12 | I3<> | +| ViableCallable.cs:575:9:575:15 | call to method M13 | M13 | I3<> | diff --git a/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.ql b/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.ql index 00873833083..75faad9d633 100644 --- a/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.ql +++ b/csharp/ql/test/library-tests/frameworks/EntityFramework/FlowSummaries.ql @@ -2,8 +2,8 @@ import semmle.code.csharp.frameworks.EntityFramework::EntityFramework import shared.FlowSummaries import semmle.code.csharp.dataflow.ExternalFlow as ExternalFlow -private class IncludeEFSummarizedCallable extends IncludeSummarizedCallable instanceof EFSummarizedCallable { -} +private class IncludeEFSummarizedCallable extends IncludeSummarizedCallable instanceof EFSummarizedCallable +{ } query predicate sourceNode(DataFlow::Node node, string kind) { ExternalFlow::sourceNode(node, kind) diff --git a/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected b/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected index 2cef6a86400..0fd2ca78088 100644 --- a/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected +++ b/csharp/ql/test/query-tests/Stubs/All/AllStubs.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n\nnamespace A1\n{\n// Generated from `A1.C1` in `Test.cs:185:18:185:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C1\n{\n}\n\n}\nnamespace A2\n{\nnamespace B2\n{\n// Generated from `A2.B2.C2` in `Test.cs:192:22:192:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C2\n{\n}\n\n}\n}\nnamespace A3\n{\n// Generated from `A3.C3` in `Test.cs:198:18:198:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C3\n{\n}\n\n}\nnamespace A4\n{\n// Generated from `A4.C4` in `Test.cs:208:18:208:19; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class C4\n{\n}\n\nnamespace B4\n{\n// Generated from `A4.B4.D4` in `Test.cs:205:22:205:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class D4\n{\n}\n\n}\n}\nnamespace Test\n{\n// Generated from `Test.Class1` in `Test.cs:5:18:5:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class1\n{\n// Generated from `Test.Class1+Class11` in `Test.cs:34:22:34:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class11 : Test.Class1.Interface1, Test.Class1.Interface2\n{\n int Test.Class1.Interface2.this[int i] { get => throw null; }\n public void Method1() => throw null;\n void Test.Class1.Interface2.Method2() => throw null;\n}\n\n\n// Generated from `Test.Class1+Class12` in `Test.cs:51:22:51:28; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class12 : Test.Class1.Class11\n{\n}\n\n\n// Generated from `Test.Class1+Class13` in `Test.cs:63:31:63:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class13\n{\n protected internal virtual void M() => throw null;\n public virtual void M1() where T: Test.Class1.Class13 => throw null;\n public abstract void M2();\n}\n\n\n// Generated from `Test.Class1+Class14` in `Test.cs:70:31:70:37; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class Class14 : Test.Class1.Class13\n{\n protected internal override void M() => throw null;\n public override void M1() => throw null;\n public abstract override void M2();\n}\n\n\n// Generated from `Test.Class1+Delegate1<>` in `Test.cs:47:30:47:41; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic delegate void Delegate1(T i, int j);\n\n\n// Generated from `Test.Class1+GenericType<>` in `Test.cs:56:22:56:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class GenericType\n{\n// Generated from `Test.Class1+GenericType<>+X` in `Test.cs:58:26:58:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class X\n{\n}\n\n\n}\n\n\n// Generated from `Test.Class1+Interface1` in `Test.cs:18:26:18:35; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface Interface1\n{\n void Method1();\n}\n\n\n// Generated from `Test.Class1+Interface2` in `Test.cs:23:38:23:47; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\nprotected internal interface Interface2\n{\n int this[int i] { get; }\n void Method2();\n}\n\n\n// Generated from `Test.Class1+Struct1` in `Test.cs:7:23:7:29; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic struct Struct1\n{\n public void Method(Test.Class1.Struct1 s = default(Test.Class1.Struct1)) => throw null;\n public int i;\n public static int j = default;\n public System.ValueTuple t1;\n public (int,int) t2;\n}\n\n\n public event Test.Class1.Delegate1 Event1;\n public Test.Class1.GenericType.X Prop { get => throw null; }\n}\n\n// Generated from `Test.Class10` in `Test.cs:138:18:138:24; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class10\n{\n unsafe public void M1(delegate* unmanaged f) => throw null;\n}\n\n// Generated from `Test.Class3` in `Test.cs:84:18:84:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class3\n{\n public object Item { get => throw null; set => throw null; }\n [System.Runtime.CompilerServices.IndexerName("MyItem")]\n public object this[string index] { get => throw null; set => throw null; }\n}\n\n// Generated from `Test.Class4` in `Test.cs:91:18:91:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class4\n{\n unsafe public void M(int* p) => throw null;\n}\n\n// Generated from `Test.Class5` in `Test.cs:102:18:102:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class5 : Test.IInterface1\n{\n public void M2() => throw null;\n}\n\n// Generated from `Test.Class6<>` in `Test.cs:107:18:107:26; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class6 where T: class, Test.IInterface1\n{\n public virtual void M1() where T: class, Test.IInterface1, new() => throw null;\n}\n\n// Generated from `Test.Class7` in `Test.cs:114:18:114:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class7 : Test.Class6\n{\n public override void M1() where T: class => throw null;\n}\n\n// Generated from `Test.Class8` in `Test.cs:121:18:121:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class8\n{\n public static int @this = default;\n}\n\n// Generated from `Test.Class9` in `Test.cs:126:18:126:23; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Class9\n{\n// Generated from `Test.Class9+Nested` in `Test.cs:130:22:130:27; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Nested : Test.Class9\n{\n}\n\n\n public Test.Class9.Nested NestedInstance { get => throw null; }\n}\n\n// Generated from `Test.Enum1` in `Test.cs:143:17:143:21; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic enum Enum1 : int\n{\n None1 = 0,\n Some11 = 1,\n Some12 = 2,\n}\n\n// Generated from `Test.Enum2` in `Test.cs:150:17:150:21; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic enum Enum2 : int\n{\n None2 = 2,\n Some21 = 1,\n Some22 = 3,\n}\n\n// Generated from `Test.Enum3` in `Test.cs:157:17:157:21; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic enum Enum3 : int\n{\n None3 = 2,\n Some31 = 1,\n Some32 = 0,\n}\n\n// Generated from `Test.Enum4` in `Test.cs:164:17:164:21; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic enum Enum4 : int\n{\n None4 = 2,\n Some41 = 7,\n Some42 = 6,\n}\n\n// Generated from `Test.EnumLong` in `Test.cs:171:17:171:24; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic enum EnumLong : long\n{\n None = 10,\n Some = 223372036854775807,\n}\n\n// Generated from `Test.IInterface1` in `Test.cs:96:22:96:32; Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IInterface1\n{\n void M1() => throw null;\n void M2();\n}\n\n}\n\n\n | +| // This file contains auto-generated code.\n// Generated from `Test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`.\n\nnamespace A1\n{\npublic class C1\n{\n}\n\n}\nnamespace A2\n{\nnamespace B2\n{\npublic class C2\n{\n}\n\n}\n}\nnamespace A3\n{\npublic class C3\n{\n}\n\n}\nnamespace A4\n{\npublic class C4\n{\n}\n\nnamespace B4\n{\npublic class D4\n{\n}\n\n}\n}\nnamespace Test\n{\npublic class Class1\n{\npublic class Class11 : Test.Class1.Interface1, Test.Class1.Interface2\n{\n int Test.Class1.Interface2.this[int i] { get => throw null; }\n public void Method1() => throw null;\n void Test.Class1.Interface2.Method2() => throw null;\n}\n\n\npublic class Class12 : Test.Class1.Class11\n{\n}\n\n\npublic abstract class Class13\n{\n protected internal virtual void M() => throw null;\n public virtual void M1() where T: Test.Class1.Class13 => throw null;\n public abstract void M2();\n}\n\n\npublic abstract class Class14 : Test.Class1.Class13\n{\n protected internal override void M() => throw null;\n public override void M1() => throw null;\n public abstract override void M2();\n}\n\n\npublic delegate void Delegate1(T i, int j);\n\n\npublic class GenericType\n{\npublic class X\n{\n}\n\n\n}\n\n\npublic interface Interface1\n{\n void Method1();\n}\n\n\nprotected internal interface Interface2\n{\n int this[int i] { get; }\n void Method2();\n}\n\n\npublic struct Struct1\n{\n public void Method(Test.Class1.Struct1 s = default(Test.Class1.Struct1)) => throw null;\n public int i;\n public static int j = default;\n public System.ValueTuple t1;\n public (int,int) t2;\n}\n\n\n public event Test.Class1.Delegate1 Event1;\n public Test.Class1.GenericType.X Prop { get => throw null; }\n}\n\npublic class Class10\n{\n unsafe public void M1(delegate* unmanaged f) => throw null;\n}\n\npublic class Class11 : Test.IInterface2, Test.IInterface3\n{\n static Test.Class11 Test.IInterface2.operator *(Test.Class11 left, Test.Class11 right) => throw null;\n public static Test.Class11 operator +(Test.Class11 left, Test.Class11 right) => throw null;\n public static Test.Class11 operator -(Test.Class11 left, Test.Class11 right) => throw null;\n static Test.Class11 Test.IInterface2.operator /(Test.Class11 left, Test.Class11 right) => throw null;\n public void M1() => throw null;\n void Test.IInterface2.M2() => throw null;\n public static explicit operator System.Int16(Test.Class11 n) => throw null;\n static explicit Test.IInterface2.operator int(Test.Class11 n) => throw null;\n}\n\npublic class Class3\n{\n public object Item { get => throw null; set => throw null; }\n [System.Runtime.CompilerServices.IndexerName("MyItem")]\n public object this[string index] { get => throw null; set => throw null; }\n}\n\npublic class Class4\n{\n unsafe public void M(int* p) => throw null;\n}\n\npublic class Class5 : Test.IInterface1\n{\n public void M2() => throw null;\n}\n\npublic class Class6 where T: class, Test.IInterface1\n{\n public virtual void M1() where T: class, Test.IInterface1, new() => throw null;\n}\n\npublic class Class7 : Test.Class6\n{\n public override void M1() where T: class => throw null;\n}\n\npublic class Class8\n{\n public static int @this = default;\n}\n\npublic class Class9\n{\npublic class Nested : Test.Class9\n{\n}\n\n\n public Test.Class9.Nested NestedInstance { get => throw null; }\n}\n\npublic enum Enum1 : int\n{\n None1 = 0,\n Some11 = 1,\n Some12 = 2,\n}\n\npublic enum Enum2 : int\n{\n None2 = 2,\n Some21 = 1,\n Some22 = 3,\n}\n\npublic enum Enum3 : int\n{\n None3 = 2,\n Some31 = 1,\n Some32 = 0,\n}\n\npublic enum Enum4 : int\n{\n None4 = 2,\n Some41 = 7,\n Some42 = 6,\n}\n\npublic enum EnumLong : long\n{\n None = 10,\n Some = 223372036854775807,\n}\n\npublic interface IInterface1\n{\n void M1() => throw null;\n void M2();\n}\n\npublic interface IInterface2 where T: Test.IInterface2\n{\n static abstract T operator *(T left, T right);\n static abstract T operator +(T left, T right);\n static virtual T operator -(T left, T right) => throw null;\n static virtual T operator /(T left, T right) => throw null;\n void M1();\n void M2();\n static abstract explicit operator System.Int16(T n);\n static abstract explicit operator int(T n);\n}\n\npublic interface IInterface3 where T: Test.IInterface3\n{\n static abstract T operator +(T left, T right);\n static virtual T operator -(T left, T right) => throw null;\n void M1();\n static abstract explicit operator System.Int16(T n);\n}\n\nunsafe public class MyUnsafeClass\n{\n unsafe public static void M1(delegate* f) => throw null;\n unsafe public static void M2(int*[] x) => throw null;\n unsafe public static System.Char* M3() => throw null;\n public static void M4(int x) => throw null;\n}\n\n}\n\n\n | diff --git a/csharp/ql/test/query-tests/Stubs/All/Test.cs b/csharp/ql/test/query-tests/Stubs/All/Test.cs index 2b46b8ec987..7e3f96bb000 100644 --- a/csharp/ql/test/query-tests/Stubs/All/Test.cs +++ b/csharp/ql/test/query-tests/Stubs/All/Test.cs @@ -140,6 +140,46 @@ namespace Test unsafe public void M1(delegate* unmanaged f) => throw null; } + public interface IInterface2 where T : IInterface2 + { + static abstract T operator +(T left, T right); + static virtual T operator -(T left, T right) => throw null; + static abstract T operator *(T left, T right); + static virtual T operator /(T left, T right) => throw null; + static abstract explicit operator short(T n); + static abstract explicit operator int(T n); + void M1(); + void M2(); + } + + public interface IInterface3 where T : IInterface3 + { + static abstract T operator +(T left, T right); + static virtual T operator -(T left, T right) => throw null; + static abstract explicit operator short(T n); + void M1(); + } + + public class Class11 : IInterface2, IInterface3 + { + public static Class11 operator +(Class11 left, Class11 right) => throw null; + public static Class11 operator -(Class11 left, Class11 right) => throw null; + static Class11 IInterface2.operator *(Class11 left, Class11 right) => throw null; + static Class11 IInterface2.operator /(Class11 left, Class11 right) => throw null; + public void M1() => throw null; + void IInterface2.M2() => throw null; + public static explicit operator short(Class11 n) => 0; + static explicit IInterface2.operator int(Class11 n) => 0; + } + + public unsafe class MyUnsafeClass + { + public static void M1(delegate* f) => throw null; + public static void M2(int*[] x) => throw null; + public static char* M3() => throw null; + public static void M4(int x) => throw null; + } + public enum Enum1 { None1, diff --git a/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected b/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected index ca740f0a899..629addbb336 100644 --- a/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected +++ b/csharp/ql/test/query-tests/Stubs/Minimal/MinimalStubsFromSource.expected @@ -1 +1 @@ -| // This file contains auto-generated code.\n\nnamespace System\n{\n// Generated from `System.Uri` in `System.Private.Uri, Version=7.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 void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n public override string ToString() => throw null;\n}\n\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\n// Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class SortedList : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ICloneable\n{\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual object Clone() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual int Count { get => throw null; }\n public virtual object GetByIndex(int index) => throw null;\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => 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 object this[object key] { get => throw null; set => throw null; }\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual void Remove(object key) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Generic\n{\n// Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Stack : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n public int Count { 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.ICollection.IsSynchronized { get => throw null; }\n public T Peek() => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Specialized\n{\n// Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic abstract class NameObjectCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n public virtual int Count { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public virtual void OnDeserialization(object sender) => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n// Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=7.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}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=7.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=7.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=7.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.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\n// Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverter\n{\n}\n\n}\nnamespace Timers\n{\n// Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n internal TimersDescriptionAttribute(string description, string unused) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace ComponentModel\n{\n// Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class TypeConverterAttribute : System.Attribute\n{\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n public TypeConverterAttribute() => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n}\n\n// Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=7.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}\nnamespace Windows\n{\nnamespace Markup\n{\n// Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=7.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\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Enumerable` in `System.Linq, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static 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}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n}\nnamespace Runtime\n{\nnamespace CompilerServices\n{\n// Generated from `System.Runtime.CompilerServices.CallSite` in `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CallSite\n{\n internal CallSite(System.Runtime.CompilerServices.CallSiteBinder binder) => throw null;\n}\n\n// Generated from `System.Runtime.CompilerServices.CallSite<>` in `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class CallSite : System.Runtime.CompilerServices.CallSite where T: class\n{\n private CallSite() : base(default(System.Runtime.CompilerServices.CallSiteBinder)) => throw null;\n private CallSite(System.Runtime.CompilerServices.CallSiteBinder binder) : base(default(System.Runtime.CompilerServices.CallSiteBinder)) => throw null;\n}\n\n// Generated from `System.Runtime.CompilerServices.CallSiteBinder` in `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic abstract class CallSiteBinder\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static 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=7.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 internal ParallelQuery(System.Linq.Parallel.QuerySettings specifiedSettings) => throw null;\n}\n\nnamespace Parallel\n{\n// Generated from `System.Linq.Parallel.QuerySettings` in `System.Linq.Parallel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\ninternal struct QuerySettings\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Linq\n{\n// Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic static class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Runtime\n{\nnamespace Serialization\n{\n// Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=7.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=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Text\n{\nnamespace RegularExpressions\n{\n// Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Capture\n{\n internal Capture(string text, int index, int length) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.GeneratedRegexAttribute` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class GeneratedRegexAttribute : System.Attribute\n{\n public GeneratedRegexAttribute(string pattern) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds, string cultureName) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, string cultureName) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Group : System.Text.RegularExpressions.Capture\n{\n internal Group(string text, int[] caps, int capcount, string name) : base(default(string), default(int), default(int)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Match : System.Text.RegularExpressions.Group\n{\n internal Match(System.Text.RegularExpressions.Regex regex, int capcount, string text, int textLength) : base(default(string), default(int[]), default(int), default(string)) => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => 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 Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n public override string ToString() => throw null;\n}\n\n// Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`\n[System.Flags]\npublic enum RegexOptions : int\n{\n IgnoreCase = 1,\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n\nnamespace System\n{\nnamespace Web\n{\n// Generated from `System.Web.HtmlString` in `../../../resources/stubs/System.Web.cs:34:18:34:27; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HtmlString : System.Web.IHtmlString\n{\n}\n\n// Generated from `System.Web.HttpContextBase` in `../../../resources/stubs/System.Web.cs:24:18:24:32; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpContextBase\n{\n public virtual System.Web.HttpRequestBase Request { get => throw null; }\n}\n\n// Generated from `System.Web.HttpCookie` in `../../../resources/stubs/System.Web.cs:174:18:174:27; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpCookie\n{\n}\n\n// Generated from `System.Web.HttpCookieCollection` in `../../../resources/stubs/System.Web.cs:192:27:192:46; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class HttpCookieCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n}\n\n// Generated from `System.Web.HttpRequest` in `../../../resources/stubs/System.Web.cs:145:18:145:28; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpRequest\n{\n}\n\n// Generated from `System.Web.HttpRequestBase` in `../../../resources/stubs/System.Web.cs:10:18:10:32; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpRequestBase\n{\n public virtual System.Collections.Specialized.NameValueCollection QueryString { get => throw null; }\n}\n\n// Generated from `System.Web.HttpResponse` in `../../../resources/stubs/System.Web.cs:156:18:156:29; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpResponse\n{\n}\n\n// Generated from `System.Web.HttpResponseBase` in `../../../resources/stubs/System.Web.cs:19:18:19:33; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpResponseBase\n{\n}\n\n// Generated from `System.Web.HttpServerUtility` in `../../../resources/stubs/System.Web.cs:41:18:41:34; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpServerUtility\n{\n}\n\n// Generated from `System.Web.IHtmlString` in `../../../resources/stubs/System.Web.cs:30:22:30:32; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IHtmlString\n{\n}\n\n// Generated from `System.Web.IHttpHandler` in `../../../resources/stubs/System.Web.cs:132:22:132:33; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IHttpHandler\n{\n}\n\n// Generated from `System.Web.IServiceProvider` in `../../../resources/stubs/System.Web.cs:136:22:136:37; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IServiceProvider\n{\n}\n\n// Generated from `System.Web.UnvalidatedRequestValues` in `../../../resources/stubs/System.Web.cs:140:18:140:41; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class UnvalidatedRequestValues\n{\n}\n\n// Generated from `System.Web.UnvalidatedRequestValuesBase` in `../../../resources/stubs/System.Web.cs:5:18:5:45; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class UnvalidatedRequestValuesBase\n{\n}\n\nnamespace Mvc\n{\n// Generated from `System.Web.Mvc.ActionMethodSelectorAttribute` in `../../../resources/stubs/System.Web.cs:241:18:241:46; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ActionMethodSelectorAttribute : System.Attribute\n{\n}\n\n// Generated from `System.Web.Mvc.ActionResult` in `../../../resources/stubs/System.Web.cs:233:18:233:29; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ActionResult\n{\n}\n\n// Generated from `System.Web.Mvc.ControllerContext` in `../../../resources/stubs/System.Web.cs:211:18:211:34; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ControllerContext\n{\n}\n\n// Generated from `System.Web.Mvc.FilterAttribute` in `../../../resources/stubs/System.Web.cs:237:18:237:32; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class FilterAttribute : System.Attribute\n{\n}\n\n// Generated from `System.Web.Mvc.GlobalFilterCollection` in `../../../resources/stubs/System.Web.cs:281:18:281:39; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class GlobalFilterCollection\n{\n}\n\n// Generated from `System.Web.Mvc.IFilterProvider` in `../../../resources/stubs/System.Web.cs:277:15:277:29; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\ninternal interface IFilterProvider\n{\n}\n\n// Generated from `System.Web.Mvc.IViewDataContainer` in `../../../resources/stubs/System.Web.cs:219:22:219:39; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic interface IViewDataContainer\n{\n}\n\n// Generated from `System.Web.Mvc.ViewContext` in `../../../resources/stubs/System.Web.cs:215:18:215:28; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ViewContext : System.Web.Mvc.ControllerContext\n{\n}\n\n// Generated from `System.Web.Mvc.ViewResult` in `../../../resources/stubs/System.Web.cs:273:18:273:27; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ViewResult : System.Web.Mvc.ViewResultBase\n{\n}\n\n// Generated from `System.Web.Mvc.ViewResultBase` in `../../../resources/stubs/System.Web.cs:269:18:269:31; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class ViewResultBase : System.Web.Mvc.ActionResult\n{\n}\n\n}\nnamespace Routing\n{\n// Generated from `System.Web.Routing.RequestContext` in `../../../resources/stubs/System.Web.cs:300:18:300:31; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class RequestContext\n{\n}\n\n}\nnamespace Script\n{\nnamespace Serialization\n{\n// Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `../../../resources/stubs/System.Web.cs:365:27:365:48; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic abstract class JavaScriptTypeResolver\n{\n}\n\n}\n}\nnamespace Security\n{\n// Generated from `System.Web.Security.MembershipUser` in `../../../resources/stubs/System.Web.cs:323:18:323:31; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class MembershipUser\n{\n}\n\n}\nnamespace SessionState\n{\n// Generated from `System.Web.SessionState.HttpSessionState` in `../../../resources/stubs/System.Web.cs:201:18:201:33; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class HttpSessionState\n{\n}\n\n}\nnamespace UI\n{\n// Generated from `System.Web.UI.Control` in `../../../resources/stubs/System.Web.cs:76:18:76:24; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class Control\n{\n}\n\nnamespace WebControls\n{\n// Generated from `System.Web.UI.WebControls.WebControl` in `../../../resources/stubs/System.Web.cs:104:18:104:27; System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`\npublic class WebControl : System.Web.UI.Control\n{\n}\n\n}\n}\n}\n}\n\n\n | +| // This file contains auto-generated code.\n// Generated from `System.Collections, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Generic\n{\npublic class Stack : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int arrayIndex) => throw null;\n public int Count { 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.ICollection.IsSynchronized { get => throw null; }\n public T Peek() => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Collections.NonGeneric, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Collections\n{\npublic class SortedList : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ICloneable\n{\n public virtual void Add(object key, object value) => throw null;\n public virtual void Clear() => throw null;\n public virtual object Clone() => throw null;\n public virtual bool Contains(object key) => throw null;\n public virtual void CopyTo(System.Array array, int arrayIndex) => throw null;\n public virtual int Count { get => throw null; }\n public virtual object GetByIndex(int index) => throw null;\n public virtual System.Collections.IDictionaryEnumerator GetEnumerator() => throw null;\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => 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 object this[object key] { get => throw null; set => throw null; }\n public virtual System.Collections.ICollection Keys { get => throw null; }\n public virtual void Remove(object key) => throw null;\n public virtual object SyncRoot { get => throw null; }\n public virtual System.Collections.ICollection Values { get => throw null; }\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Collections.Specialized, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Collections\n{\nnamespace Specialized\n{\npublic abstract class NameObjectCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable\n{\n void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;\n public virtual int Count { get => throw null; }\n public virtual System.Collections.IEnumerator GetEnumerator() => throw null;\n public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null;\n bool System.Collections.ICollection.IsSynchronized { get => throw null; }\n public virtual void OnDeserialization(object sender) => throw null;\n object System.Collections.ICollection.SyncRoot { get => throw null; }\n}\n\npublic class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n public string this[string name] { get => throw null; set => throw null; }\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.ComponentModel.TypeConverter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace ComponentModel\n{\npublic class ComponentConverter : System.ComponentModel.ReferenceConverter\n{\n}\n\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\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\npublic class ReferenceConverter : System.ComponentModel.TypeConverter\n{\n}\n\npublic class TypeConverter\n{\n}\n\n}\nnamespace Timers\n{\npublic class TimersDescriptionAttribute\n{\n public TimersDescriptionAttribute(string description) => throw null;\n internal TimersDescriptionAttribute(string description, string unused) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Linq, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Linq\n{\npublic static 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}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Linq\n{\npublic interface IQueryable : System.Collections.IEnumerable\n{\n}\n\n}\nnamespace Runtime\n{\nnamespace CompilerServices\n{\npublic class CallSite\n{\n internal CallSite(System.Runtime.CompilerServices.CallSiteBinder binder) => throw null;\n}\n\npublic class CallSite : System.Runtime.CompilerServices.CallSite where T: class\n{\n private CallSite() : base(default(System.Runtime.CompilerServices.CallSiteBinder)) => throw null;\n private CallSite(System.Runtime.CompilerServices.CallSiteBinder binder) : base(default(System.Runtime.CompilerServices.CallSiteBinder)) => throw null;\n}\n\npublic abstract class CallSiteBinder\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Linq.Parallel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Linq\n{\npublic static class ParallelEnumerable\n{\n public static System.Linq.ParallelQuery AsParallel(this System.Collections.IEnumerable source) => throw null;\n}\n\npublic class ParallelQuery : System.Collections.IEnumerable\n{\n System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;\n internal ParallelQuery(System.Linq.Parallel.QuerySettings specifiedSettings) => throw null;\n}\n\nnamespace Parallel\n{\ninternal struct QuerySettings\n{\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Linq.Queryable, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Linq\n{\npublic static class Queryable\n{\n public static System.Linq.IQueryable AsQueryable(this System.Collections.IEnumerable source) => throw null;\n}\n\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.ObjectModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace ComponentModel\n{\npublic class TypeConverterAttribute : System.Attribute\n{\n public override bool Equals(object obj) => throw null;\n public override int GetHashCode() => throw null;\n public TypeConverterAttribute() => throw null;\n public TypeConverterAttribute(System.Type type) => throw null;\n public TypeConverterAttribute(string typeName) => throw null;\n}\n\npublic class TypeDescriptionProviderAttribute : System.Attribute\n{\n public TypeDescriptionProviderAttribute(System.Type type) => throw null;\n public TypeDescriptionProviderAttribute(string typeName) => throw null;\n}\n\n}\nnamespace Windows\n{\nnamespace Markup\n{\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\n\n// This file contains auto-generated code.\n// Generated from `System.Private.Uri, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\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 void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null;\n public override string ToString() => throw null;\n}\n\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Runtime.Serialization.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Runtime\n{\nnamespace Serialization\n{\npublic class DataContractAttribute : System.Attribute\n{\n public DataContractAttribute() => throw null;\n}\n\npublic class DataMemberAttribute : System.Attribute\n{\n public DataMemberAttribute() => throw null;\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`.\n\nnamespace System\n{\nnamespace Text\n{\nnamespace RegularExpressions\n{\npublic class Capture\n{\n internal Capture(string text, int index, int length) => throw null;\n public override string ToString() => throw null;\n}\n\npublic class GeneratedRegexAttribute : System.Attribute\n{\n public GeneratedRegexAttribute(string pattern) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds, string cultureName) => throw null;\n public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, string cultureName) => throw null;\n}\n\npublic class Group : System.Text.RegularExpressions.Capture\n{\n internal Group(string text, int[] caps, int capcount, string name) : base(default(string), default(int), default(int)) => throw null;\n}\n\npublic class Match : System.Text.RegularExpressions.Group\n{\n internal Match(System.Text.RegularExpressions.Regex regex, int capcount, string text, int textLength) : base(default(string), default(int[]), default(int), default(string)) => throw null;\n}\n\npublic class Regex : System.Runtime.Serialization.ISerializable\n{\n void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo si, System.Runtime.Serialization.StreamingContext context) => throw null;\n public System.Text.RegularExpressions.Match Match(string input) => 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 Regex(string pattern) => throw null;\n public Regex(string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null;\n public string Replace(string input, string replacement) => throw null;\n public override string ToString() => throw null;\n}\n\n[System.Flags]\npublic enum RegexOptions : int\n{\n IgnoreCase = 1,\n}\n\n}\n}\n}\n\n\n// This file contains auto-generated code.\n// Generated from `System.Web, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null`.\n\nnamespace System\n{\nnamespace Web\n{\npublic class HtmlString : System.Web.IHtmlString\n{\n}\n\npublic class HttpContextBase\n{\n public virtual System.Web.HttpRequestBase Request { get => throw null; }\n}\n\npublic class HttpCookie\n{\n}\n\npublic abstract class HttpCookieCollection : System.Collections.Specialized.NameObjectCollectionBase\n{\n}\n\npublic class HttpRequest\n{\n}\n\npublic class HttpRequestBase\n{\n public virtual System.Collections.Specialized.NameValueCollection QueryString { get => throw null; }\n}\n\npublic class HttpResponse\n{\n}\n\npublic class HttpResponseBase\n{\n}\n\npublic class HttpServerUtility\n{\n}\n\npublic interface IHtmlString\n{\n}\n\npublic interface IHttpHandler\n{\n}\n\npublic interface IServiceProvider\n{\n}\n\npublic class UnvalidatedRequestValues\n{\n}\n\npublic class UnvalidatedRequestValuesBase\n{\n}\n\nnamespace Mvc\n{\npublic class ActionMethodSelectorAttribute : System.Attribute\n{\n}\n\npublic class ActionResult\n{\n}\n\npublic class ControllerContext\n{\n}\n\npublic class FilterAttribute : System.Attribute\n{\n}\n\npublic class GlobalFilterCollection\n{\n}\n\ninternal interface IFilterProvider\n{\n}\n\npublic interface IViewDataContainer\n{\n}\n\npublic class ViewContext : System.Web.Mvc.ControllerContext\n{\n}\n\npublic class ViewResult : System.Web.Mvc.ViewResultBase\n{\n}\n\npublic class ViewResultBase : System.Web.Mvc.ActionResult\n{\n}\n\n}\nnamespace Routing\n{\npublic class RequestContext\n{\n}\n\n}\nnamespace Script\n{\nnamespace Serialization\n{\npublic abstract class JavaScriptTypeResolver\n{\n}\n\n}\n}\nnamespace Security\n{\npublic class MembershipUser\n{\n}\n\n}\nnamespace SessionState\n{\npublic class HttpSessionState\n{\n}\n\n}\nnamespace UI\n{\npublic class Control\n{\n}\n\nnamespace WebControls\n{\npublic class WebControl : System.Web.UI.Control\n{\n}\n\n}\n}\n}\n}\n\n\n | diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Antiforgery.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Antiforgery.cs index 39644a441bb..bce42e8da38 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Antiforgery.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Antiforgery.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Antiforgery, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Antiforgery { - // Generated from `Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AntiforgeryOptions { public AntiforgeryOptions() => throw null; @@ -17,7 +17,6 @@ namespace Microsoft public bool SuppressXFrameOptionsHeader { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Antiforgery.AntiforgeryTokenSet` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AntiforgeryTokenSet { public AntiforgeryTokenSet(string requestToken, string cookieToken, string formFieldName, string headerName) => throw null; @@ -27,14 +26,12 @@ namespace Microsoft public string RequestToken { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AntiforgeryValidationException : System.Exception { public AntiforgeryValidationException(string message) => throw null; public AntiforgeryValidationException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.Antiforgery.IAntiforgery` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAntiforgery { Microsoft.AspNetCore.Antiforgery.AntiforgeryTokenSet GetAndStoreTokens(Microsoft.AspNetCore.Http.HttpContext httpContext); @@ -44,7 +41,6 @@ namespace Microsoft System.Threading.Tasks.Task ValidateRequestAsync(Microsoft.AspNetCore.Http.HttpContext httpContext); } - // Generated from `Microsoft.AspNetCore.Antiforgery.IAntiforgeryAdditionalDataProvider` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAntiforgeryAdditionalDataProvider { string GetAdditionalData(Microsoft.AspNetCore.Http.HttpContext context); @@ -57,7 +53,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.AntiforgeryServiceCollectionExtensions` in `Microsoft.AspNetCore.Antiforgery, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AntiforgeryServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAntiforgery(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs index bdbbf375422..e36260275d5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authentication.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Authentication { - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticateResult` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticateResult { protected AuthenticateResult() => throw null; @@ -25,7 +25,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.AuthenticationTicket Ticket { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationHttpContextExtensions` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthenticationHttpContextExtensions { public static System.Threading.Tasks.Task AuthenticateAsync(this Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -50,7 +49,6 @@ namespace Microsoft public static System.Threading.Tasks.Task SignOutAsync(this Microsoft.AspNetCore.Http.HttpContext context, string scheme, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationOptions` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationOptions { public void AddScheme(string name, System.Action configureBuilder) => throw null; @@ -67,7 +65,6 @@ namespace Microsoft public System.Collections.Generic.IEnumerable Schemes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationProperties` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationProperties { public bool? AllowRefresh { get => throw null; set => throw null; } @@ -91,7 +88,6 @@ namespace Microsoft public void SetString(string key, string value) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationScheme` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationScheme { public AuthenticationScheme(string name, string displayName, System.Type handlerType) => throw null; @@ -100,7 +96,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationSchemeBuilder` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationSchemeBuilder { public AuthenticationSchemeBuilder(string name) => throw null; @@ -110,7 +105,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationTicket` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationTicket { public string AuthenticationScheme { get => throw null; } @@ -121,7 +115,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationToken` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationToken { public AuthenticationToken() => throw null; @@ -129,7 +122,6 @@ namespace Microsoft public string Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationTokenExtensions` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthenticationTokenExtensions { public static System.Threading.Tasks.Task GetTokenAsync(this Microsoft.AspNetCore.Authentication.IAuthenticationService auth, Microsoft.AspNetCore.Http.HttpContext context, string tokenName) => throw null; @@ -140,20 +132,22 @@ namespace Microsoft public static bool UpdateTokenValue(this Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, string tokenName, string tokenValue) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticateResultFeature` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticateResultFeature { Microsoft.AspNetCore.Authentication.AuthenticateResult AuthenticateResult { get; set; } } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationFeature` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IAuthenticationConfigurationProvider + { + Microsoft.Extensions.Configuration.IConfiguration AuthenticationConfiguration { get; } + } + public interface IAuthenticationFeature { Microsoft.AspNetCore.Http.PathString OriginalPath { get; set; } Microsoft.AspNetCore.Http.PathString OriginalPathBase { get; set; } } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationHandler` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationHandler { System.Threading.Tasks.Task AuthenticateAsync(); @@ -162,19 +156,16 @@ namespace Microsoft System.Threading.Tasks.Task InitializeAsync(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Http.HttpContext context); } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationHandlerProvider { System.Threading.Tasks.Task GetHandlerAsync(Microsoft.AspNetCore.Http.HttpContext context, string authenticationScheme); } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationRequestHandler` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationRequestHandler : Microsoft.AspNetCore.Authentication.IAuthenticationHandler { System.Threading.Tasks.Task HandleRequestAsync(); } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationSchemeProvider { void AddScheme(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme); @@ -190,7 +181,6 @@ namespace Microsoft bool TryAddScheme(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationService` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationService { System.Threading.Tasks.Task AuthenticateAsync(Microsoft.AspNetCore.Http.HttpContext context, string scheme); @@ -200,19 +190,16 @@ namespace Microsoft System.Threading.Tasks.Task SignOutAsync(Microsoft.AspNetCore.Http.HttpContext context, string scheme, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties); } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationSignInHandler` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationSignInHandler : Microsoft.AspNetCore.Authentication.IAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationSignOutHandler { System.Threading.Tasks.Task SignInAsync(System.Security.Claims.ClaimsPrincipal user, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties); } - // Generated from `Microsoft.AspNetCore.Authentication.IAuthenticationSignOutHandler` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticationSignOutHandler : Microsoft.AspNetCore.Authentication.IAuthenticationHandler { System.Threading.Tasks.Task SignOutAsync(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties); } - // Generated from `Microsoft.AspNetCore.Authentication.IClaimsTransformation` in `Microsoft.AspNetCore.Authentication.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClaimsTransformation { System.Threading.Tasks.Task TransformAsync(System.Security.Claims.ClaimsPrincipal principal); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Cookies.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Cookies.cs index b033adfed56..d2df2b11c4f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Cookies.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Cookies.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authentication.Cookies, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Cookies { - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.ChunkingCookieManager` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ChunkingCookieManager : Microsoft.AspNetCore.Authentication.Cookies.ICookieManager { public void AppendResponseCookie(Microsoft.AspNetCore.Http.HttpContext context, string key, string value, Microsoft.AspNetCore.Http.CookieOptions options) => throw null; @@ -20,7 +20,6 @@ namespace Microsoft public bool ThrowForPartialCookies { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationDefaults` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CookieAuthenticationDefaults { public static Microsoft.AspNetCore.Http.PathString AccessDeniedPath; @@ -31,9 +30,9 @@ namespace Microsoft public static string ReturnUrlParameter; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieAuthenticationEvents { + public virtual System.Threading.Tasks.Task CheckSlidingExpiration(Microsoft.AspNetCore.Authentication.Cookies.CookieSlidingExpirationContext context) => throw null; public CookieAuthenticationEvents() => throw null; public System.Func OnCheckSlidingExpiration { get => throw null; set => throw null; } public System.Func, System.Threading.Tasks.Task> OnRedirectToAccessDenied { get => throw null; set => throw null; } @@ -54,7 +53,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidatePrincipal(Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationHandler` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieAuthenticationHandler : Microsoft.AspNetCore.Authentication.SignInAuthenticationHandler { public CookieAuthenticationHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.Authentication.ISystemClock clock) : base(default(Microsoft.Extensions.Options.IOptionsMonitor), default(Microsoft.Extensions.Logging.ILoggerFactory), default(System.Text.Encodings.Web.UrlEncoder), default(Microsoft.AspNetCore.Authentication.ISystemClock)) => throw null; @@ -69,7 +67,6 @@ namespace Microsoft protected override System.Threading.Tasks.Task InitializeHandlerAsync() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public Microsoft.AspNetCore.Http.PathString AccessDeniedPath { get => throw null; set => throw null; } @@ -87,27 +84,23 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.ISecureDataFormat TicketDataFormat { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieSignedInContext` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieSignedInContext : Microsoft.AspNetCore.Authentication.PrincipalContext { public CookieSignedInContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieSigningInContext` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieSigningInContext : Microsoft.AspNetCore.Authentication.PrincipalContext { public Microsoft.AspNetCore.Http.CookieOptions CookieOptions { get => throw null; set => throw null; } public CookieSigningInContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options, System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, Microsoft.AspNetCore.Http.CookieOptions cookieOptions) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieSigningOutContext` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieSigningOutContext : Microsoft.AspNetCore.Authentication.PropertiesContext { public Microsoft.AspNetCore.Http.CookieOptions CookieOptions { get => throw null; set => throw null; } public CookieSigningOutContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, Microsoft.AspNetCore.Http.CookieOptions cookieOptions) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieSlidingExpirationContext` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieSlidingExpirationContext : Microsoft.AspNetCore.Authentication.PrincipalContext { public CookieSlidingExpirationContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, System.TimeSpan elapsedTime, System.TimeSpan remainingTime) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; @@ -116,7 +109,6 @@ namespace Microsoft public bool ShouldRenew { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieValidatePrincipalContext : Microsoft.AspNetCore.Authentication.PrincipalContext { public CookieValidatePrincipalContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; @@ -125,7 +117,6 @@ namespace Microsoft public bool ShouldRenew { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.ICookieManager` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICookieManager { void AppendResponseCookie(Microsoft.AspNetCore.Http.HttpContext context, string key, string value, Microsoft.AspNetCore.Http.CookieOptions options); @@ -133,20 +124,22 @@ namespace Microsoft string GetRequestCookie(Microsoft.AspNetCore.Http.HttpContext context, string key); } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.ITicketStore` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITicketStore { System.Threading.Tasks.Task RemoveAsync(string key); System.Threading.Tasks.Task RemoveAsync(string key, System.Threading.CancellationToken cancellationToken) => throw null; + System.Threading.Tasks.Task RemoveAsync(string key, Microsoft.AspNetCore.Http.HttpContext httpContext, System.Threading.CancellationToken cancellationToken) => throw null; System.Threading.Tasks.Task RenewAsync(string key, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket); System.Threading.Tasks.Task RenewAsync(string key, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, System.Threading.CancellationToken cancellationToken) => throw null; + System.Threading.Tasks.Task RenewAsync(string key, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, Microsoft.AspNetCore.Http.HttpContext httpContext, System.Threading.CancellationToken cancellationToken) => throw null; System.Threading.Tasks.Task RetrieveAsync(string key); System.Threading.Tasks.Task RetrieveAsync(string key, System.Threading.CancellationToken cancellationToken) => throw null; + System.Threading.Tasks.Task RetrieveAsync(string key, Microsoft.AspNetCore.Http.HttpContext httpContext, System.Threading.CancellationToken cancellationToken) => throw null; System.Threading.Tasks.Task StoreAsync(Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket); System.Threading.Tasks.Task StoreAsync(Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, System.Threading.CancellationToken cancellationToken) => throw null; + System.Threading.Tasks.Task StoreAsync(Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket, Microsoft.AspNetCore.Http.HttpContext httpContext, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Cookies.PostConfigureCookieAuthenticationOptions` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureCookieAuthenticationOptions : Microsoft.Extensions.Options.IPostConfigureOptions { public void PostConfigure(string name, Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationOptions options) => throw null; @@ -160,7 +153,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.CookieExtensions` in `Microsoft.AspNetCore.Authentication.Cookies, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CookieExtensions { public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddCookie(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Core.cs index 75a72f5e2c3..23ddbd0373c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.Core.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authentication.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Authentication { - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationFeature` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationFeature : Microsoft.AspNetCore.Authentication.IAuthenticationFeature { public AuthenticationFeature() => throw null; @@ -14,7 +14,6 @@ namespace Microsoft public Microsoft.AspNetCore.Http.PathString OriginalPathBase { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationHandlerProvider : Microsoft.AspNetCore.Authentication.IAuthenticationHandlerProvider { public AuthenticationHandlerProvider(Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemes) => throw null; @@ -22,7 +21,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider Schemes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationSchemeProvider` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationSchemeProvider : Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider { public virtual void AddScheme(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme) => throw null; @@ -40,7 +38,6 @@ namespace Microsoft public virtual bool TryAddScheme(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationService` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationService : Microsoft.AspNetCore.Authentication.IAuthenticationService { public virtual System.Threading.Tasks.Task AuthenticateAsync(Microsoft.AspNetCore.Http.HttpContext context, string scheme) => throw null; @@ -55,7 +52,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.IClaimsTransformation Transform { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.NoopClaimsTransformation` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NoopClaimsTransformation : Microsoft.AspNetCore.Authentication.IClaimsTransformation { public NoopClaimsTransformation() => throw null; @@ -68,7 +64,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.AuthenticationCoreServiceCollectionExtensions` in `Microsoft.AspNetCore.Authentication.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthenticationCoreServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthenticationCore(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.OAuth.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.OAuth.cs index db3fb3de831..27bcca97c24 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.OAuth.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.OAuth.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authentication.OAuth, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Authentication { - // Generated from `Microsoft.AspNetCore.Authentication.ClaimActionCollectionMapExtensions` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ClaimActionCollectionMapExtensions { public static void DeleteClaim(this Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimActionCollection collection, string claimType) => throw null; @@ -23,7 +23,6 @@ namespace Microsoft namespace OAuth { - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthChallengeProperties` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthChallengeProperties : Microsoft.AspNetCore.Authentication.AuthenticationProperties { public OAuthChallengeProperties() => throw null; @@ -34,7 +33,6 @@ namespace Microsoft public virtual void SetScope(params string[] scopes) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthCodeExchangeContext` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthCodeExchangeContext { public string Code { get => throw null; } @@ -43,7 +41,6 @@ namespace Microsoft public string RedirectUri { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthConstants` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OAuthConstants { public static string CodeChallengeKey; @@ -52,7 +49,6 @@ namespace Microsoft public static string CodeVerifierKey; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthCreatingTicketContext` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthCreatingTicketContext : Microsoft.AspNetCore.Authentication.ResultContext { public string AccessToken { get => throw null; } @@ -68,13 +64,11 @@ namespace Microsoft public System.Text.Json.JsonElement User { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthDefaults` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OAuthDefaults { public static string DisplayName; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthEvents` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthEvents : Microsoft.AspNetCore.Authentication.RemoteAuthenticationEvents { public virtual System.Threading.Tasks.Task CreatingTicket(Microsoft.AspNetCore.Authentication.OAuth.OAuthCreatingTicketContext context) => throw null; @@ -84,7 +78,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task RedirectToAuthorizationEndpoint(Microsoft.AspNetCore.Authentication.RedirectContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthHandler<>` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthHandler : Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler where TOptions : Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions, new() { protected System.Net.Http.HttpClient Backchannel { get => throw null; } @@ -100,7 +93,6 @@ namespace Microsoft public OAuthHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.Authentication.ISystemClock clock) : base(default(Microsoft.Extensions.Options.IOptionsMonitor), default(Microsoft.Extensions.Logging.ILoggerFactory), default(System.Text.Encodings.Web.UrlEncoder), default(Microsoft.AspNetCore.Authentication.ISystemClock)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthOptions : Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions { public string AuthorizationEndpoint { get => throw null; set => throw null; } @@ -117,7 +109,6 @@ namespace Microsoft public override void Validate() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.OAuthTokenResponse` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthTokenResponse : System.IDisposable { public string AccessToken { get => throw null; set => throw null; } @@ -133,7 +124,6 @@ namespace Microsoft namespace Claims { - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ClaimAction { public ClaimAction(string claimType, string valueType) => throw null; @@ -142,7 +132,6 @@ namespace Microsoft public string ValueType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimActionCollection` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClaimActionCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public void Add(Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction action) => throw null; @@ -153,7 +142,6 @@ namespace Microsoft public void Remove(string claimType) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.CustomJsonClaimAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CustomJsonClaimAction : Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction { public CustomJsonClaimAction(string claimType, string valueType, System.Func resolver) : base(default(string), default(string)) => throw null; @@ -161,14 +149,12 @@ namespace Microsoft public override void Run(System.Text.Json.JsonElement userData, System.Security.Claims.ClaimsIdentity identity, string issuer) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.DeleteClaimAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DeleteClaimAction : Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction { public DeleteClaimAction(string claimType) : base(default(string), default(string)) => throw null; public override void Run(System.Text.Json.JsonElement userData, System.Security.Claims.ClaimsIdentity identity, string issuer) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.JsonKeyClaimAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonKeyClaimAction : Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction { public string JsonKey { get => throw null; } @@ -176,7 +162,6 @@ namespace Microsoft public override void Run(System.Text.Json.JsonElement userData, System.Security.Claims.ClaimsIdentity identity, string issuer) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.JsonSubKeyClaimAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonSubKeyClaimAction : Microsoft.AspNetCore.Authentication.OAuth.Claims.JsonKeyClaimAction { public JsonSubKeyClaimAction(string claimType, string valueType, string jsonKey, string subKey) : base(default(string), default(string), default(string)) => throw null; @@ -184,7 +169,6 @@ namespace Microsoft public string SubKey { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.OAuth.Claims.MapAllClaimsAction` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MapAllClaimsAction : Microsoft.AspNetCore.Authentication.OAuth.Claims.ClaimAction { public MapAllClaimsAction() : base(default(string), default(string)) => throw null; @@ -199,7 +183,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.OAuthExtensions` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OAuthExtensions { public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddOAuth(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, string authenticationScheme, System.Action configureOptions) => throw null; @@ -208,7 +191,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddOAuth(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder, string authenticationScheme, string displayName, System.Action configureOptions) where THandler : Microsoft.AspNetCore.Authentication.OAuth.OAuthHandler where TOptions : Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions, new() => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.OAuthPostConfigureOptions<,>` in `Microsoft.AspNetCore.Authentication.OAuth, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OAuthPostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where THandler : Microsoft.AspNetCore.Authentication.OAuth.OAuthHandler where TOptions : Microsoft.AspNetCore.Authentication.OAuth.OAuthOptions, new() { public OAuthPostConfigureOptions(Microsoft.AspNetCore.DataProtection.IDataProtectionProvider dataProtection) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.cs index b4b89562fc0..33cdb01eee1 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authentication.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authentication, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Authentication { - // Generated from `Microsoft.AspNetCore.Authentication.AccessDeniedContext` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AccessDeniedContext : Microsoft.AspNetCore.Authentication.HandleRequestContext { public AccessDeniedContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions options) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions)) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public string ReturnUrlParameter { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationBuilder` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationBuilder { public virtual Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddPolicyScheme(string authenticationScheme, string displayName, System.Action configureOptions) => throw null; @@ -27,7 +26,11 @@ namespace Microsoft public virtual Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationHandler<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public static class AuthenticationConfigurationProviderExtensions + { + public static Microsoft.Extensions.Configuration.IConfiguration GetSchemeConfiguration(this Microsoft.AspNetCore.Authentication.IAuthenticationConfigurationProvider provider, string authenticationScheme) => throw null; + } + public abstract class AuthenticationHandler : Microsoft.AspNetCore.Authentication.IAuthenticationHandler where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() { public System.Threading.Tasks.Task AuthenticateAsync() => throw null; @@ -61,7 +64,6 @@ namespace Microsoft protected System.Text.Encodings.Web.UrlEncoder UrlEncoder { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationMiddleware` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationMiddleware { public AuthenticationMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider schemes) => throw null; @@ -69,7 +71,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider Schemes { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationSchemeOptions { public AuthenticationSchemeOptions() => throw null; @@ -87,14 +88,12 @@ namespace Microsoft public virtual void Validate(string scheme) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.Base64UrlTextEncoder` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Base64UrlTextEncoder { public static System.Byte[] Decode(string text) => throw null; public static string Encode(System.Byte[] data) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.BaseContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class BaseContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { protected BaseContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, TOptions options) => throw null; @@ -105,7 +104,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.AuthenticationScheme Scheme { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.HandleRequestContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandleRequestContext : Microsoft.AspNetCore.Authentication.BaseContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { protected HandleRequestContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, TOptions options) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(TOptions)) => throw null; @@ -114,7 +112,6 @@ namespace Microsoft public void SkipHandler() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.HandleRequestResult` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandleRequestResult : Microsoft.AspNetCore.Authentication.AuthenticateResult { public static Microsoft.AspNetCore.Authentication.HandleRequestResult Fail(System.Exception failure) => throw null; @@ -130,14 +127,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Authentication.HandleRequestResult Success(Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.IDataSerializer<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDataSerializer { TModel Deserialize(System.Byte[] data); System.Byte[] Serialize(TModel model); } - // Generated from `Microsoft.AspNetCore.Authentication.ISecureDataFormat<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISecureDataFormat { string Protect(TData data); @@ -146,19 +141,16 @@ namespace Microsoft TData Unprotect(string protectedText, string purpose); } - // Generated from `Microsoft.AspNetCore.Authentication.ISystemClock` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISystemClock { System.DateTimeOffset UtcNow { get; } } - // Generated from `Microsoft.AspNetCore.Authentication.JsonDocumentAuthExtensions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JsonDocumentAuthExtensions { public static string GetString(this System.Text.Json.JsonElement element, string key) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PolicySchemeHandler` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PolicySchemeHandler : Microsoft.AspNetCore.Authentication.SignInAuthenticationHandler { protected override System.Threading.Tasks.Task HandleAuthenticateAsync() => throw null; @@ -169,33 +161,28 @@ namespace Microsoft public PolicySchemeHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.Authentication.ISystemClock clock) : base(default(Microsoft.Extensions.Options.IOptionsMonitor), default(Microsoft.Extensions.Logging.ILoggerFactory), default(System.Text.Encodings.Web.UrlEncoder), default(Microsoft.AspNetCore.Authentication.ISystemClock)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PolicySchemeOptions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PolicySchemeOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public PolicySchemeOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PrincipalContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PrincipalContext : Microsoft.AspNetCore.Authentication.PropertiesContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public virtual System.Security.Claims.ClaimsPrincipal Principal { get => throw null; set => throw null; } protected PrincipalContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, TOptions options, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(TOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PropertiesContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PropertiesContext : Microsoft.AspNetCore.Authentication.BaseContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public virtual Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } protected PropertiesContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, TOptions options, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(TOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PropertiesDataFormat` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PropertiesDataFormat : Microsoft.AspNetCore.Authentication.SecureDataFormat { public PropertiesDataFormat(Microsoft.AspNetCore.DataProtection.IDataProtector protector) : base(default(Microsoft.AspNetCore.Authentication.IDataSerializer), default(Microsoft.AspNetCore.DataProtection.IDataProtector)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.PropertiesSerializer` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PropertiesSerializer : Microsoft.AspNetCore.Authentication.IDataSerializer { public static Microsoft.AspNetCore.Authentication.PropertiesSerializer Default { get => throw null; } @@ -206,14 +193,12 @@ namespace Microsoft public virtual void Write(System.IO.BinaryWriter writer, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RedirectContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectContext : Microsoft.AspNetCore.Authentication.PropertiesContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public RedirectContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, TOptions options, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties, string redirectUri) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(TOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; public string RedirectUri { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.RemoteAuthenticationContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RemoteAuthenticationContext : Microsoft.AspNetCore.Authentication.HandleRequestContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public void Fail(System.Exception failure) => throw null; @@ -224,7 +209,6 @@ namespace Microsoft public void Success() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RemoteAuthenticationEvents` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RemoteAuthenticationEvents { public virtual System.Threading.Tasks.Task AccessDenied(Microsoft.AspNetCore.Authentication.AccessDeniedContext context) => throw null; @@ -236,7 +220,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task TicketReceived(Microsoft.AspNetCore.Authentication.TicketReceivedContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RemoteAuthenticationHandler : Microsoft.AspNetCore.Authentication.AuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationRequestHandler where TOptions : Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions, new() { protected override System.Threading.Tasks.Task CreateEventsAsync() => throw null; @@ -253,7 +236,6 @@ namespace Microsoft protected virtual bool ValidateCorrelationId(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RemoteAuthenticationOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public Microsoft.AspNetCore.Http.PathString AccessDeniedPath { get => throw null; set => throw null; } @@ -273,7 +255,6 @@ namespace Microsoft public override void Validate(string scheme) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RemoteFailureContext` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RemoteFailureContext : Microsoft.AspNetCore.Authentication.HandleRequestContext { public System.Exception Failure { get => throw null; set => throw null; } @@ -281,7 +262,6 @@ namespace Microsoft public RemoteFailureContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions options, System.Exception failure) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.RequestPathBaseCookieBuilder` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestPathBaseCookieBuilder : Microsoft.AspNetCore.Http.CookieBuilder { protected virtual string AdditionalPath { get => throw null; } @@ -289,7 +269,6 @@ namespace Microsoft public RequestPathBaseCookieBuilder() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.ResultContext<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ResultContext : Microsoft.AspNetCore.Authentication.BaseContext where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions { public void Fail(System.Exception failure) => throw null; @@ -302,7 +281,6 @@ namespace Microsoft public void Success() => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.SecureDataFormat<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SecureDataFormat : Microsoft.AspNetCore.Authentication.ISecureDataFormat { public string Protect(TData data) => throw null; @@ -312,7 +290,6 @@ namespace Microsoft public TData Unprotect(string protectedText, string purpose) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.SignInAuthenticationHandler<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class SignInAuthenticationHandler : Microsoft.AspNetCore.Authentication.SignOutAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationSignInHandler, Microsoft.AspNetCore.Authentication.IAuthenticationSignOutHandler where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() { protected abstract System.Threading.Tasks.Task HandleSignInAsync(System.Security.Claims.ClaimsPrincipal user, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties); @@ -320,7 +297,6 @@ namespace Microsoft public SignInAuthenticationHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.Authentication.ISystemClock clock) : base(default(Microsoft.Extensions.Options.IOptionsMonitor), default(Microsoft.Extensions.Logging.ILoggerFactory), default(System.Text.Encodings.Web.UrlEncoder), default(Microsoft.AspNetCore.Authentication.ISystemClock)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.SignOutAuthenticationHandler<>` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class SignOutAuthenticationHandler : Microsoft.AspNetCore.Authentication.AuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationHandler, Microsoft.AspNetCore.Authentication.IAuthenticationSignOutHandler where TOptions : Microsoft.AspNetCore.Authentication.AuthenticationSchemeOptions, new() { protected abstract System.Threading.Tasks.Task HandleSignOutAsync(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties); @@ -328,27 +304,23 @@ namespace Microsoft public SignOutAuthenticationHandler(Microsoft.Extensions.Options.IOptionsMonitor options, Microsoft.Extensions.Logging.ILoggerFactory logger, System.Text.Encodings.Web.UrlEncoder encoder, Microsoft.AspNetCore.Authentication.ISystemClock clock) : base(default(Microsoft.Extensions.Options.IOptionsMonitor), default(Microsoft.Extensions.Logging.ILoggerFactory), default(System.Text.Encodings.Web.UrlEncoder), default(Microsoft.AspNetCore.Authentication.ISystemClock)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.SystemClock` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SystemClock : Microsoft.AspNetCore.Authentication.ISystemClock { public SystemClock() => throw null; public System.DateTimeOffset UtcNow { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authentication.TicketDataFormat` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TicketDataFormat : Microsoft.AspNetCore.Authentication.SecureDataFormat { public TicketDataFormat(Microsoft.AspNetCore.DataProtection.IDataProtector protector) : base(default(Microsoft.AspNetCore.Authentication.IDataSerializer), default(Microsoft.AspNetCore.DataProtection.IDataProtector)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.TicketReceivedContext` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TicketReceivedContext : Microsoft.AspNetCore.Authentication.RemoteAuthenticationContext { public string ReturnUri { get => throw null; set => throw null; } public TicketReceivedContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions options, Microsoft.AspNetCore.Authentication.AuthenticationTicket ticket) : base(default(Microsoft.AspNetCore.Http.HttpContext), default(Microsoft.AspNetCore.Authentication.AuthenticationScheme), default(Microsoft.AspNetCore.Authentication.RemoteAuthenticationOptions), default(Microsoft.AspNetCore.Authentication.AuthenticationProperties)) => throw null; } - // Generated from `Microsoft.AspNetCore.Authentication.TicketSerializer` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TicketSerializer : Microsoft.AspNetCore.Authentication.IDataSerializer { public static Microsoft.AspNetCore.Authentication.TicketSerializer Default { get => throw null; } @@ -366,7 +338,6 @@ namespace Microsoft } namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.AuthAppBuilderExtensions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthAppBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseAuthentication(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -378,7 +349,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.AuthenticationServiceCollectionExtensions` in `Microsoft.AspNetCore.Authentication, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthenticationServiceCollectionExtensions { public static Microsoft.AspNetCore.Authentication.AuthenticationBuilder AddAuthentication(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.Policy.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.Policy.cs index 9a16deeb178..b222c2499b9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.Policy.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.Policy.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authorization.Policy, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,13 @@ namespace Microsoft { namespace Authorization { - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationMiddleware` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationMiddleware { public AuthorizationMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider policyProvider) => throw null; + public AuthorizationMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider policyProvider, System.IServiceProvider services) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationMiddlewareResultHandler` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationMiddlewareResultHandler { System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy, Microsoft.AspNetCore.Authorization.Policy.PolicyAuthorizationResult authorizeResult); @@ -21,21 +21,18 @@ namespace Microsoft namespace Policy { - // Generated from `Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationMiddlewareResultHandler : Microsoft.AspNetCore.Authorization.IAuthorizationMiddlewareResultHandler { public AuthorizationMiddlewareResultHandler() => throw null; public System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy, Microsoft.AspNetCore.Authorization.Policy.PolicyAuthorizationResult authorizeResult) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Policy.IPolicyEvaluator` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPolicyEvaluator { System.Threading.Tasks.Task AuthenticateAsync(Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy, Microsoft.AspNetCore.Http.HttpContext context); System.Threading.Tasks.Task AuthorizeAsync(Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy, Microsoft.AspNetCore.Authentication.AuthenticateResult authenticationResult, Microsoft.AspNetCore.Http.HttpContext context, object resource); } - // Generated from `Microsoft.AspNetCore.Authorization.Policy.PolicyAuthorizationResult` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PolicyAuthorizationResult { public Microsoft.AspNetCore.Authorization.AuthorizationFailure AuthorizationFailure { get => throw null; } @@ -48,7 +45,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Authorization.Policy.PolicyAuthorizationResult Success() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PolicyEvaluator : Microsoft.AspNetCore.Authorization.Policy.IPolicyEvaluator { public virtual System.Threading.Tasks.Task AuthenticateAsync(Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy, Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -60,17 +56,17 @@ namespace Microsoft } namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.AuthorizationAppBuilderExtensions` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthorizationAppBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseAuthorization(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.AuthorizationEndpointConventionBuilderExtensions` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthorizationEndpointConventionBuilderExtensions { public static TBuilder AllowAnonymous(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static TBuilder RequireAuthorization(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder RequireAuthorization(this TBuilder builder, System.Action configurePolicy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder RequireAuthorization(this TBuilder builder, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static TBuilder RequireAuthorization(this TBuilder builder, params Microsoft.AspNetCore.Authorization.IAuthorizeData[] authorizeData) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static TBuilder RequireAuthorization(this TBuilder builder, params string[] policyNames) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; } @@ -81,11 +77,11 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.PolicyServiceCollectionExtensions` in `Microsoft.AspNetCore.Authorization.Policy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class PolicyServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthorization(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthorization(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configure) => throw null; + public static Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddAuthorizationBuilder(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthorizationPolicyEvaluator(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.cs index 8c9e27c0a17..283e5ba164f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Authorization.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Authorization, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,26 @@ namespace Microsoft { namespace Authorization { - // Generated from `Microsoft.AspNetCore.Authorization.AllowAnonymousAttribute` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AllowAnonymousAttribute : System.Attribute, Microsoft.AspNetCore.Authorization.IAllowAnonymous { public AllowAnonymousAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationFailure` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class AuthorizationBuilder + { + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddDefaultPolicy(string name, System.Action configurePolicy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddDefaultPolicy(string name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddFallbackPolicy(string name, System.Action configurePolicy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddFallbackPolicy(string name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddPolicy(string name, System.Action configurePolicy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder AddPolicy(string name, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; + public AuthorizationBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; + public virtual Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get => throw null; } + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder SetDefaultPolicy(Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder SetFallbackPolicy(Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; + public virtual Microsoft.AspNetCore.Authorization.AuthorizationBuilder SetInvokeHandlersAfterFailure(bool invoke) => throw null; + } + public class AuthorizationFailure { public static Microsoft.AspNetCore.Authorization.AuthorizationFailure ExplicitFail() => throw null; @@ -23,7 +37,6 @@ namespace Microsoft public System.Collections.Generic.IEnumerable FailureReasons { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationFailureReason` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationFailureReason { public AuthorizationFailureReason(Microsoft.AspNetCore.Authorization.IAuthorizationHandler handler, string message) => throw null; @@ -31,7 +44,6 @@ namespace Microsoft public string Message { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationHandler<,>` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AuthorizationHandler : Microsoft.AspNetCore.Authorization.IAuthorizationHandler where TRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { protected AuthorizationHandler() => throw null; @@ -39,7 +51,6 @@ namespace Microsoft protected abstract System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, TRequirement requirement, TResource resource); } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationHandler<>` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AuthorizationHandler : Microsoft.AspNetCore.Authorization.IAuthorizationHandler where TRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { protected AuthorizationHandler() => throw null; @@ -47,7 +58,6 @@ namespace Microsoft protected abstract System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, TRequirement requirement); } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationHandlerContext { public AuthorizationHandlerContext(System.Collections.Generic.IEnumerable requirements, System.Security.Claims.ClaimsPrincipal user, object resource) => throw null; @@ -63,7 +73,6 @@ namespace Microsoft public virtual System.Security.Claims.ClaimsPrincipal User { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationOptions` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationOptions { public void AddPolicy(string name, System.Action configurePolicy) => throw null; @@ -75,7 +84,6 @@ namespace Microsoft public bool InvokeHandlersAfterFailure { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationPolicy` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationPolicy { public System.Collections.Generic.IReadOnlyList AuthenticationSchemes { get => throw null; } @@ -83,10 +91,10 @@ namespace Microsoft public static Microsoft.AspNetCore.Authorization.AuthorizationPolicy Combine(System.Collections.Generic.IEnumerable policies) => throw null; public static Microsoft.AspNetCore.Authorization.AuthorizationPolicy Combine(params Microsoft.AspNetCore.Authorization.AuthorizationPolicy[] policies) => throw null; public static System.Threading.Tasks.Task CombineAsync(Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider policyProvider, System.Collections.Generic.IEnumerable authorizeData) => throw null; + public static System.Threading.Tasks.Task CombineAsync(Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider policyProvider, System.Collections.Generic.IEnumerable authorizeData, System.Collections.Generic.IEnumerable policies) => throw null; public System.Collections.Generic.IReadOnlyList Requirements { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationPolicyBuilder { public Microsoft.AspNetCore.Authorization.AuthorizationPolicyBuilder AddAuthenticationSchemes(params string[] schemes) => throw null; @@ -108,7 +116,6 @@ namespace Microsoft public System.Collections.Generic.IList Requirements { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationResult` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationResult { public static Microsoft.AspNetCore.Authorization.AuthorizationResult Failed() => throw null; @@ -118,7 +125,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Authorization.AuthorizationResult Success() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizationServiceExtensions` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthorizationServiceExtensions { public static System.Threading.Tasks.Task AuthorizeAsync(this Microsoft.AspNetCore.Authorization.IAuthorizationService service, System.Security.Claims.ClaimsPrincipal user, Microsoft.AspNetCore.Authorization.AuthorizationPolicy policy) => throw null; @@ -127,7 +133,6 @@ namespace Microsoft public static System.Threading.Tasks.Task AuthorizeAsync(this Microsoft.AspNetCore.Authorization.IAuthorizationService service, System.Security.Claims.ClaimsPrincipal user, string policyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.AuthorizeAttribute` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizeAttribute : System.Attribute, Microsoft.AspNetCore.Authorization.IAuthorizeData { public string AuthenticationSchemes { get => throw null; set => throw null; } @@ -137,37 +142,33 @@ namespace Microsoft public string Roles { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Authorization.DefaultAuthorizationEvaluator` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultAuthorizationEvaluator : Microsoft.AspNetCore.Authorization.IAuthorizationEvaluator { public DefaultAuthorizationEvaluator() => throw null; public Microsoft.AspNetCore.Authorization.AuthorizationResult Evaluate(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerContextFactory` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultAuthorizationHandlerContextFactory : Microsoft.AspNetCore.Authorization.IAuthorizationHandlerContextFactory { public virtual Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext CreateContext(System.Collections.Generic.IEnumerable requirements, System.Security.Claims.ClaimsPrincipal user, object resource) => throw null; public DefaultAuthorizationHandlerContextFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.DefaultAuthorizationHandlerProvider` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultAuthorizationHandlerProvider : Microsoft.AspNetCore.Authorization.IAuthorizationHandlerProvider { public DefaultAuthorizationHandlerProvider(System.Collections.Generic.IEnumerable handlers) => throw null; public System.Threading.Tasks.Task> GetHandlersAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.DefaultAuthorizationPolicyProvider` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultAuthorizationPolicyProvider : Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider { + public virtual bool AllowsCachingPolicies { get => throw null; } public DefaultAuthorizationPolicyProvider(Microsoft.Extensions.Options.IOptions options) => throw null; public System.Threading.Tasks.Task GetDefaultPolicyAsync() => throw null; public System.Threading.Tasks.Task GetFallbackPolicyAsync() => throw null; public virtual System.Threading.Tasks.Task GetPolicyAsync(string policyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.DefaultAuthorizationService` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultAuthorizationService : Microsoft.AspNetCore.Authorization.IAuthorizationService { public virtual System.Threading.Tasks.Task AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, System.Collections.Generic.IEnumerable requirements) => throw null; @@ -175,44 +176,38 @@ namespace Microsoft public DefaultAuthorizationService(Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider policyProvider, Microsoft.AspNetCore.Authorization.IAuthorizationHandlerProvider handlers, Microsoft.Extensions.Logging.ILogger logger, Microsoft.AspNetCore.Authorization.IAuthorizationHandlerContextFactory contextFactory, Microsoft.AspNetCore.Authorization.IAuthorizationEvaluator evaluator, Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationEvaluator` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationEvaluator { Microsoft.AspNetCore.Authorization.AuthorizationResult Evaluate(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context); } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationHandler` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationHandler { System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context); } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationHandlerContextFactory` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationHandlerContextFactory { Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext CreateContext(System.Collections.Generic.IEnumerable requirements, System.Security.Claims.ClaimsPrincipal user, object resource); } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationHandlerProvider` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationHandlerProvider { System.Threading.Tasks.Task> GetHandlersAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context); } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationPolicyProvider` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationPolicyProvider { + bool AllowsCachingPolicies { get => throw null; } System.Threading.Tasks.Task GetDefaultPolicyAsync(); System.Threading.Tasks.Task GetFallbackPolicyAsync(); System.Threading.Tasks.Task GetPolicyAsync(string policyName); } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationRequirement { } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizationService` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationService { System.Threading.Tasks.Task AuthorizeAsync(System.Security.Claims.ClaimsPrincipal user, object resource, System.Collections.Generic.IEnumerable requirements); @@ -221,7 +216,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.AssertionRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AssertionRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public AssertionRequirement(System.Func> handler) => throw null; @@ -231,7 +225,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.ClaimsAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClaimsAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public System.Collections.Generic.IEnumerable AllowedValues { get => throw null; } @@ -241,7 +234,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.DenyAnonymousAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DenyAnonymousAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public DenyAnonymousAuthorizationRequirement() => throw null; @@ -249,7 +241,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.NameAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NameAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { protected override System.Threading.Tasks.Task HandleRequirementAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context, Microsoft.AspNetCore.Authorization.Infrastructure.NameAuthorizationRequirement requirement) => throw null; @@ -258,7 +249,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.OperationAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OperationAuthorizationRequirement : Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public string Name { get => throw null; set => throw null; } @@ -266,14 +256,13 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.PassThroughAuthorizationHandler` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PassThroughAuthorizationHandler : Microsoft.AspNetCore.Authorization.IAuthorizationHandler { public System.Threading.Tasks.Task HandleAsync(Microsoft.AspNetCore.Authorization.AuthorizationHandlerContext context) => throw null; public PassThroughAuthorizationHandler() => throw null; + public PassThroughAuthorizationHandler(Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Authorization.Infrastructure.RolesAuthorizationRequirement` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RolesAuthorizationRequirement : Microsoft.AspNetCore.Authorization.AuthorizationHandler, Microsoft.AspNetCore.Authorization.IAuthorizationRequirement { public System.Collections.Generic.IEnumerable AllowedRoles { get => throw null; } @@ -289,7 +278,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.AuthorizationServiceCollectionExtensions` in `Microsoft.AspNetCore.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AuthorizationServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddAuthorizationCore(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Authorization.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Authorization.cs index 9638f78aa9f..ab4f39e2d8b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Authorization.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Authorization.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Components.Authorization, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,17 +9,14 @@ namespace Microsoft { namespace Authorization { - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthenticationState` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationState { public AuthenticationState(System.Security.Claims.ClaimsPrincipal user) => throw null; public System.Security.Claims.ClaimsPrincipal User { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthenticationStateChangedHandler` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate void AuthenticationStateChangedHandler(System.Threading.Tasks.Task task); - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AuthenticationStateProvider { public event Microsoft.AspNetCore.Components.Authorization.AuthenticationStateChangedHandler AuthenticationStateChanged; @@ -27,7 +25,6 @@ namespace Microsoft protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task task) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthorizeRouteView` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizeRouteView : Microsoft.AspNetCore.Components.RouteView { public AuthorizeRouteView() => throw null; @@ -37,7 +34,6 @@ namespace Microsoft public object Resource { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthorizeView` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizeView : Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore { public AuthorizeView() => throw null; @@ -46,7 +42,6 @@ namespace Microsoft public string Roles { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Authorization.AuthorizeViewCore` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AuthorizeViewCore : Microsoft.AspNetCore.Components.ComponentBase { protected AuthorizeViewCore() => throw null; @@ -60,7 +55,6 @@ namespace Microsoft public object Resource { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Authorization.CascadingAuthenticationState` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CascadingAuthenticationState : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder __builder) => throw null; @@ -70,7 +64,6 @@ namespace Microsoft protected override void OnInitialized() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Authorization.IHostEnvironmentAuthenticationStateProvider` in `Microsoft.AspNetCore.Components.Authorization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostEnvironmentAuthenticationStateProvider { void SetAuthenticationState(System.Threading.Tasks.Task authenticationStateTask); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Forms.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Forms.cs index 304952c995c..41a3ef373fc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Forms.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Forms.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Components.Forms, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Forms { - // Generated from `Microsoft.AspNetCore.Components.Forms.DataAnnotationsValidator` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataAnnotationsValidator : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public DataAnnotationsValidator() => throw null; @@ -18,7 +18,6 @@ namespace Microsoft protected override void OnParametersSet() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.EditContext` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EditContext { public EditContext(object model) => throw null; @@ -41,14 +40,13 @@ namespace Microsoft public bool Validate() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.EditContextDataAnnotationsExtensions` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EditContextDataAnnotationsExtensions { public static Microsoft.AspNetCore.Components.Forms.EditContext AddDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext) => throw null; public static System.IDisposable EnableDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext) => throw null; + public static System.IDisposable EnableDataAnnotationsValidation(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, System.IServiceProvider serviceProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.EditContextProperties` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EditContextProperties { public EditContextProperties() => throw null; @@ -57,14 +55,12 @@ namespace Microsoft public bool TryGetValue(object key, out object value) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.FieldChangedEventArgs` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FieldChangedEventArgs : System.EventArgs { public FieldChangedEventArgs(Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) => throw null; public Microsoft.AspNetCore.Components.Forms.FieldIdentifier FieldIdentifier { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.FieldIdentifier` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FieldIdentifier : System.IEquatable { public static Microsoft.AspNetCore.Components.Forms.FieldIdentifier Create(System.Linq.Expressions.Expression> accessor) => throw null; @@ -77,7 +73,6 @@ namespace Microsoft public object Model { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.ValidationMessageStore` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationMessageStore { public void Add(System.Linq.Expressions.Expression> accessor, System.Collections.Generic.IEnumerable messages) => throw null; @@ -92,14 +87,12 @@ namespace Microsoft public ValidationMessageStore(Microsoft.AspNetCore.Components.Forms.EditContext editContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.ValidationRequestedEventArgs` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationRequestedEventArgs : System.EventArgs { public static Microsoft.AspNetCore.Components.Forms.ValidationRequestedEventArgs Empty; public ValidationRequestedEventArgs() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.ValidationStateChangedEventArgs` in `Microsoft.AspNetCore.Components.Forms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationStateChangedEventArgs : System.EventArgs { public static Microsoft.AspNetCore.Components.Forms.ValidationStateChangedEventArgs Empty; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Server.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Server.cs index 085468327de..7a6d1d8d577 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Server.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Server.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Components.Server, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComponentEndpointConventionBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder, Microsoft.AspNetCore.Builder.IHubEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ComponentEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ComponentEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.ComponentEndpointConventionBuilder MapBlazorHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints) => throw null; @@ -26,7 +26,6 @@ namespace Microsoft { namespace Server { - // Generated from `Microsoft.AspNetCore.Components.Server.CircuitOptions` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CircuitOptions { public CircuitOptions() => throw null; @@ -38,7 +37,6 @@ namespace Microsoft public Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions RootComponents { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Server.CircuitRootComponentOptions` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CircuitRootComponentOptions : Microsoft.AspNetCore.Components.Web.IJSComponentConfiguration { public CircuitRootComponentOptions() => throw null; @@ -46,7 +44,6 @@ namespace Microsoft public int MaxJSRootComponents { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Server.RevalidatingServerAuthenticationStateProvider` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RevalidatingServerAuthenticationStateProvider : Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider, System.IDisposable { void System.IDisposable.Dispose() => throw null; @@ -56,7 +53,6 @@ namespace Microsoft protected abstract System.Threading.Tasks.Task ValidateAuthenticationStateAsync(Microsoft.AspNetCore.Components.Authorization.AuthenticationState authenticationState, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Components.Server.ServerAuthenticationStateProvider` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServerAuthenticationStateProvider : Microsoft.AspNetCore.Components.Authorization.AuthenticationStateProvider, Microsoft.AspNetCore.Components.Authorization.IHostEnvironmentAuthenticationStateProvider { public override System.Threading.Tasks.Task GetAuthenticationStateAsync() => throw null; @@ -66,13 +62,11 @@ namespace Microsoft namespace Circuits { - // Generated from `Microsoft.AspNetCore.Components.Server.Circuits.Circuit` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Circuit { public string Id { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Server.Circuits.CircuitHandler` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class CircuitHandler { protected CircuitHandler() => throw null; @@ -86,7 +80,6 @@ namespace Microsoft } namespace ProtectedBrowserStorage { - // Generated from `Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ProtectedBrowserStorage { public System.Threading.Tasks.ValueTask DeleteAsync(string key) => throw null; @@ -97,7 +90,6 @@ namespace Microsoft public System.Threading.Tasks.ValueTask SetAsync(string purpose, string key, object value) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorageResult<>` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ProtectedBrowserStorageResult { // Stub generator skipped constructor @@ -105,13 +97,11 @@ namespace Microsoft public TValue Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedLocalStorage` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProtectedLocalStorage : Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage { public ProtectedLocalStorage(Microsoft.JSInterop.IJSRuntime jsRuntime, Microsoft.AspNetCore.DataProtection.IDataProtectionProvider dataProtectionProvider) : base(default(string), default(Microsoft.JSInterop.IJSRuntime), default(Microsoft.AspNetCore.DataProtection.IDataProtectionProvider)) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedSessionStorage` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProtectedSessionStorage : Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage.ProtectedBrowserStorage { public ProtectedSessionStorage(Microsoft.JSInterop.IJSRuntime jsRuntime, Microsoft.AspNetCore.DataProtection.IDataProtectionProvider dataProtectionProvider) : base(default(string), default(Microsoft.JSInterop.IJSRuntime), default(Microsoft.AspNetCore.DataProtection.IDataProtectionProvider)) => throw null; @@ -125,19 +115,16 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ComponentServiceCollectionExtensions` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ComponentServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServerSideBlazorBuilder AddServerSideBlazor(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configure = default(System.Action)) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.IServerSideBlazorBuilder` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServerSideBlazorBuilder { Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } - // Generated from `Microsoft.Extensions.DependencyInjection.ServerSideBlazorBuilderExtensions` in `Microsoft.AspNetCore.Components.Server, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServerSideBlazorBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IServerSideBlazorBuilder AddCircuitOptions(this Microsoft.Extensions.DependencyInjection.IServerSideBlazorBuilder builder, System.Action configure) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Web.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Web.cs index 0ff2e593df5..49c2bd9fadd 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Web.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.Web.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Components.Web, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Components { - // Generated from `Microsoft.AspNetCore.Components.BindInputElementAttribute` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindInputElementAttribute : System.Attribute { public BindInputElementAttribute(string type, string suffix, string valueAttribute, string changeAttribute, bool isInvariantCulture, string format) => throw null; @@ -18,14 +18,12 @@ namespace Microsoft public string ValueAttribute { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ElementReferenceExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ElementReferenceExtensions { public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference) => throw null; public static System.Threading.Tasks.ValueTask FocusAsync(this Microsoft.AspNetCore.Components.ElementReference elementReference, bool preventScroll) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.WebElementReferenceContext` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebElementReferenceContext : Microsoft.AspNetCore.Components.ElementReferenceContext { public WebElementReferenceContext(Microsoft.JSInterop.IJSRuntime jsRuntime) => throw null; @@ -33,13 +31,11 @@ namespace Microsoft namespace Forms { - // Generated from `Microsoft.AspNetCore.Components.Forms.BrowserFileExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class BrowserFileExtensions { public static System.Threading.Tasks.ValueTask RequestImageFileAsync(this Microsoft.AspNetCore.Components.Forms.IBrowserFile browserFile, string format, int maxWidth, int maxHeight) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.EditContextFieldClassExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EditContextFieldClassExtensions { public static string FieldCssClass(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) => throw null; @@ -47,7 +43,6 @@ namespace Microsoft public static void SetFieldCssClassProvider(this Microsoft.AspNetCore.Components.Forms.EditContext editContext, Microsoft.AspNetCore.Components.Forms.FieldCssClassProvider fieldCssClassProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.EditForm` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EditForm : Microsoft.AspNetCore.Components.ComponentBase { public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get => throw null; set => throw null; } @@ -62,14 +57,12 @@ namespace Microsoft public Microsoft.AspNetCore.Components.EventCallback OnValidSubmit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.FieldCssClassProvider` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FieldCssClassProvider { public FieldCssClassProvider() => throw null; public virtual string GetFieldCssClass(Microsoft.AspNetCore.Components.Forms.EditContext editContext, Microsoft.AspNetCore.Components.Forms.FieldIdentifier fieldIdentifier) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.IBrowserFile` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBrowserFile { string ContentType { get; } @@ -79,12 +72,10 @@ namespace Microsoft System.Int64 Size { get; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.IInputFileJsCallbacks` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IInputFileJsCallbacks { } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputBase<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class InputBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get => throw null; set => throw null; } @@ -105,7 +96,6 @@ namespace Microsoft public System.Linq.Expressions.Expression> ValueExpression { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputCheckbox` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputCheckbox : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -114,7 +104,6 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out bool result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputDate<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputDate : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -127,7 +116,6 @@ namespace Microsoft public Microsoft.AspNetCore.Components.Forms.InputDateType Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputDateType` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum InputDateType : int { Date = 0, @@ -136,7 +124,6 @@ namespace Microsoft Time = 3, } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputFile` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputFile : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public System.Collections.Generic.IDictionary AdditionalAttributes { get => throw null; set => throw null; } @@ -149,7 +136,6 @@ namespace Microsoft protected override void OnInitialized() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputFileChangeEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputFileChangeEventArgs : System.EventArgs { public Microsoft.AspNetCore.Components.Forms.IBrowserFile File { get => throw null; } @@ -158,7 +144,6 @@ namespace Microsoft public InputFileChangeEventArgs(System.Collections.Generic.IReadOnlyList files) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputNumber<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputNumber : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -169,18 +154,17 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputRadio<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputRadio : Microsoft.AspNetCore.Components.ComponentBase { public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get => throw null; set => throw null; } protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; + public Microsoft.AspNetCore.Components.ElementReference? Element { get => throw null; set => throw null; } public InputRadio() => throw null; public string Name { get => throw null; set => throw null; } protected override void OnParametersSet() => throw null; public TValue Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputRadioGroup<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputRadioGroup : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -191,7 +175,6 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputSelect<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputSelect : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -202,7 +185,6 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out TValue result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputText` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputText : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -211,7 +193,6 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.InputTextArea` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputTextArea : Microsoft.AspNetCore.Components.Forms.InputBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -220,7 +201,6 @@ namespace Microsoft protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.RemoteBrowserFileStreamOptions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RemoteBrowserFileStreamOptions { public int MaxBufferSize { get => throw null; set => throw null; } @@ -229,7 +209,6 @@ namespace Microsoft public System.TimeSpan SegmentFetchTimeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Forms.ValidationMessage<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationMessage : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get => throw null; set => throw null; } @@ -241,7 +220,6 @@ namespace Microsoft public ValidationMessage() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Forms.ValidationSummary` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationSummary : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public System.Collections.Generic.IReadOnlyDictionary AdditionalAttributes { get => throw null; set => throw null; } @@ -256,7 +234,6 @@ namespace Microsoft } namespace RenderTree { - // Generated from `Microsoft.AspNetCore.Components.RenderTree.WebEventDescriptor` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebEventDescriptor { public Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo EventFieldInfo { get => throw null; set => throw null; } @@ -265,7 +242,6 @@ namespace Microsoft public WebEventDescriptor() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.WebRenderer` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class WebRenderer : Microsoft.AspNetCore.Components.RenderTree.Renderer { protected internal int AddRootComponent(System.Type componentType, string domElementSelector) => throw null; @@ -278,7 +254,6 @@ namespace Microsoft } namespace Routing { - // Generated from `Microsoft.AspNetCore.Components.Routing.FocusOnNavigate` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FocusOnNavigate : Microsoft.AspNetCore.Components.ComponentBase { public FocusOnNavigate() => throw null; @@ -288,7 +263,6 @@ namespace Microsoft public string Selector { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Routing.NavLink` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NavLink : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { public string ActiveClass { get => throw null; set => throw null; } @@ -303,29 +277,36 @@ namespace Microsoft protected override void OnParametersSet() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Routing.NavLinkMatch` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum NavLinkMatch : int { All = 1, Prefix = 0, } + public class NavigationLock : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, System.IAsyncDisposable + { + void Microsoft.AspNetCore.Components.IComponent.Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; + public bool ConfirmExternalNavigation { get => throw null; set => throw null; } + System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync() => throw null; + public NavigationLock() => throw null; + System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() => throw null; + public Microsoft.AspNetCore.Components.EventCallback OnBeforeInternalNavigation { get => throw null; set => throw null; } + System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IComponent.SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) => throw null; + } + } namespace Web { - // Generated from `Microsoft.AspNetCore.Components.Web.BindAttributes` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class BindAttributes { } - // Generated from `Microsoft.AspNetCore.Components.Web.ClipboardEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClipboardEventArgs : System.EventArgs { public ClipboardEventArgs() => throw null; public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.DataTransfer` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataTransfer { public DataTransfer() => throw null; @@ -336,7 +317,6 @@ namespace Microsoft public string[] Types { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.DataTransferItem` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataTransferItem { public DataTransferItem() => throw null; @@ -344,14 +324,12 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.DragEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DragEventArgs : Microsoft.AspNetCore.Components.Web.MouseEventArgs { public Microsoft.AspNetCore.Components.Web.DataTransfer DataTransfer { get => throw null; set => throw null; } public DragEventArgs() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.ErrorBoundary` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ErrorBoundary : Microsoft.AspNetCore.Components.ErrorBoundaryBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -359,7 +337,6 @@ namespace Microsoft protected override System.Threading.Tasks.Task OnErrorAsync(System.Exception exception) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.ErrorEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ErrorEventArgs : System.EventArgs { public int Colno { get => throw null; set => throw null; } @@ -370,19 +347,16 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.EventHandlers` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EventHandlers { } - // Generated from `Microsoft.AspNetCore.Components.Web.FocusEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FocusEventArgs : System.EventArgs { public FocusEventArgs() => throw null; public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.HeadContent` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeadContent : Microsoft.AspNetCore.Components.ComponentBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -390,7 +364,6 @@ namespace Microsoft public HeadContent() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.HeadOutlet` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeadOutlet : Microsoft.AspNetCore.Components.ComponentBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -398,19 +371,16 @@ namespace Microsoft protected override System.Threading.Tasks.Task OnAfterRenderAsync(bool firstRender) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.IErrorBoundaryLogger` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IErrorBoundaryLogger { System.Threading.Tasks.ValueTask LogErrorAsync(System.Exception exception); } - // Generated from `Microsoft.AspNetCore.Components.Web.IJSComponentConfiguration` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSComponentConfiguration { Microsoft.AspNetCore.Components.Web.JSComponentConfigurationStore JSComponents { get; } } - // Generated from `Microsoft.AspNetCore.Components.Web.JSComponentConfigurationExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSComponentConfigurationExtensions { public static void RegisterForJavaScript(this Microsoft.AspNetCore.Components.Web.IJSComponentConfiguration configuration, System.Type componentType, string identifier) => throw null; @@ -419,13 +389,11 @@ namespace Microsoft public static void RegisterForJavaScript(this Microsoft.AspNetCore.Components.Web.IJSComponentConfiguration configuration, string identifier, string javaScriptInitializer) where TComponent : Microsoft.AspNetCore.Components.IComponent => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.JSComponentConfigurationStore` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSComponentConfigurationStore { public JSComponentConfigurationStore() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.KeyboardEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyboardEventArgs : System.EventArgs { public bool AltKey { get => throw null; set => throw null; } @@ -440,7 +408,6 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.MouseEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MouseEventArgs : System.EventArgs { public bool AltKey { get => throw null; set => throw null; } @@ -452,6 +419,8 @@ namespace Microsoft public System.Int64 Detail { get => throw null; set => throw null; } public bool MetaKey { get => throw null; set => throw null; } public MouseEventArgs() => throw null; + public double MovementX { get => throw null; set => throw null; } + public double MovementY { get => throw null; set => throw null; } public double OffsetX { get => throw null; set => throw null; } public double OffsetY { get => throw null; set => throw null; } public double PageX { get => throw null; set => throw null; } @@ -462,7 +431,6 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.PageTitle` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageTitle : Microsoft.AspNetCore.Components.ComponentBase { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -470,7 +438,6 @@ namespace Microsoft public PageTitle() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.PointerEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PointerEventArgs : Microsoft.AspNetCore.Components.Web.MouseEventArgs { public float Height { get => throw null; set => throw null; } @@ -484,7 +451,6 @@ namespace Microsoft public float Width { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.ProgressEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProgressEventArgs : System.EventArgs { public bool LengthComputable { get => throw null; set => throw null; } @@ -494,7 +460,6 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.TouchEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TouchEventArgs : System.EventArgs { public bool AltKey { get => throw null; set => throw null; } @@ -509,7 +474,6 @@ namespace Microsoft public string Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.TouchPoint` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TouchPoint { public double ClientX { get => throw null; set => throw null; } @@ -522,7 +486,6 @@ namespace Microsoft public TouchPoint() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.WebEventCallbackFactoryEventArgsExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebEventCallbackFactoryEventArgsExtensions { public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) => throw null; @@ -547,14 +510,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.WebRenderTreeBuilderExtensions` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebRenderTreeBuilderExtensions { public static void AddEventPreventDefaultAttribute(this Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder, int sequence, string eventName, bool value) => throw null; public static void AddEventStopPropagationAttribute(this Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder, int sequence, string eventName, bool value) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Web.WheelEventArgs` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WheelEventArgs : Microsoft.AspNetCore.Components.Web.MouseEventArgs { public System.Int64 DeltaMode { get => throw null; set => throw null; } @@ -566,7 +527,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Components.Web.Infrastructure.JSComponentInterop` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSComponentInterop { protected internal virtual int AddRootComponent(string identifier, string domElementSelector) => throw null; @@ -578,15 +538,12 @@ namespace Microsoft } namespace Virtualization { - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.IVirtualizeJsCallbacks` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IVirtualizeJsCallbacks { } - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.ValueTask> ItemsProviderDelegate(Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderRequest request); - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderRequest` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ItemsProviderRequest { public System.Threading.CancellationToken CancellationToken { get => throw null; } @@ -596,7 +553,6 @@ namespace Microsoft public int StartIndex { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ItemsProviderResult { public System.Collections.Generic.IEnumerable Items { get => throw null; } @@ -605,7 +561,6 @@ namespace Microsoft public int TotalItemCount { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.PlaceholderContext` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PlaceholderContext { public int Index { get => throw null; } @@ -614,7 +569,6 @@ namespace Microsoft public float Size { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<>` in `Microsoft.AspNetCore.Components.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Virtualize : Microsoft.AspNetCore.Components.ComponentBase, System.IAsyncDisposable { protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) => throw null; @@ -629,6 +583,7 @@ namespace Microsoft public int OverscanCount { get => throw null; set => throw null; } public Microsoft.AspNetCore.Components.RenderFragment Placeholder { get => throw null; set => throw null; } public System.Threading.Tasks.Task RefreshDataAsync() => throw null; + public string SpacerElement { get => throw null; set => throw null; } public Virtualize() => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.cs index 81b9b996f3d..d9424fa5b1e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Components.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Components, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Components { - // Generated from `Microsoft.AspNetCore.Components.BindConverter` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class BindConverter { public static string FormatValue(System.DateOnly value, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; @@ -75,7 +75,6 @@ namespace Microsoft public static bool TryConvertToTimeOnly(object obj, System.Globalization.CultureInfo culture, string format, out System.TimeOnly value) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.BindElementAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindElementAttribute : System.Attribute { public BindElementAttribute(string element, string suffix, string valueAttribute, string changeAttribute) => throw null; @@ -85,21 +84,18 @@ namespace Microsoft public string ValueAttribute { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.CascadingParameterAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CascadingParameterAttribute : System.Attribute { public CascadingParameterAttribute() => throw null; public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.CascadingTypeParameterAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CascadingTypeParameterAttribute : System.Attribute { public CascadingTypeParameterAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.CascadingValue<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CascadingValue : Microsoft.AspNetCore.Components.IComponent { public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; @@ -111,14 +107,12 @@ namespace Microsoft public TValue Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ChangeEventArgs` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ChangeEventArgs : System.EventArgs { public ChangeEventArgs() => throw null; public object Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ComponentBase` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent { void Microsoft.AspNetCore.Components.IComponent.Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; @@ -139,7 +133,6 @@ namespace Microsoft protected void StateHasChanged() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Dispatcher` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Dispatcher { public void AssertAccess() => throw null; @@ -153,7 +146,6 @@ namespace Microsoft protected void OnUnhandledException(System.UnhandledExceptionEventArgs e) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.DynamicComponent` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DynamicComponent : Microsoft.AspNetCore.Components.IComponent { public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; @@ -164,13 +156,11 @@ namespace Microsoft public System.Type Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.EditorRequiredAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EditorRequiredAttribute : System.Attribute { public EditorRequiredAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.ElementReference` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ElementReference { public Microsoft.AspNetCore.Components.ElementReferenceContext Context { get => throw null; } @@ -180,13 +170,11 @@ namespace Microsoft public string Id { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ElementReferenceContext` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ElementReferenceContext { protected ElementReferenceContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.ErrorBoundaryBase` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ErrorBoundaryBase : Microsoft.AspNetCore.Components.ComponentBase { public Microsoft.AspNetCore.Components.RenderFragment ChildContent { get => throw null; set => throw null; } @@ -198,7 +186,6 @@ namespace Microsoft public void Recover() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallback` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct EventCallback { public static Microsoft.AspNetCore.Components.EventCallback Empty; @@ -210,7 +197,6 @@ namespace Microsoft public System.Threading.Tasks.Task InvokeAsync(object arg) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallback<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct EventCallback { public static Microsoft.AspNetCore.Components.EventCallback Empty; @@ -221,7 +207,6 @@ namespace Microsoft public System.Threading.Tasks.Task InvokeAsync(TValue arg) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallbackFactory` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventCallbackFactory { public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) => throw null; @@ -240,7 +225,6 @@ namespace Microsoft public EventCallbackFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallbackFactoryBinderExtensions` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EventCallbackFactoryBinderExtensions { public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.DateOnly existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; @@ -274,10 +258,41 @@ namespace Microsoft public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.Int16 existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, System.Int16? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, string existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateOnly existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateOnly existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateOnly? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateOnly? existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTime existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTime existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTime? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTime? existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTimeOffset existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTimeOffset existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTimeOffset? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.DateTimeOffset? existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.TimeOnly existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.TimeOnly existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.TimeOnly? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.TimeOnly? existingValue, string format, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, bool existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, bool? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Decimal existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Decimal? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, double existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, double? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, float existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, float? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, int existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, int? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Int64 existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Int64? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Int16 existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, System.Int16? existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, string existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action setter, T existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateBinder(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func setter, T existingValue, System.Globalization.CultureInfo culture = default(System.Globalization.CultureInfo)) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallbackFactoryEventArgsExtensions` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EventCallbackFactoryEventArgsExtensions { public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Action callback) => throw null; @@ -286,7 +301,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Components.EventCallback Create(this Microsoft.AspNetCore.Components.EventCallbackFactory factory, object receiver, System.Func callback) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventCallbackWorkItem` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct EventCallbackWorkItem { public static Microsoft.AspNetCore.Components.EventCallbackWorkItem Empty; @@ -295,7 +309,6 @@ namespace Microsoft public System.Threading.Tasks.Task InvokeAsync(object arg) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.EventHandlerAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventHandlerAttribute : System.Attribute { public string AttributeName { get => throw null; } @@ -306,68 +319,57 @@ namespace Microsoft public EventHandlerAttribute(string attributeName, System.Type eventArgsType, bool enableStopPropagation, bool enablePreventDefault) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.ICascadingValueComponent` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface ICascadingValueComponent { } - // Generated from `Microsoft.AspNetCore.Components.IComponent` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IComponent { void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle); System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters); } - // Generated from `Microsoft.AspNetCore.Components.IComponentActivator` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IComponentActivator { Microsoft.AspNetCore.Components.IComponent CreateInstance(System.Type componentType); } - // Generated from `Microsoft.AspNetCore.Components.IErrorBoundary` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IErrorBoundary { } - // Generated from `Microsoft.AspNetCore.Components.IEventCallback` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IEventCallback { bool HasDelegate { get; } } - // Generated from `Microsoft.AspNetCore.Components.IHandleAfterRender` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHandleAfterRender { System.Threading.Tasks.Task OnAfterRenderAsync(); } - // Generated from `Microsoft.AspNetCore.Components.IHandleEvent` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHandleEvent { System.Threading.Tasks.Task HandleEventAsync(Microsoft.AspNetCore.Components.EventCallbackWorkItem item, object arg); } - // Generated from `Microsoft.AspNetCore.Components.IPersistentComponentStateStore` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPersistentComponentStateStore { System.Threading.Tasks.Task> GetPersistedStateAsync(); System.Threading.Tasks.Task PersistStateAsync(System.Collections.Generic.IReadOnlyDictionary state); } - // Generated from `Microsoft.AspNetCore.Components.InjectAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InjectAttribute : System.Attribute { public InjectAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.LayoutAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LayoutAttribute : System.Attribute { public LayoutAttribute(System.Type layoutType) => throw null; public System.Type LayoutType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.LayoutComponentBase` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class LayoutComponentBase : Microsoft.AspNetCore.Components.ComponentBase { public Microsoft.AspNetCore.Components.RenderFragment Body { get => throw null; set => throw null; } @@ -375,7 +377,6 @@ namespace Microsoft public override System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.LayoutView` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LayoutView : Microsoft.AspNetCore.Components.IComponent { public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; @@ -385,13 +386,11 @@ namespace Microsoft public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.LocationChangeException` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocationChangeException : System.Exception { public LocationChangeException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.MarkupString` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct MarkupString { // Stub generator skipped constructor @@ -401,18 +400,18 @@ namespace Microsoft public static explicit operator Microsoft.AspNetCore.Components.MarkupString(string value) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.NavigationException` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NavigationException : System.Exception { public string Location { get => throw null; } public NavigationException(string uri) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.NavigationManager` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class NavigationManager { public string BaseUri { get => throw null; set => throw null; } protected virtual void EnsureInitialized() => throw null; + protected virtual void HandleLocationChangingHandlerException(System.Exception ex, Microsoft.AspNetCore.Components.Routing.LocationChangingContext context) => throw null; + public string HistoryEntryState { get => throw null; set => throw null; } protected void Initialize(string baseUri, string uri) => throw null; public event System.EventHandler LocationChanged; public void NavigateTo(string uri, Microsoft.AspNetCore.Components.NavigationOptions options) => throw null; @@ -422,12 +421,14 @@ namespace Microsoft protected virtual void NavigateToCore(string uri, bool forceLoad) => throw null; protected NavigationManager() => throw null; protected void NotifyLocationChanged(bool isInterceptedLink) => throw null; + protected System.Threading.Tasks.ValueTask NotifyLocationChangingAsync(string uri, string state, bool isNavigationIntercepted) => throw null; + public System.IDisposable RegisterLocationChangingHandler(System.Func locationChangingHandler) => throw null; + protected virtual void SetNavigationLockState(bool value) => throw null; public System.Uri ToAbsoluteUri(string relativeUri) => throw null; public string ToBaseRelativePath(string uri) => throw null; public string Uri { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.NavigationManagerExtensions` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class NavigationManagerExtensions { public static string GetUriWithQueryParameter(this Microsoft.AspNetCore.Components.NavigationManager navigationManager, string name, System.DateOnly value) => throw null; @@ -455,15 +456,14 @@ namespace Microsoft public static string GetUriWithQueryParameters(this Microsoft.AspNetCore.Components.NavigationManager navigationManager, string uri, System.Collections.Generic.IReadOnlyDictionary parameters) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.NavigationOptions` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct NavigationOptions { public bool ForceLoad { get => throw null; set => throw null; } + public string HistoryEntryState { get => throw null; set => throw null; } // Stub generator skipped constructor public bool ReplaceHistoryEntry { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.OwningComponentBase` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class OwningComponentBase : Microsoft.AspNetCore.Components.ComponentBase, System.IDisposable { void System.IDisposable.Dispose() => throw null; @@ -473,21 +473,18 @@ namespace Microsoft protected System.IServiceProvider ScopedServices { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.OwningComponentBase<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class OwningComponentBase : Microsoft.AspNetCore.Components.OwningComponentBase, System.IDisposable { protected OwningComponentBase() => throw null; protected TService Service { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ParameterAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ParameterAttribute : System.Attribute { public bool CaptureUnmatchedValues { get => throw null; set => throw null; } public ParameterAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.ParameterValue` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ParameterValue { public bool Cascading { get => throw null; } @@ -496,10 +493,8 @@ namespace Microsoft public object Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.ParameterView` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ParameterView { - // Generated from `Microsoft.AspNetCore.Components.ParameterView+Enumerator` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator { public Microsoft.AspNetCore.Components.ParameterValue Current { get => throw null; } @@ -519,7 +514,6 @@ namespace Microsoft public bool TryGetValue(string parameterName, out TValue result) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.PersistentComponentState` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PersistentComponentState { public void PersistAsJson(string key, TValue instance) => throw null; @@ -527,20 +521,16 @@ namespace Microsoft public bool TryTakeFromJson(string key, out TValue instance) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.PersistingComponentStateSubscription` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PersistingComponentStateSubscription : System.IDisposable { public void Dispose() => throw null; // Stub generator skipped constructor } - // Generated from `Microsoft.AspNetCore.Components.RenderFragment` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate void RenderFragment(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder); - // Generated from `Microsoft.AspNetCore.Components.RenderFragment<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(TValue value); - // Generated from `Microsoft.AspNetCore.Components.RenderHandle` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RenderHandle { public Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get => throw null; } @@ -550,14 +540,12 @@ namespace Microsoft // Stub generator skipped constructor } - // Generated from `Microsoft.AspNetCore.Components.RouteAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteAttribute : System.Attribute { public RouteAttribute(string template) => throw null; public string Template { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.RouteData` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteData { public System.Type PageType { get => throw null; } @@ -565,7 +553,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyDictionary RouteValues { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.RouteView` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteView : Microsoft.AspNetCore.Components.IComponent { public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) => throw null; @@ -576,7 +563,6 @@ namespace Microsoft public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.SupplyParameterFromQueryAttribute` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SupplyParameterFromQueryAttribute : System.Attribute { public string Name { get => throw null; set => throw null; } @@ -585,18 +571,22 @@ namespace Microsoft namespace CompilerServices { - // Generated from `Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RuntimeHelpers { + public static System.Func CreateInferredBindSetter(System.Action callback, T value) => throw null; + public static System.Func CreateInferredBindSetter(System.Func callback, T value) => throw null; public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Action callback, T value) => throw null; + public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, Microsoft.AspNetCore.Components.EventCallback callback, T value) => throw null; public static Microsoft.AspNetCore.Components.EventCallback CreateInferredEventCallback(object receiver, System.Func callback, T value) => throw null; + public static System.Threading.Tasks.Task InvokeAsynchronousDelegate(System.Action callback) => throw null; + public static System.Threading.Tasks.Task InvokeAsynchronousDelegate(System.Func callback) => throw null; + public static void InvokeSynchronousDelegate(System.Action callback) => throw null; public static T TypeCheck(T value) => throw null; } } namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Components.Infrastructure.ComponentStatePersistenceManager` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComponentStatePersistenceManager { public ComponentStatePersistenceManager(Microsoft.Extensions.Logging.ILogger logger) => throw null; @@ -608,7 +598,6 @@ namespace Microsoft } namespace RenderTree { - // Generated from `Microsoft.AspNetCore.Components.RenderTree.ArrayBuilderSegment<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ArrayBuilderSegment : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public T[] Array { get => throw null; } @@ -620,7 +609,6 @@ namespace Microsoft public int Offset { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.ArrayRange<>` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ArrayRange { public T[] Array; @@ -630,7 +618,6 @@ namespace Microsoft public int Count; } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.EventFieldInfo` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventFieldInfo { public int ComponentId { get => throw null; set => throw null; } @@ -638,7 +625,6 @@ namespace Microsoft public object FieldValue { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderBatch` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RenderBatch { public Microsoft.AspNetCore.Components.RenderTree.ArrayRange DisposedComponentIDs { get => throw null; } @@ -648,7 +634,6 @@ namespace Microsoft public Microsoft.AspNetCore.Components.RenderTree.ArrayRange UpdatedComponents { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiff` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RenderTreeDiff { public int ComponentId; @@ -656,7 +641,6 @@ namespace Microsoft // Stub generator skipped constructor } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderTreeEdit` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RenderTreeEdit { public int MoveToSiblingIndex; @@ -667,7 +651,6 @@ namespace Microsoft public Microsoft.AspNetCore.Components.RenderTree.RenderTreeEditType Type; } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderTreeEditType` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RenderTreeEditType : int { PermutationListEnd = 10, @@ -682,7 +665,6 @@ namespace Microsoft UpdateText = 5, } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RenderTreeFrame { public System.UInt64 AttributeEventHandlerId { get => throw null; } @@ -710,7 +692,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrameType` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RenderTreeFrameType : short { Attribute = 3, @@ -724,7 +705,6 @@ namespace Microsoft Text = 2, } - // Generated from `Microsoft.AspNetCore.Components.RenderTree.Renderer` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Renderer : System.IAsyncDisposable, System.IDisposable { protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) => throw null; @@ -751,7 +731,6 @@ namespace Microsoft } namespace Rendering { - // Generated from `Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RenderTreeBuilder : System.IDisposable { public void AddAttribute(int sequence, Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) => throw null; @@ -764,6 +743,7 @@ namespace Microsoft public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) => throw null; public void AddComponentReferenceCapture(int sequence, System.Action componentReferenceCaptureAction) => throw null; public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString markupContent) => throw null; + public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString? markupContent) => throw null; public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment) => throw null; public void AddContent(int sequence, object textContent) => throw null; public void AddContent(int sequence, string textContent) => throw null; @@ -789,34 +769,40 @@ namespace Microsoft } namespace Routing { - // Generated from `Microsoft.AspNetCore.Components.Routing.IHostEnvironmentNavigationManager` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostEnvironmentNavigationManager { void Initialize(string baseUri, string uri); } - // Generated from `Microsoft.AspNetCore.Components.Routing.INavigationInterception` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface INavigationInterception { System.Threading.Tasks.Task EnableNavigationInterceptionAsync(); } - // Generated from `Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocationChangedEventArgs : System.EventArgs { + public string HistoryEntryState { get => throw null; set => throw null; } public bool IsNavigationIntercepted { get => throw null; } public string Location { get => throw null; } public LocationChangedEventArgs(string location, bool isNavigationIntercepted) => throw null; } - // Generated from `Microsoft.AspNetCore.Components.Routing.NavigationContext` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class LocationChangingContext + { + public System.Threading.CancellationToken CancellationToken { get => throw null; set => throw null; } + public string HistoryEntryState { get => throw null; set => throw null; } + public bool IsNavigationIntercepted { get => throw null; set => throw null; } + public LocationChangingContext() => throw null; + public void PreventNavigation() => throw null; + public string TargetLocation { get => throw null; set => throw null; } + } + public class NavigationContext { public System.Threading.CancellationToken CancellationToken { get => throw null; } public string Path { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Components.Routing.Router` in `Microsoft.AspNetCore.Components, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Router : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, System.IDisposable { public System.Collections.Generic.IEnumerable AdditionalAssemblies { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Connections.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Connections.Abstractions.cs index 29e4569777f..34184920670 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Connections.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Connections.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Connections.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Connections { - // Generated from `Microsoft.AspNetCore.Connections.AddressInUseException` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AddressInUseException : System.InvalidOperationException { public AddressInUseException(string message) => throw null; public AddressInUseException(string message, System.Exception inner) => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.BaseConnectionContext` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class BaseConnectionContext : System.IAsyncDisposable { public abstract void Abort(); @@ -28,7 +27,6 @@ namespace Microsoft public virtual System.Net.EndPoint RemoteEndPoint { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionAbortedException` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionAbortedException : System.OperationCanceledException { public ConnectionAbortedException() => throw null; @@ -36,7 +34,6 @@ namespace Microsoft public ConnectionAbortedException(string message, System.Exception inner) => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionBuilder` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionBuilder : Microsoft.AspNetCore.Connections.IConnectionBuilder { public System.IServiceProvider ApplicationServices { get => throw null; } @@ -45,7 +42,6 @@ namespace Microsoft public Microsoft.AspNetCore.Connections.IConnectionBuilder Use(System.Func middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionBuilderExtensions` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConnectionBuilderExtensions { public static Microsoft.AspNetCore.Connections.IConnectionBuilder Run(this Microsoft.AspNetCore.Connections.IConnectionBuilder connectionBuilder, System.Func middleware) => throw null; @@ -53,7 +49,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Connections.IConnectionBuilder UseConnectionHandler(this Microsoft.AspNetCore.Connections.IConnectionBuilder connectionBuilder) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionContext` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConnectionContext : Microsoft.AspNetCore.Connections.BaseConnectionContext, System.IAsyncDisposable { public override void Abort() => throw null; @@ -62,17 +57,14 @@ namespace Microsoft public abstract System.IO.Pipelines.IDuplexPipe Transport { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionDelegate` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task ConnectionDelegate(Microsoft.AspNetCore.Connections.ConnectionContext connection); - // Generated from `Microsoft.AspNetCore.Connections.ConnectionHandler` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConnectionHandler { protected ConnectionHandler() => throw null; public abstract System.Threading.Tasks.Task OnConnectedAsync(Microsoft.AspNetCore.Connections.ConnectionContext connection); } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionItems` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionItems : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -96,14 +88,12 @@ namespace Microsoft System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Connections.ConnectionResetException` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionResetException : System.IO.IOException { public ConnectionResetException(string message) => throw null; public ConnectionResetException(string message, System.Exception inner) => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.DefaultConnectionContext` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultConnectionContext : Microsoft.AspNetCore.Connections.ConnectionContext, Microsoft.AspNetCore.Connections.Features.IConnectionEndPointFeature, Microsoft.AspNetCore.Connections.Features.IConnectionIdFeature, Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature, Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature, Microsoft.AspNetCore.Connections.Features.IConnectionTransportFeature, Microsoft.AspNetCore.Connections.Features.IConnectionUserFeature { public override void Abort(Microsoft.AspNetCore.Connections.ConnectionAbortedException abortReason) => throw null; @@ -122,7 +112,6 @@ namespace Microsoft public System.Security.Claims.ClaimsPrincipal User { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Connections.FileHandleEndPoint` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileHandleEndPoint : System.Net.EndPoint { public System.UInt64 FileHandle { get => throw null; } @@ -130,7 +119,6 @@ namespace Microsoft public Microsoft.AspNetCore.Connections.FileHandleType FileHandleType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Connections.FileHandleType` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum FileHandleType : int { Auto = 0, @@ -138,7 +126,6 @@ namespace Microsoft Tcp = 1, } - // Generated from `Microsoft.AspNetCore.Connections.IConnectionBuilder` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionBuilder { System.IServiceProvider ApplicationServices { get; } @@ -146,13 +133,11 @@ namespace Microsoft Microsoft.AspNetCore.Connections.IConnectionBuilder Use(System.Func middleware); } - // Generated from `Microsoft.AspNetCore.Connections.IConnectionFactory` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionFactory { System.Threading.Tasks.ValueTask ConnectAsync(System.Net.EndPoint endpoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.IConnectionListener` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionListener : System.IAsyncDisposable { System.Threading.Tasks.ValueTask AcceptAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -160,13 +145,11 @@ namespace Microsoft System.Threading.Tasks.ValueTask UnbindAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.IConnectionListenerFactory` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionListenerFactory { System.Threading.Tasks.ValueTask BindAsync(System.Net.EndPoint endpoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMultiplexedConnectionBuilder { System.IServiceProvider ApplicationServices { get; } @@ -174,13 +157,11 @@ namespace Microsoft Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder Use(System.Func middleware); } - // Generated from `Microsoft.AspNetCore.Connections.IMultiplexedConnectionFactory` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMultiplexedConnectionFactory { System.Threading.Tasks.ValueTask ConnectAsync(System.Net.EndPoint endpoint, Microsoft.AspNetCore.Http.Features.IFeatureCollection features = default(Microsoft.AspNetCore.Http.Features.IFeatureCollection), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.IMultiplexedConnectionListener` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMultiplexedConnectionListener : System.IAsyncDisposable { System.Threading.Tasks.ValueTask AcceptAsync(Microsoft.AspNetCore.Http.Features.IFeatureCollection features = default(Microsoft.AspNetCore.Http.Features.IFeatureCollection), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -188,13 +169,11 @@ namespace Microsoft System.Threading.Tasks.ValueTask UnbindAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.IMultiplexedConnectionListenerFactory` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMultiplexedConnectionListenerFactory { System.Threading.Tasks.ValueTask BindAsync(System.Net.EndPoint endpoint, Microsoft.AspNetCore.Http.Features.IFeatureCollection features = default(Microsoft.AspNetCore.Http.Features.IFeatureCollection), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Connections.MultiplexedConnectionBuilder` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MultiplexedConnectionBuilder : Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder { public System.IServiceProvider ApplicationServices { get => throw null; } @@ -203,7 +182,6 @@ namespace Microsoft public Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder Use(System.Func middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.MultiplexedConnectionContext` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class MultiplexedConnectionContext : Microsoft.AspNetCore.Connections.BaseConnectionContext, System.IAsyncDisposable { public abstract System.Threading.Tasks.ValueTask AcceptAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -211,10 +189,24 @@ namespace Microsoft protected MultiplexedConnectionContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Connections.MultiplexedConnectionDelegate` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task MultiplexedConnectionDelegate(Microsoft.AspNetCore.Connections.MultiplexedConnectionContext connection); - // Generated from `Microsoft.AspNetCore.Connections.TransferFormat` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class TlsConnectionCallbackContext + { + public System.Net.Security.SslClientHelloInfo ClientHelloInfo { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Connections.BaseConnectionContext Connection { get => throw null; set => throw null; } + public object State { get => throw null; set => throw null; } + public TlsConnectionCallbackContext() => throw null; + } + + public class TlsConnectionCallbackOptions + { + public System.Collections.Generic.List ApplicationProtocols { get => throw null; set => throw null; } + public System.Func> OnConnection { get => throw null; set => throw null; } + public object OnConnectionState { get => throw null; set => throw null; } + public TlsConnectionCallbackOptions() => throw null; + } + [System.Flags] public enum TransferFormat : int { @@ -222,7 +214,6 @@ namespace Microsoft Text = 2, } - // Generated from `Microsoft.AspNetCore.Connections.UriEndPoint` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UriEndPoint : System.Net.EndPoint { public override string ToString() => throw null; @@ -232,114 +223,101 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionCompleteFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionCompleteFeature { void OnCompleted(System.Func callback, object state); } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionEndPointFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionEndPointFeature { System.Net.EndPoint LocalEndPoint { get; set; } System.Net.EndPoint RemoteEndPoint { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionHeartbeatFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionHeartbeatFeature { void OnHeartbeat(System.Action action, object state); } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionIdFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionIdFeature { string ConnectionId { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionInherentKeepAliveFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionInherentKeepAliveFeature { bool HasInherentKeepAlive { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionItemsFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionItemsFeature { System.Collections.Generic.IDictionary Items { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionLifetimeFeature { void Abort(); System.Threading.CancellationToken ConnectionClosed { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionLifetimeNotificationFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionLifetimeNotificationFeature { System.Threading.CancellationToken ConnectionClosedRequested { get; set; } void RequestClose(); } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionSocketFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionSocketFeature { System.Net.Sockets.Socket Socket { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionTransportFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionTransportFeature { System.IO.Pipelines.IDuplexPipe Transport { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IConnectionUserFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionUserFeature { System.Security.Claims.ClaimsPrincipal User { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IMemoryPoolFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMemoryPoolFeature { System.Buffers.MemoryPool MemoryPool { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IPersistentStateFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPersistentStateFeature { System.Collections.Generic.IDictionary State { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IProtocolErrorCodeFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IProtocolErrorCodeFeature { System.Int64 Error { get; set; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IStreamAbortFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStreamAbortFeature { void AbortRead(System.Int64 errorCode, Microsoft.AspNetCore.Connections.ConnectionAbortedException abortReason); void AbortWrite(System.Int64 errorCode, Microsoft.AspNetCore.Connections.ConnectionAbortedException abortReason); } - // Generated from `Microsoft.AspNetCore.Connections.Features.IStreamDirectionFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IStreamClosedFeature + { + void OnClosed(System.Action callback, object state); + } + public interface IStreamDirectionFeature { bool CanRead { get; } bool CanWrite { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.IStreamIdFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStreamIdFeature { System.Int64 StreamId { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.ITlsHandshakeFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITlsHandshakeFeature { System.Security.Authentication.CipherAlgorithmType CipherAlgorithm { get; } @@ -351,7 +329,6 @@ namespace Microsoft System.Security.Authentication.SslProtocols Protocol { get; } } - // Generated from `Microsoft.AspNetCore.Connections.Features.ITransferFormatFeature` in `Microsoft.AspNetCore.Connections.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITransferFormatFeature { Microsoft.AspNetCore.Connections.TransferFormat ActiveFormat { get; set; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.CookiePolicy.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.CookiePolicy.cs index c501847a681..79c0c7f33e9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.CookiePolicy.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.CookiePolicy.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.CookiePolicy, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,18 +7,17 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.CookiePolicyAppBuilderExtensions` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CookiePolicyAppBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCookiePolicy(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCookiePolicy(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.CookiePolicyOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.CookiePolicyOptions` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookiePolicyOptions { public System.Func CheckConsentNeeded { get => throw null; set => throw null; } public Microsoft.AspNetCore.Http.CookieBuilder ConsentCookie { get => throw null; set => throw null; } + public string ConsentCookieValue { get => throw null; set => throw null; } public CookiePolicyOptions() => throw null; public Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy HttpOnly { get => throw null; set => throw null; } public Microsoft.AspNetCore.Http.SameSiteMode MinimumSameSitePolicy { get => throw null; set => throw null; } @@ -29,7 +29,6 @@ namespace Microsoft } namespace CookiePolicy { - // Generated from `Microsoft.AspNetCore.CookiePolicy.AppendCookieContext` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AppendCookieContext { public AppendCookieContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.CookieOptions options, string name, string value) => throw null; @@ -42,7 +41,6 @@ namespace Microsoft public bool IssueCookie { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.CookiePolicy.CookiePolicyMiddleware` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookiePolicyMiddleware { public CookiePolicyMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options) => throw null; @@ -51,7 +49,6 @@ namespace Microsoft public Microsoft.AspNetCore.Builder.CookiePolicyOptions Options { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.CookiePolicy.DeleteCookieContext` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DeleteCookieContext { public Microsoft.AspNetCore.Http.HttpContext Context { get => throw null; } @@ -63,7 +60,6 @@ namespace Microsoft public bool IssueCookie { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HttpOnlyPolicy : int { Always = 1, @@ -76,7 +72,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.CookiePolicyServiceCollectionExtensions` in `Microsoft.AspNetCore.CookiePolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CookiePolicyServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddCookiePolicy(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cors.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cors.cs index ba7f530ee20..ff5767e49b8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cors.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cors.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Cors, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.CorsEndpointConventionBuilderExtensions` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CorsEndpointConventionBuilderExtensions { public static TBuilder RequireCors(this TBuilder builder, System.Action configurePolicy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static TBuilder RequireCors(this TBuilder builder, string policyName) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.CorsMiddlewareExtensions` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CorsMiddlewareExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCors(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -24,20 +23,17 @@ namespace Microsoft } namespace Cors { - // Generated from `Microsoft.AspNetCore.Cors.CorsPolicyMetadata` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsPolicyMetadata : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata, Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyMetadata { public CorsPolicyMetadata(Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy policy) => throw null; public Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy Policy { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Cors.DisableCorsAttribute` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DisableCorsAttribute : System.Attribute, Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata, Microsoft.AspNetCore.Cors.Infrastructure.IDisableCorsAttribute { public DisableCorsAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.EnableCorsAttribute` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnableCorsAttribute : System.Attribute, Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata, Microsoft.AspNetCore.Cors.Infrastructure.IEnableCorsAttribute { public EnableCorsAttribute() => throw null; @@ -47,7 +43,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsConstants` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CorsConstants { public static string AccessControlAllowCredentials; @@ -63,7 +58,6 @@ namespace Microsoft public static string PreflightHttpMethod; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsMiddleware` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsMiddleware { public CorsMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Cors.Infrastructure.ICorsService corsService, Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy policy, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; @@ -72,7 +66,6 @@ namespace Microsoft public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyProvider corsPolicyProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsOptions` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsOptions { public void AddDefaultPolicy(System.Action configurePolicy) => throw null; @@ -84,7 +77,6 @@ namespace Microsoft public Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy GetPolicy(string name) => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsPolicy { public bool AllowAnyHeader { get => throw null; } @@ -101,7 +93,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsPolicyBuilder { public Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder AllowAnyHeader() => throw null; @@ -121,7 +112,6 @@ namespace Microsoft public Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicyBuilder WithOrigins(params string[] origins) => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsResult` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsResult { public System.Collections.Generic.IList AllowedExposedHeaders { get => throw null; } @@ -137,7 +127,6 @@ namespace Microsoft public bool VaryByOrigin { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.CorsService` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsService : Microsoft.AspNetCore.Cors.Infrastructure.ICorsService { public virtual void ApplyResult(Microsoft.AspNetCore.Cors.Infrastructure.CorsResult result, Microsoft.AspNetCore.Http.HttpResponse response) => throw null; @@ -148,38 +137,32 @@ namespace Microsoft public virtual void EvaluateRequest(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy policy, Microsoft.AspNetCore.Cors.Infrastructure.CorsResult result) => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.DefaultCorsPolicyProvider` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultCorsPolicyProvider : Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyProvider { public DefaultCorsPolicyProvider(Microsoft.Extensions.Options.IOptions options) => throw null; public System.Threading.Tasks.Task GetPolicyAsync(Microsoft.AspNetCore.Http.HttpContext context, string policyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyMetadata` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICorsPolicyMetadata : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata { Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy Policy { get; } } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyProvider` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICorsPolicyProvider { System.Threading.Tasks.Task GetPolicyAsync(Microsoft.AspNetCore.Http.HttpContext context, string policyName); } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.ICorsService` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICorsService { void ApplyResult(Microsoft.AspNetCore.Cors.Infrastructure.CorsResult result, Microsoft.AspNetCore.Http.HttpResponse response); Microsoft.AspNetCore.Cors.Infrastructure.CorsResult EvaluatePolicy(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Cors.Infrastructure.CorsPolicy policy); } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.IDisableCorsAttribute` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDisableCorsAttribute : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata { } - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.IEnableCorsAttribute` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEnableCorsAttribute : Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata { string PolicyName { get; set; } @@ -192,7 +175,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.CorsServiceCollectionExtensions` in `Microsoft.AspNetCore.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CorsServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddCors(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cryptography.KeyDerivation.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cryptography.KeyDerivation.cs index caf6639e24b..ec08c360049 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cryptography.KeyDerivation.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Cryptography.KeyDerivation.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Cryptography.KeyDerivation, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,13 +9,11 @@ namespace Microsoft { namespace KeyDerivation { - // Generated from `Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivation` in `Microsoft.AspNetCore.Cryptography.KeyDerivation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class KeyDerivation { public static System.Byte[] Pbkdf2(string password, System.Byte[] salt, Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivationPrf prf, int iterationCount, int numBytesRequested) => throw null; } - // Generated from `Microsoft.AspNetCore.Cryptography.KeyDerivation.KeyDerivationPrf` in `Microsoft.AspNetCore.Cryptography.KeyDerivation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum KeyDerivationPrf : int { HMACSHA1 = 0, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Abstractions.cs index e2f17cad601..4b0d1c2e0aa 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.DataProtection.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DataProtection { - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionCommonExtensions` in `Microsoft.AspNetCore.DataProtection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionCommonExtensions { public static Microsoft.AspNetCore.DataProtection.IDataProtector CreateProtector(this Microsoft.AspNetCore.DataProtection.IDataProtectionProvider provider, System.Collections.Generic.IEnumerable purposes) => throw null; @@ -18,13 +18,11 @@ namespace Microsoft public static string Unprotect(this Microsoft.AspNetCore.DataProtection.IDataProtector protector, string protectedData) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.IDataProtectionProvider` in `Microsoft.AspNetCore.DataProtection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDataProtectionProvider { Microsoft.AspNetCore.DataProtection.IDataProtector CreateProtector(string purpose); } - // Generated from `Microsoft.AspNetCore.DataProtection.IDataProtector` in `Microsoft.AspNetCore.DataProtection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDataProtector : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider { System.Byte[] Protect(System.Byte[] plaintext); @@ -33,7 +31,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.DataProtection.Infrastructure.IApplicationDiscriminator` in `Microsoft.AspNetCore.DataProtection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationDiscriminator { string Discriminator { get; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Extensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Extensions.cs index 62449e4a545..8af2af938a4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Extensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.Extensions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.DataProtection.Extensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DataProtection { - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionAdvancedExtensions` in `Microsoft.AspNetCore.DataProtection.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionAdvancedExtensions { public static System.Byte[] Protect(this Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector protector, System.Byte[] plaintext, System.TimeSpan lifetime) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public static string Unprotect(this Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector protector, string protectedData, out System.DateTimeOffset expiration) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionProvider` in `Microsoft.AspNetCore.DataProtection.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionProvider { public static Microsoft.AspNetCore.DataProtection.IDataProtectionProvider Create(System.IO.DirectoryInfo keyDirectory) => throw null; @@ -27,7 +26,6 @@ namespace Microsoft public static Microsoft.AspNetCore.DataProtection.IDataProtectionProvider Create(string applicationName, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector` in `Microsoft.AspNetCore.DataProtection.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITimeLimitedDataProtector : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider, Microsoft.AspNetCore.DataProtection.IDataProtector { Microsoft.AspNetCore.DataProtection.ITimeLimitedDataProtector CreateProtector(string purpose); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.cs index 612d9b5b68a..7f59a478870 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.DataProtection.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.DataProtection, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DataProtection { - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionBuilderExtensions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionBuilderExtensions { public static Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder AddKeyEscrowSink(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder builder, System.Func factory) => throw null; @@ -32,20 +32,17 @@ namespace Microsoft public static Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder UseEphemeralDataProtectionProvider(this Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder builder) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionOptions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataProtectionOptions { public string ApplicationDiscriminator { get => throw null; set => throw null; } public DataProtectionOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.DataProtectionUtilityExtensions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionUtilityExtensions { public static string GetApplicationUniqueIdentifier(this System.IServiceProvider services) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.EphemeralDataProtectionProvider` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EphemeralDataProtectionProvider : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider { public Microsoft.AspNetCore.DataProtection.IDataProtector CreateProtector(string purpose) => throw null; @@ -53,26 +50,22 @@ namespace Microsoft public EphemeralDataProtectionProvider(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDataProtectionBuilder { Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } - // Generated from `Microsoft.AspNetCore.DataProtection.IPersistedDataProtector` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPersistedDataProtector : Microsoft.AspNetCore.DataProtection.IDataProtectionProvider, Microsoft.AspNetCore.DataProtection.IDataProtector { System.Byte[] DangerousUnprotect(System.Byte[] protectedData, bool ignoreRevocationErrors, out bool requiresMigration, out bool wasRevoked); } - // Generated from `Microsoft.AspNetCore.DataProtection.ISecret` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISecret : System.IDisposable { int Length { get; } void WriteSecretIntoBuffer(System.ArraySegment buffer); } - // Generated from `Microsoft.AspNetCore.DataProtection.Secret` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Secret : Microsoft.AspNetCore.DataProtection.ISecret, System.IDisposable { public void Dispose() => throw null; @@ -88,28 +81,24 @@ namespace Microsoft namespace AuthenticatedEncryption { - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.AuthenticatedEncryptorFactory` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticatedEncryptorFactory : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory { public AuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey key) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngCbcAuthenticatedEncryptorFactory` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngCbcAuthenticatedEncryptorFactory : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory { public CngCbcAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey key) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.CngGcmAuthenticatedEncryptorFactory` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngGcmAuthenticatedEncryptorFactory : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory { public CngGcmAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey key) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.EncryptionAlgorithm` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum EncryptionAlgorithm : int { AES_128_CBC = 0, @@ -120,27 +109,23 @@ namespace Microsoft AES_256_GCM = 5, } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticatedEncryptor { System.Byte[] Decrypt(System.ArraySegment ciphertext, System.ArraySegment additionalAuthenticatedData); System.Byte[] Encrypt(System.ArraySegment plaintext, System.ArraySegment additionalAuthenticatedData); } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticatedEncryptorFactory { Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey key); } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ManagedAuthenticatedEncryptorFactory` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ManagedAuthenticatedEncryptorFactory : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptorFactory { public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor CreateEncryptorInstance(Microsoft.AspNetCore.DataProtection.KeyManagement.IKey key) => throw null; public ManagedAuthenticatedEncryptorFactory(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ValidationAlgorithm : int { HMACSHA256 = 0, @@ -149,14 +134,12 @@ namespace Microsoft namespace ConfigurationModel { - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AlgorithmConfiguration { protected AlgorithmConfiguration() => throw null; public abstract Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor CreateNewDescriptor(); } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticatedEncryptorConfiguration : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration { public AuthenticatedEncryptorConfiguration() => throw null; @@ -165,21 +148,18 @@ namespace Microsoft public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ValidationAlgorithm ValidationAlgorithm { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticatedEncryptorDescriptor : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor { public AuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorConfiguration configuration, Microsoft.AspNetCore.DataProtection.ISecret masterKey) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo ExportToXml() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AuthenticatedEncryptorDescriptorDeserializer` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticatedEncryptorDescriptorDeserializer : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer { public AuthenticatedEncryptorDescriptorDeserializer() => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor ImportFromXml(System.Xml.Linq.XElement element) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngCbcAuthenticatedEncryptorConfiguration : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration { public CngCbcAuthenticatedEncryptorConfiguration() => throw null; @@ -191,21 +171,18 @@ namespace Microsoft public string HashAlgorithmProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngCbcAuthenticatedEncryptorDescriptor : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor { public CngCbcAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorConfiguration configuration, Microsoft.AspNetCore.DataProtection.ISecret masterKey) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo ExportToXml() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngCbcAuthenticatedEncryptorDescriptorDeserializer` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngCbcAuthenticatedEncryptorDescriptorDeserializer : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer { public CngCbcAuthenticatedEncryptorDescriptorDeserializer() => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor ImportFromXml(System.Xml.Linq.XElement element) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngGcmAuthenticatedEncryptorConfiguration : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration { public CngGcmAuthenticatedEncryptorConfiguration() => throw null; @@ -215,38 +192,32 @@ namespace Microsoft public string EncryptionAlgorithmProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngGcmAuthenticatedEncryptorDescriptor : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor { public CngGcmAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorConfiguration configuration, Microsoft.AspNetCore.DataProtection.ISecret masterKey) => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo ExportToXml() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.CngGcmAuthenticatedEncryptorDescriptorDeserializer` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CngGcmAuthenticatedEncryptorDescriptorDeserializer : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer { public CngGcmAuthenticatedEncryptorDescriptorDeserializer() => throw null; public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor ImportFromXml(System.Xml.Linq.XElement element) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticatedEncryptorDescriptor { Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo ExportToXml(); } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthenticatedEncryptorDescriptorDeserializer { Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor ImportFromXml(System.Xml.Linq.XElement element); } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IInternalAlgorithmConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IInternalAlgorithmConfiguration { } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ManagedAuthenticatedEncryptorConfiguration : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration { public override Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor CreateNewDescriptor() => throw null; @@ -256,27 +227,23 @@ namespace Microsoft public System.Type ValidationAlgorithmType { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ManagedAuthenticatedEncryptorDescriptor : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor { public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo ExportToXml() => throw null; public ManagedAuthenticatedEncryptorDescriptor(Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorConfiguration configuration, Microsoft.AspNetCore.DataProtection.ISecret masterKey) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.ManagedAuthenticatedEncryptorDescriptorDeserializer` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ManagedAuthenticatedEncryptorDescriptorDeserializer : Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptorDeserializer { public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.IAuthenticatedEncryptorDescriptor ImportFromXml(System.Xml.Linq.XElement element) => throw null; public ManagedAuthenticatedEncryptorDescriptorDeserializer() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlExtensions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class XmlExtensions { public static void MarkAsRequiresEncryption(this System.Xml.Linq.XElement element) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.XmlSerializedDescriptorInfo` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlSerializedDescriptorInfo { public System.Type DeserializerType { get => throw null; } @@ -288,7 +255,6 @@ namespace Microsoft } namespace Internal { - // Generated from `Microsoft.AspNetCore.DataProtection.Internal.IActivator` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActivator { object CreateInstance(System.Type expectedBaseType, string implementationTypeName); @@ -297,7 +263,6 @@ namespace Microsoft } namespace KeyManagement { - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.IKey` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKey { System.DateTimeOffset ActivationDate { get; } @@ -309,13 +274,11 @@ namespace Microsoft System.Guid KeyId { get; } } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyEscrowSink` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeyEscrowSink { void Store(System.Guid keyId, System.Xml.Linq.XElement element); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeyManager { Microsoft.AspNetCore.DataProtection.KeyManagement.IKey CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate); @@ -325,7 +288,6 @@ namespace Microsoft void RevokeKey(System.Guid keyId, string reason = default(string)); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.KeyManagementOptions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyManagementOptions { public Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.ConfigurationModel.AlgorithmConfiguration AuthenticatedEncryptorConfiguration { get => throw null; set => throw null; } @@ -338,7 +300,6 @@ namespace Microsoft public Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository XmlRepository { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlKeyManager : Microsoft.AspNetCore.DataProtection.KeyManagement.IKeyManager, Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager { public Microsoft.AspNetCore.DataProtection.KeyManagement.IKey CreateNewKey(System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate) => throw null; @@ -355,12 +316,10 @@ namespace Microsoft namespace Internal { - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheableKeyRing { } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct DefaultKeyResolution { public Microsoft.AspNetCore.DataProtection.KeyManagement.IKey DefaultKey; @@ -369,19 +328,16 @@ namespace Microsoft public bool ShouldGenerateNewKey; } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.ICacheableKeyRingProvider` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICacheableKeyRingProvider { Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.CacheableKeyRing GetCacheableKeyRing(System.DateTimeOffset now); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IDefaultKeyResolver` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDefaultKeyResolver { Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.DefaultKeyResolution ResolveDefaultKeyPolicy(System.DateTimeOffset now, System.Collections.Generic.IEnumerable allKeys); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IInternalXmlKeyManager` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IInternalXmlKeyManager { Microsoft.AspNetCore.DataProtection.KeyManagement.IKey CreateNewKey(System.Guid keyId, System.DateTimeOffset creationDate, System.DateTimeOffset activationDate, System.DateTimeOffset expirationDate); @@ -389,7 +345,6 @@ namespace Microsoft void RevokeSingleKey(System.Guid keyId, System.DateTimeOffset revocationDate, string reason); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeyRing { Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor DefaultAuthenticatedEncryptor { get; } @@ -397,7 +352,6 @@ namespace Microsoft Microsoft.AspNetCore.DataProtection.AuthenticatedEncryption.IAuthenticatedEncryptor GetAuthenticatedEncryptorByKeyId(System.Guid keyId, out bool isRevoked); } - // Generated from `Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRingProvider` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeyRingProvider { Microsoft.AspNetCore.DataProtection.KeyManagement.Internal.IKeyRing GetCurrentKeyRing(); @@ -407,7 +361,6 @@ namespace Microsoft } namespace Repositories { - // Generated from `Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileSystemXmlRepository : Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository { public static System.IO.DirectoryInfo DefaultKeyStorageDirectory { get => throw null; } @@ -417,14 +370,12 @@ namespace Microsoft public virtual void StoreElement(System.Xml.Linq.XElement element, string friendlyName) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IXmlRepository { System.Collections.Generic.IReadOnlyCollection GetAllElements(); void StoreElement(System.Xml.Linq.XElement element, string friendlyName); } - // Generated from `Microsoft.AspNetCore.DataProtection.Repositories.RegistryXmlRepository` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RegistryXmlRepository : Microsoft.AspNetCore.DataProtection.Repositories.IXmlRepository { public static Microsoft.Win32.RegistryKey DefaultRegistryKey { get => throw null; } @@ -437,14 +388,12 @@ namespace Microsoft } namespace XmlEncryption { - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateResolver` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CertificateResolver : Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver { public CertificateResolver() => throw null; public virtual System.Security.Cryptography.X509Certificates.X509Certificate2 ResolveCertificate(string thumbprint) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.CertificateXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CertificateXmlEncryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor { public CertificateXmlEncryptor(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; @@ -452,7 +401,6 @@ namespace Microsoft public Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo Encrypt(System.Xml.Linq.XElement plaintextElement) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum DpapiNGProtectionDescriptorFlags : int { @@ -461,7 +409,6 @@ namespace Microsoft None = 0, } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DpapiNGXmlDecryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor { public System.Xml.Linq.XElement Decrypt(System.Xml.Linq.XElement encryptedElement) => throw null; @@ -469,14 +416,12 @@ namespace Microsoft public DpapiNGXmlDecryptor(System.IServiceProvider services) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DpapiNGXmlEncryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor { public DpapiNGXmlEncryptor(string protectionDescriptorRule, Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiNGProtectionDescriptorFlags flags, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo Encrypt(System.Xml.Linq.XElement plaintextElement) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DpapiXmlDecryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor { public System.Xml.Linq.XElement Decrypt(System.Xml.Linq.XElement encryptedElement) => throw null; @@ -484,14 +429,12 @@ namespace Microsoft public DpapiXmlDecryptor(System.IServiceProvider services) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.DpapiXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DpapiXmlEncryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor { public DpapiXmlEncryptor(bool protectToLocalMachine, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo Encrypt(System.Xml.Linq.XElement plaintextElement) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EncryptedXmlDecryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor { public System.Xml.Linq.XElement Decrypt(System.Xml.Linq.XElement encryptedElement) => throw null; @@ -499,7 +442,6 @@ namespace Microsoft public EncryptedXmlDecryptor(System.IServiceProvider services) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EncryptedXmlInfo { public System.Type DecryptorType { get => throw null; } @@ -507,42 +449,35 @@ namespace Microsoft public EncryptedXmlInfo(System.Xml.Linq.XElement encryptedElement, System.Type decryptorType) => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.ICertificateResolver` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICertificateResolver { System.Security.Cryptography.X509Certificates.X509Certificate2 ResolveCertificate(string thumbprint); } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.IInternalCertificateXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IInternalCertificateXmlEncryptor { } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.IInternalEncryptedXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IInternalEncryptedXmlDecryptor { } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IXmlDecryptor { System.Xml.Linq.XElement Decrypt(System.Xml.Linq.XElement encryptedElement); } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IXmlEncryptor { Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo Encrypt(System.Xml.Linq.XElement plaintextElement); } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlDecryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullXmlDecryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlDecryptor { public System.Xml.Linq.XElement Decrypt(System.Xml.Linq.XElement encryptedElement) => throw null; public NullXmlDecryptor() => throw null; } - // Generated from `Microsoft.AspNetCore.DataProtection.XmlEncryption.NullXmlEncryptor` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullXmlEncryptor : Microsoft.AspNetCore.DataProtection.XmlEncryption.IXmlEncryptor { public Microsoft.AspNetCore.DataProtection.XmlEncryption.EncryptedXmlInfo Encrypt(System.Xml.Linq.XElement plaintextElement) => throw null; @@ -557,7 +492,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.DataProtectionServiceCollectionExtensions` in `Microsoft.AspNetCore.DataProtection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DataProtectionServiceCollectionExtensions { public static Microsoft.AspNetCore.DataProtection.IDataProtectionBuilder AddDataProtection(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.Abstractions.cs index 2d7acb4a851..a9a42cc87ac 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Diagnostics.CompilationFailure` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompilationFailure { public CompilationFailure(string sourceFilePath, string sourceFileContent, string compiledContent, System.Collections.Generic.IEnumerable messages) => throw null; @@ -18,7 +18,6 @@ namespace Microsoft public string SourceFilePath { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.DiagnosticMessage` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DiagnosticMessage { public DiagnosticMessage(string message, string formattedMessage, string filePath, int startLine, int startColumn, int endLine, int endColumn) => throw null; @@ -31,7 +30,6 @@ namespace Microsoft public int StartLine { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.ErrorContext` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ErrorContext { public ErrorContext(Microsoft.AspNetCore.Http.HttpContext httpContext, System.Exception exception) => throw null; @@ -39,19 +37,16 @@ namespace Microsoft public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.ICompilationException` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompilationException { System.Collections.Generic.IEnumerable CompilationFailures { get; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.IDeveloperPageExceptionFilter` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDeveloperPageExceptionFilter { System.Threading.Tasks.Task HandleExceptionAsync(Microsoft.AspNetCore.Diagnostics.ErrorContext errorContext, System.Func next); } - // Generated from `Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IExceptionHandlerFeature { Microsoft.AspNetCore.Http.Endpoint Endpoint { get => throw null; } @@ -60,24 +55,23 @@ namespace Microsoft Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IExceptionHandlerPathFeature : Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature { string Path { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStatusCodePagesFeature { bool Enabled { get; set; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature` in `Microsoft.AspNetCore.Diagnostics.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStatusCodeReExecuteFeature { + Microsoft.AspNetCore.Http.Endpoint Endpoint { get => throw null; } string OriginalPath { get; set; } string OriginalPathBase { get; set; } string OriginalQueryString { get; set; } + Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.HealthChecks.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.HealthChecks.cs index 9845836f809..72e2ff634ce 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.HealthChecks.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.HealthChecks.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.HealthCheckApplicationBuilderExtensions` in `Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HealthCheckApplicationBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHealthChecks(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString path) => throw null; @@ -17,7 +17,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHealthChecks(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString path, string port, Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HealthCheckEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HealthCheckEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapHealthChecks(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) => throw null; @@ -29,14 +28,12 @@ namespace Microsoft { namespace HealthChecks { - // Generated from `Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckMiddleware` in `Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckMiddleware { public HealthCheckMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions healthCheckOptions, Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService healthCheckService) => throw null; public System.Threading.Tasks.Task InvokeAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.HealthChecks.HealthCheckOptions` in `Microsoft.AspNetCore.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckOptions { public bool AllowCachingResponses { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.cs index d06344f10dd..25407c6d530 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Diagnostics.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Diagnostics, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.DeveloperExceptionPageExtensions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DeveloperExceptionPageExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDeveloperExceptionPage(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDeveloperExceptionPage(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.DeveloperExceptionPageOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.DeveloperExceptionPageOptions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DeveloperExceptionPageOptions { public DeveloperExceptionPageOptions() => throw null; @@ -21,7 +20,6 @@ namespace Microsoft public int SourceCodeLineCount { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.ExceptionHandlerExtensions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ExceptionHandlerExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseExceptionHandler(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -30,7 +28,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseExceptionHandler(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string errorHandlingPath) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ExceptionHandlerOptions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExceptionHandlerOptions { public bool AllowStatusCode404Response { get => throw null; set => throw null; } @@ -39,7 +36,6 @@ namespace Microsoft public Microsoft.AspNetCore.Http.PathString ExceptionHandlingPath { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.StatusCodePagesExtensions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StatusCodePagesExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseStatusCodePages(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -51,14 +47,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseStatusCodePagesWithRedirects(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string locationFormat) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.StatusCodePagesOptions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodePagesOptions { public System.Func HandleAsync { get => throw null; set => throw null; } public StatusCodePagesOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.WelcomePageExtensions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WelcomePageExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseWelcomePage(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -67,7 +61,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseWelcomePage(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string path) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.WelcomePageOptions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WelcomePageOptions { public Microsoft.AspNetCore.Http.PathString Path { get => throw null; set => throw null; } @@ -77,14 +70,12 @@ namespace Microsoft } namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DeveloperExceptionPageMiddleware { public DeveloperExceptionPageMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment, System.Diagnostics.DiagnosticSource diagnosticSource, System.Collections.Generic.IEnumerable filters) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.ExceptionHandlerFeature` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExceptionHandlerFeature : Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature, Microsoft.AspNetCore.Diagnostics.IExceptionHandlerPathFeature { public Microsoft.AspNetCore.Http.Endpoint Endpoint { get => throw null; set => throw null; } @@ -94,14 +85,12 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExceptionHandlerMiddleware { public ExceptionHandlerMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions options, System.Diagnostics.DiagnosticListener diagnosticListener) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.StatusCodeContext` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodeContext { public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; } @@ -110,30 +99,28 @@ namespace Microsoft public StatusCodeContext(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Builder.StatusCodePagesOptions options, Microsoft.AspNetCore.Http.RequestDelegate next) => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.StatusCodePagesFeature` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodePagesFeature : Microsoft.AspNetCore.Diagnostics.IStatusCodePagesFeature { public bool Enabled { get => throw null; set => throw null; } public StatusCodePagesFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodePagesMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public StatusCodePagesMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.StatusCodeReExecuteFeature` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodeReExecuteFeature : Microsoft.AspNetCore.Diagnostics.IStatusCodeReExecuteFeature { + public Microsoft.AspNetCore.Http.Endpoint Endpoint { get => throw null; set => throw null; } public string OriginalPath { get => throw null; set => throw null; } public string OriginalPathBase { get => throw null; set => throw null; } public string OriginalQueryString { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; set => throw null; } public StatusCodeReExecuteFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Diagnostics.WelcomePageMiddleware` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WelcomePageMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -146,7 +133,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ExceptionHandlerServiceCollectionExtensions` in `Microsoft.AspNetCore.Diagnostics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ExceptionHandlerServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddExceptionHandler(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HostFiltering.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HostFiltering.cs index 72b7c96346f..88f68a97857 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HostFiltering.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HostFiltering.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.HostFiltering, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,11 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.HostFilteringBuilderExtensions` in `Microsoft.AspNetCore.HostFiltering, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostFilteringBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHostFiltering(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HostFilteringServicesExtensions` in `Microsoft.AspNetCore.HostFiltering, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostFilteringServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHostFiltering(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; @@ -21,14 +20,12 @@ namespace Microsoft } namespace HostFiltering { - // Generated from `Microsoft.AspNetCore.HostFiltering.HostFilteringMiddleware` in `Microsoft.AspNetCore.HostFiltering, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostFilteringMiddleware { public HostFilteringMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILogger logger, Microsoft.Extensions.Options.IOptionsMonitor optionsMonitor) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.HostFiltering.HostFilteringOptions` in `Microsoft.AspNetCore.HostFiltering, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostFilteringOptions { public bool AllowEmptyHosts { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Abstractions.cs index 0080e0b8d85..104755283a9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Hosting.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.EnvironmentName` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EnvironmentName { public static string Development; @@ -14,7 +14,6 @@ namespace Microsoft public static string Staging; } - // Generated from `Microsoft.AspNetCore.Hosting.HostingAbstractionsWebHostBuilderExtensions` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostingAbstractionsWebHostBuilderExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder CaptureStartupErrors(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder, bool captureStartupErrors) => throw null; @@ -31,7 +30,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseWebRoot(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder, string webRoot) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.HostingEnvironmentExtensions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class HostingEnvironmentExtensions { public static bool IsDevelopment(this Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment) => throw null; @@ -40,14 +38,12 @@ namespace Microsoft public static bool IsStaging(this Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.HostingStartupAttribute` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostingStartupAttribute : System.Attribute { public HostingStartupAttribute(System.Type hostingStartupType) => throw null; public System.Type HostingStartupType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Hosting.IApplicationLifetime` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationLifetime { System.Threading.CancellationToken ApplicationStarted { get; } @@ -56,7 +52,6 @@ namespace Microsoft void StopApplication(); } - // Generated from `Microsoft.AspNetCore.Hosting.IHostingEnvironment` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostingEnvironment { string ApplicationName { get; set; } @@ -67,38 +62,32 @@ namespace Microsoft string WebRootPath { get; set; } } - // Generated from `Microsoft.AspNetCore.Hosting.IHostingStartup` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostingStartup { void Configure(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder); } - // Generated from `Microsoft.AspNetCore.Hosting.IStartup` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStartup { void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app); System.IServiceProvider ConfigureServices(Microsoft.Extensions.DependencyInjection.IServiceCollection services); } - // Generated from `Microsoft.AspNetCore.Hosting.IStartupConfigureContainerFilter<>` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStartupConfigureContainerFilter { System.Action ConfigureContainer(System.Action container); } - // Generated from `Microsoft.AspNetCore.Hosting.IStartupConfigureServicesFilter` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStartupConfigureServicesFilter { System.Action ConfigureServices(System.Action next); } - // Generated from `Microsoft.AspNetCore.Hosting.IStartupFilter` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStartupFilter { System.Action Configure(System.Action next); } - // Generated from `Microsoft.AspNetCore.Hosting.IWebHost` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IWebHost : System.IDisposable { Microsoft.AspNetCore.Http.Features.IFeatureCollection ServerFeatures { get; } @@ -108,7 +97,6 @@ namespace Microsoft System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Hosting.IWebHostBuilder` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IWebHostBuilder { Microsoft.AspNetCore.Hosting.IWebHost Build(); @@ -119,14 +107,12 @@ namespace Microsoft Microsoft.AspNetCore.Hosting.IWebHostBuilder UseSetting(string key, string value); } - // Generated from `Microsoft.AspNetCore.Hosting.IWebHostEnvironment` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IWebHostEnvironment : Microsoft.Extensions.Hosting.IHostEnvironment { Microsoft.Extensions.FileProviders.IFileProvider WebRootFileProvider { get; set; } string WebRootPath { get; set; } } - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderContext` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebHostBuilderContext { public Microsoft.Extensions.Configuration.IConfiguration Configuration { get => throw null; set => throw null; } @@ -134,7 +120,6 @@ namespace Microsoft public WebHostBuilderContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.WebHostDefaults` in `Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostDefaults { public static string ApplicationKey; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Server.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Server.Abstractions.cs index 9c74a9e64af..7360c39d570 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Server.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.Server.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Server { - // Generated from `Microsoft.AspNetCore.Hosting.Server.IHttpApplication<>` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpApplication { TContext CreateContext(Microsoft.AspNetCore.Http.Features.IFeatureCollection contextFeatures); @@ -16,7 +16,6 @@ namespace Microsoft System.Threading.Tasks.Task ProcessRequestAsync(TContext context); } - // Generated from `Microsoft.AspNetCore.Hosting.Server.IServer` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServer : System.IDisposable { Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get; } @@ -24,14 +23,12 @@ namespace Microsoft System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Hosting.Server.IServerIntegratedAuth` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServerIntegratedAuth { string AuthenticationScheme { get; } bool IsEnabled { get; } } - // Generated from `Microsoft.AspNetCore.Hosting.Server.ServerIntegratedAuth` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServerIntegratedAuth : Microsoft.AspNetCore.Hosting.Server.IServerIntegratedAuth { public string AuthenticationScheme { get => throw null; set => throw null; } @@ -41,7 +38,6 @@ namespace Microsoft namespace Abstractions { - // Generated from `Microsoft.AspNetCore.Hosting.Server.Abstractions.IHostContextContainer<>` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostContextContainer { TContext HostContext { get; set; } @@ -50,7 +46,6 @@ namespace Microsoft } namespace Features { - // Generated from `Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature` in `Microsoft.AspNetCore.Hosting.Server.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServerAddressesFeature { System.Collections.Generic.ICollection Addresses { get; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.cs index e20d5d3885a..628fe2725a4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Hosting.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Hosting, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,19 +7,16 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.DelegateStartup` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DelegateStartup : Microsoft.AspNetCore.Hosting.StartupBase { public override void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; public DelegateStartup(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory, System.Action configureApp) : base(default(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory)) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.HostingEnvironmentExtensions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class HostingEnvironmentExtensions { } - // Generated from `Microsoft.AspNetCore.Hosting.StartupBase` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class StartupBase : Microsoft.AspNetCore.Hosting.IStartup { public abstract void Configure(Microsoft.AspNetCore.Builder.IApplicationBuilder app); @@ -28,7 +26,6 @@ namespace Microsoft protected StartupBase() => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.StartupBase<>` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class StartupBase : Microsoft.AspNetCore.Hosting.StartupBase { public virtual void ConfigureContainer(TBuilder builder) => throw null; @@ -36,7 +33,6 @@ namespace Microsoft public StartupBase(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilder` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebHostBuilder : Microsoft.AspNetCore.Hosting.IWebHostBuilder { public Microsoft.AspNetCore.Hosting.IWebHost Build() => throw null; @@ -48,7 +44,6 @@ namespace Microsoft public WebHostBuilder() => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderExtensions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostBuilderExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder Configure(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder, System.Action configureApp) => throw null; @@ -64,7 +59,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseStaticWebAssets(this Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.WebHostExtensions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostExtensions { public static void Run(this Microsoft.AspNetCore.Hosting.IWebHost host) => throw null; @@ -76,14 +70,12 @@ namespace Microsoft namespace Builder { - // Generated from `Microsoft.AspNetCore.Hosting.Builder.ApplicationBuilderFactory` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationBuilderFactory : Microsoft.AspNetCore.Hosting.Builder.IApplicationBuilderFactory { public ApplicationBuilderFactory(System.IServiceProvider serviceProvider) => throw null; public Microsoft.AspNetCore.Builder.IApplicationBuilder CreateBuilder(Microsoft.AspNetCore.Http.Features.IFeatureCollection serverFeatures) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.Builder.IApplicationBuilderFactory` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationBuilderFactory { Microsoft.AspNetCore.Builder.IApplicationBuilder CreateBuilder(Microsoft.AspNetCore.Http.Features.IFeatureCollection serverFeatures); @@ -92,13 +84,11 @@ namespace Microsoft } namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Hosting.Infrastructure.ISupportsConfigureWebHost` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISupportsConfigureWebHost { Microsoft.Extensions.Hosting.IHostBuilder ConfigureWebHost(System.Action configure, System.Action configureOptions); } - // Generated from `Microsoft.AspNetCore.Hosting.Infrastructure.ISupportsStartup` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISupportsStartup { Microsoft.AspNetCore.Hosting.IWebHostBuilder Configure(System.Action configure); @@ -112,7 +102,6 @@ namespace Microsoft { namespace Features { - // Generated from `Microsoft.AspNetCore.Hosting.Server.Features.ServerAddressesFeature` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServerAddressesFeature : Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature { public System.Collections.Generic.ICollection Addresses { get => throw null; } @@ -124,7 +113,6 @@ namespace Microsoft } namespace StaticWebAssets { - // Generated from `Microsoft.AspNetCore.Hosting.StaticWebAssets.StaticWebAssetsLoader` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StaticWebAssetsLoader { public StaticWebAssetsLoader() => throw null; @@ -135,7 +123,6 @@ namespace Microsoft } namespace Http { - // Generated from `Microsoft.AspNetCore.Http.DefaultHttpContextFactory` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultHttpContextFactory : Microsoft.AspNetCore.Http.IHttpContextFactory { public Microsoft.AspNetCore.Http.HttpContext Create(Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection) => throw null; @@ -149,14 +136,12 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.Extensions.Hosting.GenericHostWebHostBuilderExtensions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class GenericHostWebHostBuilderExtensions { public static Microsoft.Extensions.Hosting.IHostBuilder ConfigureWebHost(this Microsoft.Extensions.Hosting.IHostBuilder builder, System.Action configure) => throw null; public static Microsoft.Extensions.Hosting.IHostBuilder ConfigureWebHost(this Microsoft.Extensions.Hosting.IHostBuilder builder, System.Action configure, System.Action configureWebHostBuilder) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.WebHostBuilderOptions` in `Microsoft.AspNetCore.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebHostBuilderOptions { public bool SuppressEnvironmentConfiguration { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Html.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Html.Abstractions.cs index d86ae3897ef..f645b2a4f44 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Html.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Html.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Html.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Html { - // Generated from `Microsoft.AspNetCore.Html.HtmlContentBuilder` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlContentBuilder : Microsoft.AspNetCore.Html.IHtmlContent, Microsoft.AspNetCore.Html.IHtmlContentBuilder, Microsoft.AspNetCore.Html.IHtmlContentContainer { public Microsoft.AspNetCore.Html.IHtmlContentBuilder Append(string unencoded) => throw null; @@ -22,7 +22,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Html.HtmlContentBuilderExtensions` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlContentBuilderExtensions { public static Microsoft.AspNetCore.Html.IHtmlContentBuilder AppendFormat(this Microsoft.AspNetCore.Html.IHtmlContentBuilder builder, System.IFormatProvider formatProvider, string format, params object[] args) => throw null; @@ -36,7 +35,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContentBuilder SetHtmlContent(this Microsoft.AspNetCore.Html.IHtmlContentBuilder builder, string encoded) => throw null; } - // Generated from `Microsoft.AspNetCore.Html.HtmlFormattableString` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlFormattableString : Microsoft.AspNetCore.Html.IHtmlContent { public HtmlFormattableString(System.IFormatProvider formatProvider, string format, params object[] args) => throw null; @@ -44,7 +42,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Html.HtmlString` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlString : Microsoft.AspNetCore.Html.IHtmlContent { public static Microsoft.AspNetCore.Html.HtmlString Empty; @@ -55,13 +52,11 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Html.IHtmlContent` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlContent { void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder); } - // Generated from `Microsoft.AspNetCore.Html.IHtmlContentBuilder` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlContentBuilder : Microsoft.AspNetCore.Html.IHtmlContent, Microsoft.AspNetCore.Html.IHtmlContentContainer { Microsoft.AspNetCore.Html.IHtmlContentBuilder Append(string unencoded); @@ -70,7 +65,6 @@ namespace Microsoft Microsoft.AspNetCore.Html.IHtmlContentBuilder Clear(); } - // Generated from `Microsoft.AspNetCore.Html.IHtmlContentContainer` in `Microsoft.AspNetCore.Html.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlContentContainer : Microsoft.AspNetCore.Html.IHtmlContent { void CopyTo(Microsoft.AspNetCore.Html.IHtmlContentBuilder builder); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Abstractions.cs index 210f0425967..ecfba7c73fb 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,17 +7,17 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.EndpointBuilder` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class EndpointBuilder { + public System.IServiceProvider ApplicationServices { get => throw null; set => throw null; } public abstract Microsoft.AspNetCore.Http.Endpoint Build(); public string DisplayName { get => throw null; set => throw null; } protected EndpointBuilder() => throw null; + public System.Collections.Generic.IList> FilterFactories { get => throw null; } public System.Collections.Generic.IList Metadata { get => throw null; } public Microsoft.AspNetCore.Http.RequestDelegate RequestDelegate { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.IApplicationBuilder` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationBuilder { System.IServiceProvider ApplicationServices { get; set; } @@ -27,13 +28,12 @@ namespace Microsoft Microsoft.AspNetCore.Builder.IApplicationBuilder Use(System.Func middleware); } - // Generated from `Microsoft.AspNetCore.Builder.IEndpointConventionBuilder` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointConventionBuilder { void Add(System.Action convention); + void Finally(System.Action finallyConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.MapExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MapExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder Map(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString pathMatch, System.Action configuration) => throw null; @@ -41,39 +41,33 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder Map(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string pathMatch, System.Action configuration) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.MapWhenExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MapWhenExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder MapWhen(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func predicate, System.Action configuration) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RunExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RunExtensions { public static void Run(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.RequestDelegate handler) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.UseExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UseExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder Use(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func, System.Threading.Tasks.Task> middleware) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder Use(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.UseMiddlewareExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UseMiddlewareExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Type middleware, params object[] args) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseMiddleware(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, params object[] args) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.UsePathBaseExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UsePathBaseExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UsePathBase(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Http.PathString pathBase) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.UseWhenExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UseWhenExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseWhen(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, System.Func predicate, System.Action configuration) => throw null; @@ -81,14 +75,12 @@ namespace Microsoft namespace Extensions { - // Generated from `Microsoft.AspNetCore.Builder.Extensions.MapMiddleware` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MapMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public MapMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Builder.Extensions.MapOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.Extensions.MapOptions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MapOptions { public Microsoft.AspNetCore.Http.RequestDelegate Branch { get => throw null; set => throw null; } @@ -97,14 +89,12 @@ namespace Microsoft public bool PreserveMatchedPathSegment { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.Extensions.MapWhenMiddleware` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MapWhenMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public MapWhenMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Builder.Extensions.MapWhenOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.Extensions.MapWhenOptions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MapWhenOptions { public Microsoft.AspNetCore.Http.RequestDelegate Branch { get => throw null; set => throw null; } @@ -112,7 +102,6 @@ namespace Microsoft public System.Func Predicate { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.Extensions.UsePathBaseMiddleware` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UsePathBaseMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -125,7 +114,6 @@ namespace Microsoft { namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Cors.Infrastructure.ICorsMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICorsMetadata { } @@ -134,7 +122,11 @@ namespace Microsoft } namespace Http { - // Generated from `Microsoft.AspNetCore.Http.BadHttpRequestException` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class AsParametersAttribute : System.Attribute + { + public AsParametersAttribute() => throw null; + } + public class BadHttpRequestException : System.IO.IOException { public BadHttpRequestException(string message) => throw null; @@ -144,7 +136,6 @@ namespace Microsoft public int StatusCode { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.ConnectionInfo` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConnectionInfo { public abstract System.Security.Cryptography.X509Certificates.X509Certificate2 ClientCertificate { get; set; } @@ -158,7 +149,6 @@ namespace Microsoft public virtual void RequestClose() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.CookieBuilder` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieBuilder { public Microsoft.AspNetCore.Http.CookieOptions Build(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -166,6 +156,7 @@ namespace Microsoft public CookieBuilder() => throw null; public virtual string Domain { get => throw null; set => throw null; } public virtual System.TimeSpan? Expiration { get => throw null; set => throw null; } + public System.Collections.Generic.IList Extensions { get => throw null; } public virtual bool HttpOnly { get => throw null; set => throw null; } public virtual bool IsEssential { get => throw null; set => throw null; } public virtual System.TimeSpan? MaxAge { get => throw null; set => throw null; } @@ -175,7 +166,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Http.CookieSecurePolicy SecurePolicy { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.CookieSecurePolicy` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum CookieSecurePolicy : int { Always = 1, @@ -183,7 +173,14 @@ namespace Microsoft SameAsRequest = 0, } - // Generated from `Microsoft.AspNetCore.Http.Endpoint` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class DefaultEndpointFilterInvocationContext : Microsoft.AspNetCore.Http.EndpointFilterInvocationContext + { + public override System.Collections.Generic.IList Arguments { get => throw null; } + public DefaultEndpointFilterInvocationContext(Microsoft.AspNetCore.Http.HttpContext httpContext, params object[] arguments) => throw null; + public override T GetArgument(int index) => throw null; + public override Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; } + } + public class Endpoint { public string DisplayName { get => throw null; } @@ -193,17 +190,31 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.EndpointHttpContextExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public delegate System.Threading.Tasks.ValueTask EndpointFilterDelegate(Microsoft.AspNetCore.Http.EndpointFilterInvocationContext context); + + public class EndpointFilterFactoryContext + { + public System.IServiceProvider ApplicationServices { get => throw null; set => throw null; } + public EndpointFilterFactoryContext() => throw null; + public System.Reflection.MethodInfo MethodInfo { get => throw null; set => throw null; } + } + + public abstract class EndpointFilterInvocationContext + { + public abstract System.Collections.Generic.IList Arguments { get; } + protected EndpointFilterInvocationContext() => throw null; + public abstract T GetArgument(int index); + public abstract Microsoft.AspNetCore.Http.HttpContext HttpContext { get; } + } + public static class EndpointHttpContextExtensions { public static Microsoft.AspNetCore.Http.Endpoint GetEndpoint(this Microsoft.AspNetCore.Http.HttpContext context) => throw null; public static void SetEndpoint(this Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.Endpoint endpoint) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.EndpointMetadataCollection` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointMetadataCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Http.EndpointMetadataCollection+Enumerator` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public object Current { get => throw null; } @@ -223,10 +234,10 @@ namespace Microsoft System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; public T GetMetadata() where T : class => throw null; public System.Collections.Generic.IReadOnlyList GetOrderedMetadata() where T : class => throw null; + public T GetRequiredMetadata() where T : class => throw null; public object this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.FragmentString` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FragmentString : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Http.FragmentString left, Microsoft.AspNetCore.Http.FragmentString right) => throw null; @@ -245,7 +256,6 @@ namespace Microsoft public string Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.HeaderDictionaryExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HeaderDictionaryExtensions { public static void Append(this Microsoft.AspNetCore.Http.IHeaderDictionary headers, string key, Microsoft.Extensions.Primitives.StringValues value) => throw null; @@ -254,7 +264,6 @@ namespace Microsoft public static void SetCommaSeparatedValues(this Microsoft.AspNetCore.Http.IHeaderDictionary headers, string key, params string[] values) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HostString` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct HostString : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Http.HostString left, Microsoft.AspNetCore.Http.HostString right) => throw null; @@ -276,7 +285,6 @@ namespace Microsoft public string Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.HttpContext` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HttpContext { public abstract void Abort(); @@ -294,7 +302,6 @@ namespace Microsoft public abstract Microsoft.AspNetCore.Http.WebSocketManager WebSockets { get; } } - // Generated from `Microsoft.AspNetCore.Http.HttpMethods` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpMethods { public static string Connect; @@ -319,7 +326,6 @@ namespace Microsoft public static string Trace; } - // Generated from `Microsoft.AspNetCore.Http.HttpProtocol` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpProtocol { public static string GetHttpProtocol(System.Version version) => throw null; @@ -335,7 +341,6 @@ namespace Microsoft public static bool IsHttp3(string protocol) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpRequest` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HttpRequest { public abstract System.IO.Stream Body { get; set; } @@ -361,7 +366,6 @@ namespace Microsoft public abstract string Scheme { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.HttpResponse` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HttpResponse { public abstract System.IO.Stream Body { get; set; } @@ -386,46 +390,98 @@ namespace Microsoft public abstract int StatusCode { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.HttpResponseWritingExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpResponseWritingExtensions { public static System.Threading.Tasks.Task WriteAsync(this Microsoft.AspNetCore.Http.HttpResponse response, string text, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsync(this Microsoft.AspNetCore.Http.HttpResponse response, string text, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.IHttpContextAccessor` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HttpValidationProblemDetails : Microsoft.AspNetCore.Mvc.ProblemDetails + { + public System.Collections.Generic.IDictionary Errors { get => throw null; } + public HttpValidationProblemDetails() => throw null; + public HttpValidationProblemDetails(System.Collections.Generic.IDictionary errors) => throw null; + } + + public interface IBindableFromHttpContext where TSelf : class, Microsoft.AspNetCore.Http.IBindableFromHttpContext + { + static abstract System.Threading.Tasks.ValueTask BindAsync(Microsoft.AspNetCore.Http.HttpContext context, System.Reflection.ParameterInfo parameter); + } + + public interface IContentTypeHttpResult + { + string ContentType { get; } + } + + public interface IEndpointFilter + { + System.Threading.Tasks.ValueTask InvokeAsync(Microsoft.AspNetCore.Http.EndpointFilterInvocationContext context, Microsoft.AspNetCore.Http.EndpointFilterDelegate next); + } + + public interface IFileHttpResult + { + string ContentType { get; } + string FileDownloadName { get; } + } + public interface IHttpContextAccessor { Microsoft.AspNetCore.Http.HttpContext HttpContext { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.IHttpContextFactory` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpContextFactory { Microsoft.AspNetCore.Http.HttpContext Create(Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection); void Dispose(Microsoft.AspNetCore.Http.HttpContext httpContext); } - // Generated from `Microsoft.AspNetCore.Http.IMiddleware` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMiddleware { System.Threading.Tasks.Task InvokeAsync(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.AspNetCore.Http.RequestDelegate next); } - // Generated from `Microsoft.AspNetCore.Http.IMiddlewareFactory` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMiddlewareFactory { Microsoft.AspNetCore.Http.IMiddleware Create(System.Type middlewareType); void Release(Microsoft.AspNetCore.Http.IMiddleware middleware); } - // Generated from `Microsoft.AspNetCore.Http.IResult` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface INestedHttpResult + { + Microsoft.AspNetCore.Http.IResult Result { get; } + } + + public interface IProblemDetailsService + { + System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.Http.ProblemDetailsContext context); + } + + public interface IProblemDetailsWriter + { + bool CanWrite(Microsoft.AspNetCore.Http.ProblemDetailsContext context); + System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.Http.ProblemDetailsContext context); + } + public interface IResult { System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext); } - // Generated from `Microsoft.AspNetCore.Http.PathString` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IStatusCodeHttpResult + { + int? StatusCode { get; } + } + + public interface IValueHttpResult + { + object Value { get; } + } + + public interface IValueHttpResult + { + TValue Value { get; } + } + public struct PathString : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Http.PathString left, Microsoft.AspNetCore.Http.PathString right) => throw null; @@ -459,7 +515,14 @@ namespace Microsoft public static implicit operator Microsoft.AspNetCore.Http.PathString(string s) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.QueryString` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class ProblemDetailsContext + { + public Microsoft.AspNetCore.Http.EndpointMetadataCollection AdditionalMetadata { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Mvc.ProblemDetails ProblemDetails { get => throw null; set => throw null; } + public ProblemDetailsContext() => throw null; + } + public struct QueryString : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Http.QueryString left, Microsoft.AspNetCore.Http.QueryString right) => throw null; @@ -484,10 +547,8 @@ namespace Microsoft public string Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.RequestDelegate` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task RequestDelegate(Microsoft.AspNetCore.Http.HttpContext context); - // Generated from `Microsoft.AspNetCore.Http.RequestDelegateResult` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestDelegateResult { public System.Collections.Generic.IReadOnlyList EndpointMetadata { get => throw null; } @@ -495,7 +556,6 @@ namespace Microsoft public RequestDelegateResult(Microsoft.AspNetCore.Http.RequestDelegate requestDelegate, System.Collections.Generic.IReadOnlyList metadata) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.RequestTrailerExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestTrailerExtensions { public static bool CheckTrailersAvailable(this Microsoft.AspNetCore.Http.HttpRequest request) => throw null; @@ -504,7 +564,6 @@ namespace Microsoft public static bool SupportsTrailers(this Microsoft.AspNetCore.Http.HttpRequest request) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.ResponseTrailerExtensions` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ResponseTrailerExtensions { public static void AppendTrailer(this Microsoft.AspNetCore.Http.HttpResponse response, string trailerName, Microsoft.Extensions.Primitives.StringValues trailerValues) => throw null; @@ -512,7 +571,6 @@ namespace Microsoft public static bool SupportsTrailers(this Microsoft.AspNetCore.Http.HttpResponse response) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.StatusCodes` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StatusCodes { public const int Status100Continue = default; @@ -582,7 +640,6 @@ namespace Microsoft public const int Status511NetworkAuthenticationRequired = default; } - // Generated from `Microsoft.AspNetCore.Http.WebSocketManager` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class WebSocketManager { public virtual System.Threading.Tasks.Task AcceptWebSocketAsync() => throw null; @@ -595,13 +652,11 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Http.Features.IEndpointFeature` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointFeature { Microsoft.AspNetCore.Http.Endpoint Endpoint { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IRouteValuesFeature` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteValuesFeature { Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get; set; } @@ -610,7 +665,6 @@ namespace Microsoft } namespace Metadata { - // Generated from `Microsoft.AspNetCore.Http.Metadata.IAcceptsMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAcceptsMetadata { System.Collections.Generic.IReadOnlyList ContentTypes { get; } @@ -618,36 +672,55 @@ namespace Microsoft System.Type RequestType { get; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IFromBodyMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IEndpointDescriptionMetadata + { + string Description { get; } + } + + public interface IEndpointMetadataProvider + { + static abstract void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder); + } + + public interface IEndpointParameterMetadataProvider + { + static abstract void PopulateMetadata(System.Reflection.ParameterInfo parameter, Microsoft.AspNetCore.Builder.EndpointBuilder builder); + } + + public interface IEndpointSummaryMetadata + { + string Summary { get; } + } + public interface IFromBodyMetadata { bool AllowEmpty { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IFromHeaderMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IFromFormMetadata + { + string Name { get; } + } + public interface IFromHeaderMetadata { string Name { get; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IFromQueryMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFromQueryMetadata { string Name { get; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IFromRouteMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFromRouteMetadata { string Name { get; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IFromServiceMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFromServiceMetadata { } - // Generated from `Microsoft.AspNetCore.Http.Metadata.IProducesResponseTypeMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IProducesResponseTypeMetadata { System.Collections.Generic.IEnumerable ContentTypes { get; } @@ -655,7 +728,15 @@ namespace Microsoft System.Type Type { get; } } - // Generated from `Microsoft.AspNetCore.Http.Metadata.ITagsMetadata` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IRequestSizeLimitMetadata + { + System.Int64? MaxRequestBodySize { get; } + } + + public interface ISkipStatusCodePagesMetadata + { + } + public interface ITagsMetadata { System.Collections.Generic.IReadOnlyList Tags { get; } @@ -663,12 +744,24 @@ namespace Microsoft } } + namespace Mvc + { + public class ProblemDetails + { + public string Detail { get => throw null; set => throw null; } + public System.Collections.Generic.IDictionary Extensions { get => throw null; } + public string Instance { get => throw null; set => throw null; } + public ProblemDetails() => throw null; + public int? Status { get => throw null; set => throw null; } + public string Title { get => throw null; set => throw null; } + public string Type { get => throw null; set => throw null; } + } + + } namespace Routing { - // Generated from `Microsoft.AspNetCore.Routing.RouteValueDictionary` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValueDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Routing.RouteValueDictionary+Enumerator` in `Microsoft.AspNetCore.Http.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -701,6 +794,9 @@ namespace Microsoft public bool Remove(string key) => throw null; public bool Remove(string key, out object value) => throw null; public RouteValueDictionary() => throw null; + public RouteValueDictionary(System.Collections.Generic.IEnumerable> values) => throw null; + public RouteValueDictionary(System.Collections.Generic.IEnumerable> values) => throw null; + public RouteValueDictionary(Microsoft.AspNetCore.Routing.RouteValueDictionary dictionary) => throw null; public RouteValueDictionary(object values) => throw null; public bool TryAdd(string key, object value) => throw null; public bool TryGetValue(string key, out object value) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.Common.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.Common.cs index cf8a1c6d7e6..2c97c6fff35 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.Common.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.Common.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Connections.Common, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Connections { - // Generated from `Microsoft.AspNetCore.Http.Connections.AvailableTransport` in `Microsoft.AspNetCore.Http.Connections.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AvailableTransport { public AvailableTransport() => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public string Transport { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Connections.HttpTransportType` in `Microsoft.AspNetCore.Http.Connections.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum HttpTransportType : int { @@ -26,20 +25,17 @@ namespace Microsoft WebSockets = 1, } - // Generated from `Microsoft.AspNetCore.Http.Connections.HttpTransports` in `Microsoft.AspNetCore.Http.Connections.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpTransports { public static Microsoft.AspNetCore.Http.Connections.HttpTransportType All; } - // Generated from `Microsoft.AspNetCore.Http.Connections.NegotiateProtocol` in `Microsoft.AspNetCore.Http.Connections.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class NegotiateProtocol { public static Microsoft.AspNetCore.Http.Connections.NegotiationResponse ParseResponse(System.ReadOnlySpan content) => throw null; public static void WriteResponse(Microsoft.AspNetCore.Http.Connections.NegotiationResponse response, System.Buffers.IBufferWriter output) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Connections.NegotiationResponse` in `Microsoft.AspNetCore.Http.Connections.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NegotiationResponse { public string AccessToken { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.cs index cf4302ce5eb..e2a1f777e5f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Connections.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Connections, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ConnectionEndpointRouteBuilder` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionEndpointRouteBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ConnectionEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConnectionEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.ConnectionEndpointRouteBuilder MapConnectionHandler(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) where TConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler => throw null; @@ -26,14 +26,12 @@ namespace Microsoft { namespace Connections { - // Generated from `Microsoft.AspNetCore.Http.Connections.ConnectionOptions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionOptions { public ConnectionOptions() => throw null; public System.TimeSpan? DisconnectTimeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Connections.ConnectionOptionsSetup` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConnectionOptionsSetup : Microsoft.Extensions.Options.IConfigureOptions { public void Configure(Microsoft.AspNetCore.Http.Connections.ConnectionOptions options) => throw null; @@ -41,13 +39,11 @@ namespace Microsoft public static System.TimeSpan DefaultDisconectTimeout; } - // Generated from `Microsoft.AspNetCore.Http.Connections.HttpConnectionContextExtensions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpConnectionContextExtensions { public static Microsoft.AspNetCore.Http.HttpContext GetHttpContext(this Microsoft.AspNetCore.Connections.ConnectionContext connection) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Connections.HttpConnectionDispatcherOptions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpConnectionDispatcherOptions { public System.Int64 ApplicationMaxBufferSize { get => throw null; set => throw null; } @@ -62,20 +58,17 @@ namespace Microsoft public Microsoft.AspNetCore.Http.Connections.WebSocketOptions WebSockets { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Connections.LongPollingOptions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LongPollingOptions { public LongPollingOptions() => throw null; public System.TimeSpan PollTimeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Connections.NegotiateMetadata` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NegotiateMetadata { public NegotiateMetadata() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Connections.WebSocketOptions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebSocketOptions { public System.TimeSpan CloseTimeout { get => throw null; set => throw null; } @@ -85,13 +78,11 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Http.Connections.Features.IHttpContextFeature` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpContextFeature { Microsoft.AspNetCore.Http.HttpContext HttpContext { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Connections.Features.IHttpTransportFeature` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpTransportFeature { Microsoft.AspNetCore.Http.Connections.HttpTransportType TransportType { get; } @@ -105,7 +96,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ConnectionsDependencyInjectionExtensions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConnectionsDependencyInjectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddConnections(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -115,14 +105,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Threading - { - namespace Tasks - { - /* Duplicate type 'TaskExtensions' is not stubbed in this assembly 'Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Extensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Extensions.cs index d07f2c9635c..2e98c6e5cd5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Extensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Extensions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Extensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,18 @@ namespace Microsoft { namespace Http { - // Generated from `Microsoft.AspNetCore.Http.HeaderDictionaryTypeExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class EndpointDescriptionAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IEndpointDescriptionMetadata + { + public string Description { get => throw null; } + public EndpointDescriptionAttribute(string description) => throw null; + } + + public class EndpointSummaryAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IEndpointSummaryMetadata + { + public EndpointSummaryAttribute(string summary) => throw null; + public string Summary { get => throw null; } + } + public static class HeaderDictionaryTypeExtensions { public static void AppendList(this Microsoft.AspNetCore.Http.IHeaderDictionary Headers, string name, System.Collections.Generic.IList values) => throw null; @@ -14,66 +26,71 @@ namespace Microsoft public static Microsoft.AspNetCore.Http.Headers.ResponseHeaders GetTypedHeaders(this Microsoft.AspNetCore.Http.HttpResponse response) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpContextServerVariableExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpContextServerVariableExtensions { public static string GetServerVariable(this Microsoft.AspNetCore.Http.HttpContext context, string variableName) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpRequestJsonExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpRequestJsonExtensions { public static bool HasJsonContentType(this Microsoft.AspNetCore.Http.HttpRequest request) => throw null; public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Type type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Type type, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask ReadFromJsonAsync(this Microsoft.AspNetCore.Http.HttpRequest request, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpResponseJsonExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpResponseJsonExtensions { public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, object value, System.Type type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, object value, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, string contentType = default(string), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, object value, System.Type type, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, object value, System.Type type, System.Text.Json.JsonSerializerOptions options, string contentType, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, TValue value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, TValue value, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, TValue value, System.Text.Json.JsonSerializerOptions options, string contentType, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task WriteAsJsonAsync(this Microsoft.AspNetCore.Http.HttpResponse response, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, string contentType = default(string), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpValidationProblemDetails` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class HttpValidationProblemDetails : Microsoft.AspNetCore.Mvc.ProblemDetails + public class ProblemDetailsOptions { - public System.Collections.Generic.IDictionary Errors { get => throw null; } - public HttpValidationProblemDetails() => throw null; - public HttpValidationProblemDetails(System.Collections.Generic.IDictionary errors) => throw null; + public System.Action CustomizeProblemDetails { get => throw null; set => throw null; } + public ProblemDetailsOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.RequestDelegateFactory` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestDelegateFactory { - public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Delegate handler, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options = default(Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions)) => throw null; - public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Reflection.MethodInfo methodInfo, System.Func targetFactory = default(System.Func), Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options = default(Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions)) => throw null; + public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Delegate handler, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options) => throw null; + public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Delegate handler, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options = default(Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions), Microsoft.AspNetCore.Http.RequestDelegateMetadataResult metadataResult = default(Microsoft.AspNetCore.Http.RequestDelegateMetadataResult)) => throw null; + public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Reflection.MethodInfo methodInfo, System.Func targetFactory, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options) => throw null; + public static Microsoft.AspNetCore.Http.RequestDelegateResult Create(System.Reflection.MethodInfo methodInfo, System.Func targetFactory = default(System.Func), Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options = default(Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions), Microsoft.AspNetCore.Http.RequestDelegateMetadataResult metadataResult = default(Microsoft.AspNetCore.Http.RequestDelegateMetadataResult)) => throw null; + public static Microsoft.AspNetCore.Http.RequestDelegateMetadataResult InferMetadata(System.Reflection.MethodInfo methodInfo, Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions options = default(Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestDelegateFactoryOptions { public bool DisableInferBodyFromParameters { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Builder.EndpointBuilder EndpointBuilder { get => throw null; set => throw null; } public RequestDelegateFactoryOptions() => throw null; public System.Collections.Generic.IEnumerable RouteParameterNames { get => throw null; set => throw null; } public System.IServiceProvider ServiceProvider { get => throw null; set => throw null; } public bool ThrowOnBadRequest { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.ResponseExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class RequestDelegateMetadataResult + { + public System.Collections.Generic.IReadOnlyList EndpointMetadata { get => throw null; set => throw null; } + public RequestDelegateMetadataResult() => throw null; + } + public static class ResponseExtensions { public static void Clear(this Microsoft.AspNetCore.Http.HttpResponse response) => throw null; public static void Redirect(this Microsoft.AspNetCore.Http.HttpResponse response, string location, bool permanent, bool preserveMethod) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.SendFileResponseExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SendFileResponseExtensions { public static System.Threading.Tasks.Task SendFileAsync(this Microsoft.AspNetCore.Http.HttpResponse response, Microsoft.Extensions.FileProviders.IFileInfo file, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -82,7 +99,6 @@ namespace Microsoft public static System.Threading.Tasks.Task SendFileAsync(this Microsoft.AspNetCore.Http.HttpResponse response, string fileName, System.Int64 offset, System.Int64? count, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.SessionExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SessionExtensions { public static System.Byte[] Get(this Microsoft.AspNetCore.Http.ISession session, string key) => throw null; @@ -92,7 +108,6 @@ namespace Microsoft public static void SetString(this Microsoft.AspNetCore.Http.ISession session, string key, string value) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.TagsAttribute` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagsAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.ITagsMetadata { public System.Collections.Generic.IReadOnlyList Tags { get => throw null; } @@ -101,13 +116,11 @@ namespace Microsoft namespace Extensions { - // Generated from `Microsoft.AspNetCore.Http.Extensions.HttpRequestMultipartExtensions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpRequestMultipartExtensions { public static string GetMultipartBoundary(this Microsoft.AspNetCore.Http.HttpRequest request) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Extensions.QueryBuilder` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryBuilder : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public void Add(string key, System.Collections.Generic.IEnumerable values) => throw null; @@ -123,14 +136,12 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Extensions.StreamCopyOperation` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StreamCopyOperation { public static System.Threading.Tasks.Task CopyToAsync(System.IO.Stream source, System.IO.Stream destination, System.Int64? count, System.Threading.CancellationToken cancel) => throw null; public static System.Threading.Tasks.Task CopyToAsync(System.IO.Stream source, System.IO.Stream destination, System.Int64? count, int bufferSize, System.Threading.CancellationToken cancel) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Extensions.UriHelper` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UriHelper { public static string BuildAbsolute(string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.PathString path = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.QueryString query = default(Microsoft.AspNetCore.Http.QueryString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString)) => throw null; @@ -145,7 +156,6 @@ namespace Microsoft } namespace Headers { - // Generated from `Microsoft.AspNetCore.Http.Headers.RequestHeaders` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestHeaders { public System.Collections.Generic.IList Accept { get => throw null; set => throw null; } @@ -179,7 +189,6 @@ namespace Microsoft public void SetList(string name, System.Collections.Generic.IList values) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Headers.ResponseHeaders` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseHeaders { public void Append(string name, object value) => throw null; @@ -206,7 +215,6 @@ namespace Microsoft } namespace Json { - // Generated from `Microsoft.AspNetCore.Http.Json.JsonOptions` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonOptions { public JsonOptions() => throw null; @@ -215,18 +223,20 @@ namespace Microsoft } } - namespace Mvc + } + namespace Extensions + { + namespace DependencyInjection { - // Generated from `Microsoft.AspNetCore.Mvc.ProblemDetails` in `Microsoft.AspNetCore.Http.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class ProblemDetails + public static class HttpJsonServiceExtensions { - public string Detail { get => throw null; set => throw null; } - public System.Collections.Generic.IDictionary Extensions { get => throw null; } - public string Instance { get => throw null; set => throw null; } - public ProblemDetails() => throw null; - public int? Status { get => throw null; set => throw null; } - public string Title { get => throw null; set => throw null; } - public string Type { get => throw null; set => throw null; } + public static Microsoft.Extensions.DependencyInjection.IServiceCollection ConfigureHttpJsonOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; + } + + public static class ProblemDetailsServiceCollectionExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddProblemDetails(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddProblemDetails(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configure) => throw null; } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Features.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Features.cs index 606b18b725f..acf927a9dca 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Features.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Features.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Features, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,12 +7,14 @@ namespace Microsoft { namespace Http { - // Generated from `Microsoft.AspNetCore.Http.CookieOptions` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieOptions { public CookieOptions() => throw null; + public CookieOptions(Microsoft.AspNetCore.Http.CookieOptions options) => throw null; + public Microsoft.Net.Http.Headers.SetCookieHeaderValue CreateCookieHeader(string name, string value) => throw null; public string Domain { get => throw null; set => throw null; } public System.DateTimeOffset? Expires { get => throw null; set => throw null; } + public System.Collections.Generic.IList Extensions { get => throw null; } public bool HttpOnly { get => throw null; set => throw null; } public bool IsEssential { get => throw null; set => throw null; } public System.TimeSpan? MaxAge { get => throw null; set => throw null; } @@ -20,7 +23,6 @@ namespace Microsoft public bool Secure { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.IFormCollection` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFormCollection : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { bool ContainsKey(string key); @@ -31,7 +33,6 @@ namespace Microsoft bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); } - // Generated from `Microsoft.AspNetCore.Http.IFormFile` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFormFile { string ContentDisposition { get; } @@ -45,7 +46,6 @@ namespace Microsoft System.IO.Stream OpenReadStream(); } - // Generated from `Microsoft.AspNetCore.Http.IFormFileCollection` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFormFileCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { Microsoft.AspNetCore.Http.IFormFile GetFile(string name); @@ -53,7 +53,6 @@ namespace Microsoft Microsoft.AspNetCore.Http.IFormFile this[string name] { get; } } - // Generated from `Microsoft.AspNetCore.Http.IHeaderDictionary` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHeaderDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { Microsoft.Extensions.Primitives.StringValues Accept { get => throw null; set => throw null; } @@ -149,7 +148,6 @@ namespace Microsoft Microsoft.Extensions.Primitives.StringValues XXSSProtection { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.IQueryCollection` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IQueryCollection : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { bool ContainsKey(string key); @@ -159,7 +157,6 @@ namespace Microsoft bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value); } - // Generated from `Microsoft.AspNetCore.Http.IRequestCookieCollection` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestCookieCollection : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { bool ContainsKey(string key); @@ -169,7 +166,6 @@ namespace Microsoft bool TryGetValue(string key, out string value); } - // Generated from `Microsoft.AspNetCore.Http.IResponseCookies` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResponseCookies { void Append(System.ReadOnlySpan> keyValuePairs, Microsoft.AspNetCore.Http.CookieOptions options) => throw null; @@ -179,7 +175,6 @@ namespace Microsoft void Delete(string key, Microsoft.AspNetCore.Http.CookieOptions options); } - // Generated from `Microsoft.AspNetCore.Http.ISession` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISession { void Clear(); @@ -193,7 +188,6 @@ namespace Microsoft bool TryGetValue(string key, out System.Byte[] value); } - // Generated from `Microsoft.AspNetCore.Http.SameSiteMode` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum SameSiteMode : int { Lax = 1, @@ -202,7 +196,6 @@ namespace Microsoft Unspecified = -1, } - // Generated from `Microsoft.AspNetCore.Http.WebSocketAcceptContext` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebSocketAcceptContext { public bool DangerousEnableCompression { get => throw null; set => throw null; } @@ -215,7 +208,6 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Http.Features.HttpsCompressionMode` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HttpsCompressionMode : int { Compress = 2, @@ -223,13 +215,11 @@ namespace Microsoft DoNotCompress = 1, } - // Generated from `Microsoft.AspNetCore.Http.Features.IBadRequestExceptionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBadRequestExceptionFeature { System.Exception Error { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IFormFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFormFeature { Microsoft.AspNetCore.Http.IFormCollection Form { get; set; } @@ -238,13 +228,11 @@ namespace Microsoft System.Threading.Tasks.Task ReadFormAsync(System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpBodyControlFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpBodyControlFeature { bool AllowSynchronousIO { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpConnectionFeature { string ConnectionId { get; set; } @@ -254,20 +242,24 @@ namespace Microsoft int RemotePort { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpMaxRequestBodySizeFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHttpExtendedConnectFeature + { + System.Threading.Tasks.ValueTask AcceptAsync(); + bool IsExtendedConnect { get; } + string Protocol { get; } + } + public interface IHttpMaxRequestBodySizeFeature { bool IsReadOnly { get; } System.Int64? MaxRequestBodySize { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpRequestBodyDetectionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestBodyDetectionFeature { bool CanHaveBody { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpRequestFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestFeature { System.IO.Stream Body { get; set; } @@ -281,33 +273,28 @@ namespace Microsoft string Scheme { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestIdentifierFeature { string TraceIdentifier { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestLifetimeFeature { void Abort(); System.Threading.CancellationToken RequestAborted { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpRequestTrailersFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestTrailersFeature { bool Available { get; } Microsoft.AspNetCore.Http.IHeaderDictionary Trailers { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpResetFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpResetFeature { void Reset(int errorCode); } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpResponseBodyFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpResponseBodyFeature { System.Threading.Tasks.Task CompleteAsync(); @@ -318,7 +305,6 @@ namespace Microsoft System.IO.Pipelines.PipeWriter Writer { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpResponseFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpResponseFeature { System.IO.Stream Body { get; set; } @@ -330,95 +316,86 @@ namespace Microsoft int StatusCode { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpResponseTrailersFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpResponseTrailersFeature { Microsoft.AspNetCore.Http.IHeaderDictionary Trailers { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpUpgradeFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpUpgradeFeature { bool IsUpgradableRequest { get; } System.Threading.Tasks.Task UpgradeAsync(); } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpWebSocketFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpWebSocketFeature { System.Threading.Tasks.Task AcceptAsync(Microsoft.AspNetCore.Http.WebSocketAcceptContext context); bool IsWebSocketRequest { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpsCompressionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface IHttpWebTransportFeature + { + System.Threading.Tasks.ValueTask AcceptAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + bool IsWebTransportRequest { get; } + } + public interface IHttpsCompressionFeature { Microsoft.AspNetCore.Http.Features.HttpsCompressionMode Mode { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IItemsFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IItemsFeature { System.Collections.Generic.IDictionary Items { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IQueryFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IQueryFeature { Microsoft.AspNetCore.Http.IQueryCollection Query { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IRequestBodyPipeFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestBodyPipeFeature { System.IO.Pipelines.PipeReader Reader { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IRequestCookiesFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestCookiesFeature { Microsoft.AspNetCore.Http.IRequestCookieCollection Cookies { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResponseCookiesFeature { Microsoft.AspNetCore.Http.IResponseCookies Cookies { get; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IServerVariablesFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServerVariablesFeature { string this[string variableName] { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceProvidersFeature { System.IServiceProvider RequestServices { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.ISessionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISessionFeature { Microsoft.AspNetCore.Http.ISession Session { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITlsConnectionFeature { System.Security.Cryptography.X509Certificates.X509Certificate2 ClientCertificate { get; set; } System.Threading.Tasks.Task GetClientCertificateAsync(System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Http.Features.ITlsTokenBindingFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITlsTokenBindingFeature { System.Byte[] GetProvidedTokenBindingId(); System.Byte[] GetReferredTokenBindingId(); } - // Generated from `Microsoft.AspNetCore.Http.Features.ITrackingConsentFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITrackingConsentFeature { bool CanTrack { get; } @@ -429,9 +406,16 @@ namespace Microsoft void WithdrawConsent(); } + public interface IWebTransportSession + { + void Abort(int errorCode); + System.Threading.Tasks.ValueTask AcceptStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + System.Threading.Tasks.ValueTask OpenUnidirectionalStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + System.Int64 SessionId { get; } + } + namespace Authentication { - // Generated from `Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature` in `Microsoft.AspNetCore.Http.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpAuthenticationFeature { System.Security.Claims.ClaimsPrincipal User { get; set; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Results.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Results.cs index e5c417e5ffc..d6c359772a4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Results.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.Results.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http.Results, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,35 +7,46 @@ namespace Microsoft { namespace Http { - // Generated from `Microsoft.AspNetCore.Http.IResultExtensions` in `Microsoft.AspNetCore.Http.Results, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResultExtensions { } - // Generated from `Microsoft.AspNetCore.Http.Results` in `Microsoft.AspNetCore.Http.Results, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Results { public static Microsoft.AspNetCore.Http.IResult Accepted(string uri = default(string), object value = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Accepted(string uri = default(string), TValue value = default(TValue)) => throw null; public static Microsoft.AspNetCore.Http.IResult AcceptedAtRoute(string routeName = default(string), object routeValues = default(object), object value = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult AcceptedAtRoute(string routeName = default(string), object routeValues = default(object), TValue value = default(TValue)) => throw null; public static Microsoft.AspNetCore.Http.IResult BadRequest(object error = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult BadRequest(TValue error) => throw null; public static Microsoft.AspNetCore.Http.IResult Bytes(System.Byte[] contents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Bytes(System.ReadOnlyMemory contents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; public static Microsoft.AspNetCore.Http.IResult Challenge(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; public static Microsoft.AspNetCore.Http.IResult Conflict(object error = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Conflict(TValue error) => throw null; public static Microsoft.AspNetCore.Http.IResult Content(string content, Microsoft.Net.Http.Headers.MediaTypeHeaderValue contentType) => throw null; - public static Microsoft.AspNetCore.Http.IResult Content(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Content(string content, string contentType, System.Text.Encoding contentEncoding) => throw null; + public static Microsoft.AspNetCore.Http.IResult Content(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding), int? statusCode = default(int?)) => throw null; public static Microsoft.AspNetCore.Http.IResult Created(System.Uri uri, object value) => throw null; public static Microsoft.AspNetCore.Http.IResult Created(string uri, object value) => throw null; + public static Microsoft.AspNetCore.Http.IResult Created(System.Uri uri, TValue value) => throw null; + public static Microsoft.AspNetCore.Http.IResult Created(string uri, TValue value) => throw null; public static Microsoft.AspNetCore.Http.IResult CreatedAtRoute(string routeName = default(string), object routeValues = default(object), object value = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult CreatedAtRoute(string routeName = default(string), object routeValues = default(object), TValue value = default(TValue)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Empty { get => throw null; } public static Microsoft.AspNetCore.Http.IResultExtensions Extensions { get => throw null; } public static Microsoft.AspNetCore.Http.IResult File(System.Byte[] fileContents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; public static Microsoft.AspNetCore.Http.IResult File(System.IO.Stream fileStream, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; public static Microsoft.AspNetCore.Http.IResult File(string path, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; public static Microsoft.AspNetCore.Http.IResult Forbid(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; public static Microsoft.AspNetCore.Http.IResult Json(object data, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), string contentType = default(string), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Json(TValue data, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), string contentType = default(string), int? statusCode = default(int?)) => throw null; public static Microsoft.AspNetCore.Http.IResult LocalRedirect(string localUrl, bool permanent = default(bool), bool preserveMethod = default(bool)) => throw null; public static Microsoft.AspNetCore.Http.IResult NoContent() => throw null; public static Microsoft.AspNetCore.Http.IResult NotFound(object value = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult NotFound(TValue value) => throw null; public static Microsoft.AspNetCore.Http.IResult Ok(object value = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Ok(TValue value) => throw null; public static Microsoft.AspNetCore.Http.IResult Problem(Microsoft.AspNetCore.Mvc.ProblemDetails problemDetails) => throw null; public static Microsoft.AspNetCore.Http.IResult Problem(string detail = default(string), string instance = default(string), int? statusCode = default(int?), string title = default(string), string type = default(string), System.Collections.Generic.IDictionary extensions = default(System.Collections.Generic.IDictionary)) => throw null; public static Microsoft.AspNetCore.Http.IResult Redirect(string url, bool permanent = default(bool), bool preserveMethod = default(bool)) => throw null; @@ -42,13 +54,490 @@ namespace Microsoft public static Microsoft.AspNetCore.Http.IResult SignIn(System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), string authenticationScheme = default(string)) => throw null; public static Microsoft.AspNetCore.Http.IResult SignOut(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; public static Microsoft.AspNetCore.Http.IResult StatusCode(int statusCode) => throw null; + public static Microsoft.AspNetCore.Http.IResult Stream(System.Func streamWriterCallback, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Stream(System.IO.Pipelines.PipeReader pipeReader, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; public static Microsoft.AspNetCore.Http.IResult Stream(System.IO.Stream stream, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; - public static Microsoft.AspNetCore.Http.IResult Text(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Text(System.ReadOnlySpan utf8Content, string contentType = default(string), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.IResult Text(string content, string contentType, System.Text.Encoding contentEncoding) => throw null; + public static Microsoft.AspNetCore.Http.IResult Text(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding), int? statusCode = default(int?)) => throw null; public static Microsoft.AspNetCore.Http.IResult Unauthorized() => throw null; public static Microsoft.AspNetCore.Http.IResult UnprocessableEntity(object error = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.IResult UnprocessableEntity(TValue error) => throw null; public static Microsoft.AspNetCore.Http.IResult ValidationProblem(System.Collections.Generic.IDictionary errors, string detail = default(string), string instance = default(string), int? statusCode = default(int?), string title = default(string), string type = default(string), System.Collections.Generic.IDictionary extensions = default(System.Collections.Generic.IDictionary)) => throw null; } + public static class TypedResults + { + public static Microsoft.AspNetCore.Http.HttpResults.Accepted Accepted(System.Uri uri) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Accepted Accepted(string uri) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Accepted Accepted(System.Uri uri, TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Accepted Accepted(string uri, TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.AcceptedAtRoute AcceptedAtRoute(string routeName = default(string), object routeValues = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.AcceptedAtRoute AcceptedAtRoute(TValue value, string routeName = default(string), object routeValues = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.BadRequest BadRequest() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.BadRequest BadRequest(TValue error) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.FileContentHttpResult Bytes(System.Byte[] contents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.FileContentHttpResult Bytes(System.ReadOnlyMemory contents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ChallengeHttpResult Challenge(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Conflict Conflict() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Conflict Conflict(TValue error) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult Content(string content, Microsoft.Net.Http.Headers.MediaTypeHeaderValue contentType) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult Content(string content, string contentType, System.Text.Encoding contentEncoding) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult Content(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Created Created(System.Uri uri) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Created Created(string uri) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Created Created(System.Uri uri, TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Created Created(string uri, TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.CreatedAtRoute CreatedAtRoute(string routeName = default(string), object routeValues = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.CreatedAtRoute CreatedAtRoute(TValue value, string routeName = default(string), object routeValues = default(object)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.EmptyHttpResult Empty { get => throw null; } + public static Microsoft.AspNetCore.Http.HttpResults.FileContentHttpResult File(System.Byte[] fileContents, string contentType = default(string), string fileDownloadName = default(string), bool enableRangeProcessing = default(bool), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.FileStreamHttpResult File(System.IO.Stream fileStream, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ForbidHttpResult Forbid(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.JsonHttpResult Json(TValue data, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), string contentType = default(string), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.RedirectHttpResult LocalRedirect(string localUrl, bool permanent = default(bool), bool preserveMethod = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.NoContent NoContent() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.NotFound NotFound() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.NotFound NotFound(TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Ok Ok() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Ok Ok(TValue value) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.PhysicalFileHttpResult PhysicalFile(string path, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ProblemHttpResult Problem(Microsoft.AspNetCore.Mvc.ProblemDetails problemDetails) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ProblemHttpResult Problem(string detail = default(string), string instance = default(string), int? statusCode = default(int?), string title = default(string), string type = default(string), System.Collections.Generic.IDictionary extensions = default(System.Collections.Generic.IDictionary)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.RedirectHttpResult Redirect(string url, bool permanent = default(bool), bool preserveMethod = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.RedirectToRouteHttpResult RedirectToRoute(string routeName = default(string), object routeValues = default(object), bool permanent = default(bool), bool preserveMethod = default(bool), string fragment = default(string)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.SignInHttpResult SignIn(System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), string authenticationScheme = default(string)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.SignOutHttpResult SignOut(Microsoft.AspNetCore.Authentication.AuthenticationProperties properties = default(Microsoft.AspNetCore.Authentication.AuthenticationProperties), System.Collections.Generic.IList authenticationSchemes = default(System.Collections.Generic.IList)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.StatusCodeHttpResult StatusCode(int statusCode) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.PushStreamHttpResult Stream(System.Func streamWriterCallback, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.FileStreamHttpResult Stream(System.IO.Pipelines.PipeReader pipeReader, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.FileStreamHttpResult Stream(System.IO.Stream stream, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.Utf8ContentHttpResult Text(System.ReadOnlySpan utf8Content, string contentType = default(string), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult Text(string content, string contentType, System.Text.Encoding contentEncoding) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ContentHttpResult Text(string content, string contentType = default(string), System.Text.Encoding contentEncoding = default(System.Text.Encoding), int? statusCode = default(int?)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.UnauthorizedHttpResult Unauthorized() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.UnprocessableEntity UnprocessableEntity() => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.UnprocessableEntity UnprocessableEntity(TValue error) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.ValidationProblem ValidationProblem(System.Collections.Generic.IDictionary errors, string detail = default(string), string instance = default(string), string title = default(string), string type = default(string), System.Collections.Generic.IDictionary extensions = default(System.Collections.Generic.IDictionary)) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.VirtualFileHttpResult VirtualFile(string path, string contentType = default(string), string fileDownloadName = default(string), System.DateTimeOffset? lastModified = default(System.DateTimeOffset?), Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag = default(Microsoft.Net.Http.Headers.EntityTagHeaderValue), bool enableRangeProcessing = default(bool)) => throw null; + } + + namespace HttpResults + { + public class Accepted : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string Location { get => throw null; } + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class Accepted : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string Location { get => throw null; } + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class AcceptedAtRoute : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public string RouteName { get => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class AcceptedAtRoute : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public string RouteName { get => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class BadRequest : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class BadRequest : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class ChallengeHttpResult : Microsoft.AspNetCore.Http.IResult + { + public System.Collections.Generic.IReadOnlyList AuthenticationSchemes { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } + } + + public class Conflict : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class Conflict : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class ContentHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult + { + public string ContentType { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string ResponseContent { get => throw null; set => throw null; } + public int? StatusCode { get => throw null; set => throw null; } + } + + public class Created : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string Location { get => throw null; } + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class Created : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string Location { get => throw null; } + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class CreatedAtRoute : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public string RouteName { get => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class CreatedAtRoute : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public string RouteName { get => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class EmptyHttpResult : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static Microsoft.AspNetCore.Http.HttpResults.EmptyHttpResult Instance { get => throw null; } + } + + public class FileContentHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IFileHttpResult, Microsoft.AspNetCore.Http.IResult + { + public string ContentType { get => throw null; set => throw null; } + public bool EnableRangeProcessing { get => throw null; set => throw null; } + public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public System.ReadOnlyMemory FileContents { get => throw null; set => throw null; } + public string FileDownloadName { get => throw null; set => throw null; } + public System.Int64? FileLength { get => throw null; set => throw null; } + public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } + } + + public class FileStreamHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IFileHttpResult, Microsoft.AspNetCore.Http.IResult + { + public string ContentType { get => throw null; set => throw null; } + public bool EnableRangeProcessing { get => throw null; set => throw null; } + public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string FileDownloadName { get => throw null; set => throw null; } + public System.Int64? FileLength { get => throw null; set => throw null; } + public System.IO.Stream FileStream { get => throw null; } + public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } + } + + public class ForbidHttpResult : Microsoft.AspNetCore.Http.IResult + { + public System.Collections.Generic.IReadOnlyList AuthenticationSchemes { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } + } + + public class JsonHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult + { + public string ContentType { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public System.Text.Json.JsonSerializerOptions JsonSerializerOptions { get => throw null; set => throw null; } + public int? StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class NoContent : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class NotFound : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class NotFound : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; set => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class Ok : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class Ok : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class PhysicalFileHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IFileHttpResult, Microsoft.AspNetCore.Http.IResult + { + public string ContentType { get => throw null; set => throw null; } + public bool EnableRangeProcessing { get => throw null; set => throw null; } + public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string FileDownloadName { get => throw null; set => throw null; } + public System.Int64? FileLength { get => throw null; set => throw null; } + public string FileName { get => throw null; } + public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } + } + + public class ProblemHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult + { + public string ContentType { get => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public Microsoft.AspNetCore.Mvc.ProblemDetails ProblemDetails { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + Microsoft.AspNetCore.Mvc.ProblemDetails Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class PushStreamHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IFileHttpResult, Microsoft.AspNetCore.Http.IResult + { + public string ContentType { get => throw null; set => throw null; } + public bool EnableRangeProcessing { get => throw null; set => throw null; } + public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string FileDownloadName { get => throw null; set => throw null; } + public System.Int64? FileLength { get => throw null; set => throw null; } + public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } + } + + public class RedirectHttpResult : Microsoft.AspNetCore.Http.IResult + { + public bool AcceptLocalUrlOnly { get => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public bool Permanent { get => throw null; } + public bool PreserveMethod { get => throw null; } + public string Url { get => throw null; } + } + + public class RedirectToRouteHttpResult : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string Fragment { get => throw null; } + public bool Permanent { get => throw null; } + public bool PreserveMethod { get => throw null; } + public string RouteName { get => throw null; } + public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; } + } + + public class Results : Microsoft.AspNetCore.Http.INestedHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider where TResult1 : Microsoft.AspNetCore.Http.IResult where TResult2 : Microsoft.AspNetCore.Http.IResult where TResult3 : Microsoft.AspNetCore.Http.IResult where TResult4 : Microsoft.AspNetCore.Http.IResult where TResult5 : Microsoft.AspNetCore.Http.IResult where TResult6 : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.IResult Result { get => throw null; } + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult1 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult2 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult3 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult4 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult5 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult6 result) => throw null; + } + + public class Results : Microsoft.AspNetCore.Http.INestedHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider where TResult1 : Microsoft.AspNetCore.Http.IResult where TResult2 : Microsoft.AspNetCore.Http.IResult where TResult3 : Microsoft.AspNetCore.Http.IResult where TResult4 : Microsoft.AspNetCore.Http.IResult where TResult5 : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.IResult Result { get => throw null; } + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult1 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult2 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult3 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult4 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult5 result) => throw null; + } + + public class Results : Microsoft.AspNetCore.Http.INestedHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider where TResult1 : Microsoft.AspNetCore.Http.IResult where TResult2 : Microsoft.AspNetCore.Http.IResult where TResult3 : Microsoft.AspNetCore.Http.IResult where TResult4 : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.IResult Result { get => throw null; } + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult1 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult2 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult3 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult4 result) => throw null; + } + + public class Results : Microsoft.AspNetCore.Http.INestedHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider where TResult1 : Microsoft.AspNetCore.Http.IResult where TResult2 : Microsoft.AspNetCore.Http.IResult where TResult3 : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.IResult Result { get => throw null; } + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult1 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult2 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult3 result) => throw null; + } + + public class Results : Microsoft.AspNetCore.Http.INestedHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider where TResult1 : Microsoft.AspNetCore.Http.IResult where TResult2 : Microsoft.AspNetCore.Http.IResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.IResult Result { get => throw null; } + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult1 result) => throw null; + public static implicit operator Microsoft.AspNetCore.Http.HttpResults.Results(TResult2 result) => throw null; + } + + public class SignInHttpResult : Microsoft.AspNetCore.Http.IResult + { + public string AuthenticationScheme { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public System.Security.Claims.ClaimsPrincipal Principal { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } + } + + public class SignOutHttpResult : Microsoft.AspNetCore.Http.IResult + { + public System.Collections.Generic.IReadOnlyList AuthenticationSchemes { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } + } + + public class StatusCodeHttpResult : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class UnauthorizedHttpResult : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class UnprocessableEntity : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + } + + public class UnprocessableEntity : Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + public TValue Value { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class Utf8ContentHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult + { + public string ContentType { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public System.ReadOnlyMemory ResponseContent { get => throw null; set => throw null; } + public int? StatusCode { get => throw null; set => throw null; } + } + + public class ValidationProblem : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IResult, Microsoft.AspNetCore.Http.IStatusCodeHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.IValueHttpResult, Microsoft.AspNetCore.Http.Metadata.IEndpointMetadataProvider + { + public string ContentType { get => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public static void PopulateMetadata(System.Reflection.MethodInfo method, Microsoft.AspNetCore.Builder.EndpointBuilder builder) => throw null; + public Microsoft.AspNetCore.Http.HttpValidationProblemDetails ProblemDetails { get => throw null; } + public int StatusCode { get => throw null; } + int? Microsoft.AspNetCore.Http.IStatusCodeHttpResult.StatusCode { get => throw null; } + object Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + Microsoft.AspNetCore.Http.HttpValidationProblemDetails Microsoft.AspNetCore.Http.IValueHttpResult.Value { get => throw null; } + } + + public class VirtualFileHttpResult : Microsoft.AspNetCore.Http.IContentTypeHttpResult, Microsoft.AspNetCore.Http.IFileHttpResult, Microsoft.AspNetCore.Http.IResult + { + public string ContentType { get => throw null; set => throw null; } + public bool EnableRangeProcessing { get => throw null; set => throw null; } + public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; + public string FileDownloadName { get => throw null; set => throw null; } + public System.Int64? FileLength { get => throw null; set => throw null; } + public string FileName { get => throw null; set => throw null; } + public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } + } + + } } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.cs index 6a7d7b8c988..8625e51e6a0 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Http.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Http, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ApplicationBuilder` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationBuilder : Microsoft.AspNetCore.Builder.IApplicationBuilder { public ApplicationBuilder(System.IServiceProvider serviceProvider) => throw null; @@ -22,7 +22,6 @@ namespace Microsoft } namespace Http { - // Generated from `Microsoft.AspNetCore.Http.BindingAddress` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingAddress { public BindingAddress() => throw null; @@ -38,7 +37,6 @@ namespace Microsoft public string UnixPipePath { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.DefaultHttpContext` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultHttpContext : Microsoft.AspNetCore.Http.HttpContext { public override void Abort() => throw null; @@ -62,10 +60,8 @@ namespace Microsoft public override Microsoft.AspNetCore.Http.WebSocketManager WebSockets { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.FormCollection` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormCollection : Microsoft.AspNetCore.Http.IFormCollection, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Http.FormCollection+Enumerator` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -90,7 +86,6 @@ namespace Microsoft public bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.FormFile` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFile : Microsoft.AspNetCore.Http.IFormFile { public string ContentDisposition { get => throw null; set => throw null; } @@ -105,7 +100,6 @@ namespace Microsoft public System.IO.Stream OpenReadStream() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.FormFileCollection` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFileCollection : System.Collections.Generic.List, Microsoft.AspNetCore.Http.IFormFileCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { public FormFileCollection() => throw null; @@ -114,10 +108,8 @@ namespace Microsoft public Microsoft.AspNetCore.Http.IFormFile this[string name] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.HeaderDictionary` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeaderDictionary : Microsoft.AspNetCore.Http.IHeaderDictionary, System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Http.HeaderDictionary+Enumerator` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -153,14 +145,12 @@ namespace Microsoft public System.Collections.Generic.ICollection Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.HttpContextAccessor` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpContextAccessor : Microsoft.AspNetCore.Http.IHttpContextAccessor { public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; set => throw null; } public HttpContextAccessor() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.HttpRequestRewindExtensions` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpRequestRewindExtensions { public static void EnableBuffering(this Microsoft.AspNetCore.Http.HttpRequest request) => throw null; @@ -169,7 +159,6 @@ namespace Microsoft public static void EnableBuffering(this Microsoft.AspNetCore.Http.HttpRequest request, System.Int64 bufferLimit) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.MiddlewareFactory` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MiddlewareFactory : Microsoft.AspNetCore.Http.IMiddlewareFactory { public Microsoft.AspNetCore.Http.IMiddleware Create(System.Type middlewareType) => throw null; @@ -177,10 +166,8 @@ namespace Microsoft public void Release(Microsoft.AspNetCore.Http.IMiddleware middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.QueryCollection` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryCollection : Microsoft.AspNetCore.Http.IQueryCollection, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Http.QueryCollection+Enumerator` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -207,19 +194,16 @@ namespace Microsoft public bool TryGetValue(string key, out Microsoft.Extensions.Primitives.StringValues value) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.RequestFormReaderExtensions` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestFormReaderExtensions { public static System.Threading.Tasks.Task ReadFormAsync(this Microsoft.AspNetCore.Http.HttpRequest request, Microsoft.AspNetCore.Http.Features.FormOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.SendFileFallback` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SendFileFallback { public static System.Threading.Tasks.Task SendFileAsync(System.IO.Stream destination, string filePath, System.Int64 offset, System.Int64? count, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.StreamResponseBodyFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StreamResponseBodyFeature : Microsoft.AspNetCore.Http.Features.IHttpResponseBodyFeature { public virtual System.Threading.Tasks.Task CompleteAsync() => throw null; @@ -236,14 +220,12 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Http.Features.DefaultSessionFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultSessionFeature : Microsoft.AspNetCore.Http.Features.ISessionFeature { public DefaultSessionFeature() => throw null; public Microsoft.AspNetCore.Http.ISession Session { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.FormFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFeature : Microsoft.AspNetCore.Http.Features.IFormFeature { public Microsoft.AspNetCore.Http.IFormCollection Form { get => throw null; set => throw null; } @@ -256,7 +238,6 @@ namespace Microsoft public System.Threading.Tasks.Task ReadFormAsync(System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.FormOptions` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormOptions { public bool BufferBody { get => throw null; set => throw null; } @@ -276,7 +257,6 @@ namespace Microsoft public int ValueLengthLimit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.HttpConnectionFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpConnectionFeature : Microsoft.AspNetCore.Http.Features.IHttpConnectionFeature { public string ConnectionId { get => throw null; set => throw null; } @@ -287,7 +267,6 @@ namespace Microsoft public int RemotePort { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.HttpRequestFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpRequestFeature : Microsoft.AspNetCore.Http.Features.IHttpRequestFeature { public System.IO.Stream Body { get => throw null; set => throw null; } @@ -302,14 +281,12 @@ namespace Microsoft public string Scheme { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.HttpRequestIdentifierFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpRequestIdentifierFeature : Microsoft.AspNetCore.Http.Features.IHttpRequestIdentifierFeature { public HttpRequestIdentifierFeature() => throw null; public string TraceIdentifier { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.HttpRequestLifetimeFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpRequestLifetimeFeature : Microsoft.AspNetCore.Http.Features.IHttpRequestLifetimeFeature { public void Abort() => throw null; @@ -317,7 +294,6 @@ namespace Microsoft public System.Threading.CancellationToken RequestAborted { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.HttpResponseFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpResponseFeature : Microsoft.AspNetCore.Http.Features.IHttpResponseFeature { public System.IO.Stream Body { get => throw null; set => throw null; } @@ -330,20 +306,17 @@ namespace Microsoft public int StatusCode { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IHttpActivityFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpActivityFeature { System.Diagnostics.Activity Activity { get; set; } } - // Generated from `Microsoft.AspNetCore.Http.Features.ItemsFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ItemsFeature : Microsoft.AspNetCore.Http.Features.IItemsFeature { public System.Collections.Generic.IDictionary Items { get => throw null; set => throw null; } public ItemsFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.QueryFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryFeature : Microsoft.AspNetCore.Http.Features.IQueryFeature { public Microsoft.AspNetCore.Http.IQueryCollection Query { get => throw null; set => throw null; } @@ -351,14 +324,12 @@ namespace Microsoft public QueryFeature(Microsoft.AspNetCore.Http.IQueryCollection query) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.RequestBodyPipeFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestBodyPipeFeature : Microsoft.AspNetCore.Http.Features.IRequestBodyPipeFeature { public System.IO.Pipelines.PipeReader Reader { get => throw null; } public RequestBodyPipeFeature(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.RequestCookiesFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestCookiesFeature : Microsoft.AspNetCore.Http.Features.IRequestCookiesFeature { public Microsoft.AspNetCore.Http.IRequestCookieCollection Cookies { get => throw null; set => throw null; } @@ -366,7 +337,6 @@ namespace Microsoft public RequestCookiesFeature(Microsoft.AspNetCore.Http.IRequestCookieCollection cookies) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.RequestServicesFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestServicesFeature : Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature, System.IAsyncDisposable, System.IDisposable { public void Dispose() => throw null; @@ -375,7 +345,6 @@ namespace Microsoft public RequestServicesFeature(Microsoft.AspNetCore.Http.HttpContext context, Microsoft.Extensions.DependencyInjection.IServiceScopeFactory scopeFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.ResponseCookiesFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCookiesFeature : Microsoft.AspNetCore.Http.Features.IResponseCookiesFeature { public Microsoft.AspNetCore.Http.IResponseCookies Cookies { get => throw null; } @@ -383,21 +352,18 @@ namespace Microsoft public ResponseCookiesFeature(Microsoft.AspNetCore.Http.Features.IFeatureCollection features, Microsoft.Extensions.ObjectPool.ObjectPool builderPool) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.RouteValuesFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValuesFeature : Microsoft.AspNetCore.Http.Features.IRouteValuesFeature { public Microsoft.AspNetCore.Routing.RouteValueDictionary RouteValues { get => throw null; set => throw null; } public RouteValuesFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.ServiceProvidersFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceProvidersFeature : Microsoft.AspNetCore.Http.Features.IServiceProvidersFeature { public System.IServiceProvider RequestServices { get => throw null; set => throw null; } public ServiceProvidersFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.TlsConnectionFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TlsConnectionFeature : Microsoft.AspNetCore.Http.Features.ITlsConnectionFeature { public System.Security.Cryptography.X509Certificates.X509Certificate2 ClientCertificate { get => throw null; set => throw null; } @@ -407,7 +373,6 @@ namespace Microsoft namespace Authentication { - // Generated from `Microsoft.AspNetCore.Http.Features.Authentication.HttpAuthenticationFeature` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpAuthenticationFeature : Microsoft.AspNetCore.Http.Features.Authentication.IHttpAuthenticationFeature { public HttpAuthenticationFeature() => throw null; @@ -422,7 +387,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.HttpServiceCollectionExtensions` in `Microsoft.AspNetCore.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHttpContextAccessor(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpLogging.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpLogging.cs index aca5bc3bc03..b648a77f716 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpLogging.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpLogging.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.HttpLogging, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.HttpLoggingBuilderExtensions` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpLoggingBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHttpLogging(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft } namespace HttpLogging { - // Generated from `Microsoft.AspNetCore.HttpLogging.HttpLoggingFields` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum HttpLoggingFields : long { @@ -41,7 +40,6 @@ namespace Microsoft ResponseTrailers = 512, } - // Generated from `Microsoft.AspNetCore.HttpLogging.HttpLoggingOptions` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpLoggingOptions { public HttpLoggingOptions() => throw null; @@ -53,7 +51,6 @@ namespace Microsoft public System.Collections.Generic.ISet ResponseHeaders { get => throw null; } } - // Generated from `Microsoft.AspNetCore.HttpLogging.MediaTypeOptions` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MediaTypeOptions { public void AddBinary(Microsoft.Net.Http.Headers.MediaTypeHeaderValue mediaType) => throw null; @@ -63,9 +60,9 @@ namespace Microsoft public void Clear() => throw null; } - // Generated from `Microsoft.AspNetCore.HttpLogging.W3CLoggerOptions` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class W3CLoggerOptions { + public System.Collections.Generic.ISet AdditionalRequestHeaders { get => throw null; } public string FileName { get => throw null; set => throw null; } public int? FileSizeLimit { get => throw null; set => throw null; } public System.TimeSpan FlushInterval { get => throw null; set => throw null; } @@ -75,7 +72,6 @@ namespace Microsoft public W3CLoggerOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.HttpLogging.W3CLoggingFields` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum W3CLoggingFields : long { @@ -109,7 +105,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.HttpLoggingServicesExtensions` in `Microsoft.AspNetCore.HttpLogging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpLoggingServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHttpLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpOverrides.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpOverrides.cs index a6d29df8e8b..36678aa5c0d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpOverrides.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpOverrides.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.HttpOverrides, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,20 +7,17 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.CertificateForwardingBuilderExtensions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CertificateForwardingBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseCertificateForwarding(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ForwardedHeadersExtensions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ForwardedHeadersExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseForwardedHeaders(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseForwardedHeaders(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, Microsoft.AspNetCore.Builder.ForwardedHeadersOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ForwardedHeadersOptions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ForwardedHeadersOptions { public System.Collections.Generic.IList AllowedHosts { get => throw null; set => throw null; } @@ -37,14 +35,12 @@ namespace Microsoft public bool RequireHeaderSymmetry { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.HttpMethodOverrideExtensions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpMethodOverrideExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHttpMethodOverride(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHttpMethodOverride(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HttpMethodOverrideOptions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodOverrideOptions { public string FormFieldName { get => throw null; set => throw null; } @@ -54,14 +50,12 @@ namespace Microsoft } namespace HttpOverrides { - // Generated from `Microsoft.AspNetCore.HttpOverrides.CertificateForwardingMiddleware` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CertificateForwardingMiddleware { public CertificateForwardingMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions options) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; } - // Generated from `Microsoft.AspNetCore.HttpOverrides.CertificateForwardingOptions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CertificateForwardingOptions { public CertificateForwardingOptions() => throw null; @@ -69,7 +63,6 @@ namespace Microsoft public System.Func HeaderConverter; } - // Generated from `Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum ForwardedHeaders : int { @@ -80,7 +73,6 @@ namespace Microsoft XForwardedProto = 4, } - // Generated from `Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersDefaults` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ForwardedHeadersDefaults { public static string XForwardedForHeaderName { get => throw null; } @@ -91,7 +83,6 @@ namespace Microsoft public static string XOriginalProtoHeaderName { get => throw null; } } - // Generated from `Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ForwardedHeadersMiddleware { public void ApplyForwarders(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -99,14 +90,12 @@ namespace Microsoft public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.HttpOverrides.HttpMethodOverrideMiddleware` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodOverrideMiddleware { public HttpMethodOverrideMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.HttpOverrides.IPNetwork` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IPNetwork { public bool Contains(System.Net.IPAddress address) => throw null; @@ -121,7 +110,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.CertificateForwardingServiceExtensions` in `Microsoft.AspNetCore.HttpOverrides, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CertificateForwardingServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddCertificateForwarding(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configure) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpsPolicy.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpsPolicy.cs index bd0c68d9de7..5614099fd84 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpsPolicy.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.HttpsPolicy.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.HttpsPolicy, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,25 +7,21 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.HstsBuilderExtensions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HstsBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHsts(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HstsServicesExtensions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HstsServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHsts(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HttpsPolicyBuilderExtensions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpsPolicyBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseHttpsRedirection(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HttpsRedirectionServicesExtensions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpsRedirectionServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHttpsRedirection(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; @@ -33,7 +30,6 @@ namespace Microsoft } namespace HttpsPolicy { - // Generated from `Microsoft.AspNetCore.HttpsPolicy.HstsMiddleware` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HstsMiddleware { public HstsMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options) => throw null; @@ -41,7 +37,6 @@ namespace Microsoft public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.HttpsPolicy.HstsOptions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HstsOptions { public System.Collections.Generic.IList ExcludedHosts { get => throw null; } @@ -51,7 +46,6 @@ namespace Microsoft public bool Preload { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpsRedirectionMiddleware { public HttpsRedirectionMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Configuration.IConfiguration config, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; @@ -59,7 +53,6 @@ namespace Microsoft public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionOptions` in `Microsoft.AspNetCore.HttpsPolicy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpsRedirectionOptions { public int? HttpsPort { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Identity.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Identity.cs index e02748808fd..134862c6d1c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Identity.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Identity.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Identity, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,21 +7,18 @@ namespace Microsoft { namespace Identity { - // Generated from `Microsoft.AspNetCore.Identity.AspNetRoleManager<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AspNetRoleManager : Microsoft.AspNetCore.Identity.RoleManager, System.IDisposable where TRole : class { public AspNetRoleManager(Microsoft.AspNetCore.Identity.IRoleStore store, System.Collections.Generic.IEnumerable> roleValidators, Microsoft.AspNetCore.Identity.ILookupNormalizer keyNormalizer, Microsoft.AspNetCore.Identity.IdentityErrorDescriber errors, Microsoft.Extensions.Logging.ILogger> logger, Microsoft.AspNetCore.Http.IHttpContextAccessor contextAccessor) : base(default(Microsoft.AspNetCore.Identity.IRoleStore), default(System.Collections.Generic.IEnumerable>), default(Microsoft.AspNetCore.Identity.ILookupNormalizer), default(Microsoft.AspNetCore.Identity.IdentityErrorDescriber), default(Microsoft.Extensions.Logging.ILogger>)) => throw null; protected override System.Threading.CancellationToken CancellationToken { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.AspNetUserManager<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AspNetUserManager : Microsoft.AspNetCore.Identity.UserManager, System.IDisposable where TUser : class { public AspNetUserManager(Microsoft.AspNetCore.Identity.IUserStore store, Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.AspNetCore.Identity.IPasswordHasher passwordHasher, System.Collections.Generic.IEnumerable> userValidators, System.Collections.Generic.IEnumerable> passwordValidators, Microsoft.AspNetCore.Identity.ILookupNormalizer keyNormalizer, Microsoft.AspNetCore.Identity.IdentityErrorDescriber errors, System.IServiceProvider services, Microsoft.Extensions.Logging.ILogger> logger) : base(default(Microsoft.AspNetCore.Identity.IUserStore), default(Microsoft.Extensions.Options.IOptions), default(Microsoft.AspNetCore.Identity.IPasswordHasher), default(System.Collections.Generic.IEnumerable>), default(System.Collections.Generic.IEnumerable>), default(Microsoft.AspNetCore.Identity.ILookupNormalizer), default(Microsoft.AspNetCore.Identity.IdentityErrorDescriber), default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILogger>)) => throw null; protected override System.Threading.CancellationToken CancellationToken { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.DataProtectionTokenProviderOptions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataProtectionTokenProviderOptions { public DataProtectionTokenProviderOptions() => throw null; @@ -28,7 +26,6 @@ namespace Microsoft public System.TimeSpan TokenLifespan { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.DataProtectorTokenProvider<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataProtectorTokenProvider : Microsoft.AspNetCore.Identity.IUserTwoFactorTokenProvider where TUser : class { public virtual System.Threading.Tasks.Task CanGenerateTwoFactorTokenAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; @@ -41,7 +38,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidateAsync(string purpose, string token, Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.ExternalLoginInfo` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExternalLoginInfo : Microsoft.AspNetCore.Identity.UserLoginInfo { public Microsoft.AspNetCore.Authentication.AuthenticationProperties AuthenticationProperties { get => throw null; set => throw null; } @@ -50,18 +46,15 @@ namespace Microsoft public System.Security.Claims.ClaimsPrincipal Principal { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.ISecurityStampValidator` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISecurityStampValidator { System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext context); } - // Generated from `Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITwoFactorSecurityStampValidator : Microsoft.AspNetCore.Identity.ISecurityStampValidator { } - // Generated from `Microsoft.AspNetCore.Identity.IdentityBuilderExtensions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class IdentityBuilderExtensions { public static Microsoft.AspNetCore.Identity.IdentityBuilder AddDefaultTokenProviders(this Microsoft.AspNetCore.Identity.IdentityBuilder builder) => throw null; @@ -69,7 +62,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Identity.IdentityBuilder AddSignInManager(this Microsoft.AspNetCore.Identity.IdentityBuilder builder) where TSignInManager : class => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityConstants` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityConstants { public static string ApplicationScheme; @@ -79,7 +71,6 @@ namespace Microsoft public static string TwoFactorUserIdScheme; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityCookieAuthenticationBuilderExtensions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class IdentityCookieAuthenticationBuilderExtensions { public static Microsoft.Extensions.Options.OptionsBuilder AddApplicationCookie(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder) => throw null; @@ -90,7 +81,6 @@ namespace Microsoft public static Microsoft.Extensions.Options.OptionsBuilder AddTwoFactorUserIdCookie(this Microsoft.AspNetCore.Authentication.AuthenticationBuilder builder) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityCookiesBuilder` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityCookiesBuilder { public Microsoft.Extensions.Options.OptionsBuilder ApplicationCookie { get => throw null; set => throw null; } @@ -100,7 +90,6 @@ namespace Microsoft public Microsoft.Extensions.Options.OptionsBuilder TwoFactorUserIdCookie { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.SecurityStampRefreshingPrincipalContext` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SecurityStampRefreshingPrincipalContext { public System.Security.Claims.ClaimsPrincipal CurrentPrincipal { get => throw null; set => throw null; } @@ -108,14 +97,12 @@ namespace Microsoft public SecurityStampRefreshingPrincipalContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.SecurityStampValidator` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SecurityStampValidator { public static System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext context) where TValidator : Microsoft.AspNetCore.Identity.ISecurityStampValidator => throw null; public static System.Threading.Tasks.Task ValidatePrincipalAsync(Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.SecurityStampValidator<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SecurityStampValidator : Microsoft.AspNetCore.Identity.ISecurityStampValidator where TUser : class { public Microsoft.AspNetCore.Authentication.ISystemClock Clock { get => throw null; } @@ -128,7 +115,6 @@ namespace Microsoft protected virtual System.Threading.Tasks.Task VerifySecurityStamp(System.Security.Claims.ClaimsPrincipal principal) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.SecurityStampValidatorOptions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SecurityStampValidatorOptions { public System.Func OnRefreshingPrincipal { get => throw null; set => throw null; } @@ -136,7 +122,6 @@ namespace Microsoft public System.TimeSpan ValidationInterval { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.SignInManager<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SignInManager where TUser : class { public virtual System.Threading.Tasks.Task CanSignInAsync(TUser user) => throw null; @@ -180,7 +165,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidateTwoFactorSecurityStampAsync(System.Security.Claims.ClaimsPrincipal principal) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.TwoFactorSecurityStampValidator<>` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TwoFactorSecurityStampValidator : Microsoft.AspNetCore.Identity.SecurityStampValidator, Microsoft.AspNetCore.Identity.ISecurityStampValidator, Microsoft.AspNetCore.Identity.ITwoFactorSecurityStampValidator where TUser : class { protected override System.Threading.Tasks.Task SecurityStampVerified(TUser user, Microsoft.AspNetCore.Authentication.Cookies.CookieValidatePrincipalContext context) => throw null; @@ -194,7 +178,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class IdentityServiceCollectionExtensions { public static Microsoft.AspNetCore.Identity.IdentityBuilder AddIdentity(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TRole : class where TUser : class => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.Routing.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.Routing.cs index 9407778c975..4afdc6833c3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.Routing.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.Routing.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Localization.Routing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Routing { - // Generated from `Microsoft.AspNetCore.Localization.Routing.RouteDataRequestCultureProvider` in `Microsoft.AspNetCore.Localization.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteDataRequestCultureProvider : Microsoft.AspNetCore.Localization.RequestCultureProvider { public override System.Threading.Tasks.Task DetermineProviderCultureResult(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.cs index 0ee8f565ee8..64c83d42619 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Localization.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Localization, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ApplicationBuilderExtensions` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ApplicationBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRequestLocalization(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -15,7 +15,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRequestLocalization(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, params string[] cultures) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RequestLocalizationOptions` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestLocalizationOptions { public Microsoft.AspNetCore.Builder.RequestLocalizationOptions AddSupportedCultures(params string[] cultures) => throw null; @@ -31,7 +30,6 @@ namespace Microsoft public System.Collections.Generic.IList SupportedUICultures { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.RequestLocalizationOptionsExtensions` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestLocalizationOptionsExtensions { public static Microsoft.AspNetCore.Builder.RequestLocalizationOptions AddInitialRequestCultureProvider(this Microsoft.AspNetCore.Builder.RequestLocalizationOptions requestLocalizationOptions, Microsoft.AspNetCore.Localization.RequestCultureProvider requestCultureProvider) => throw null; @@ -40,7 +38,6 @@ namespace Microsoft } namespace Localization { - // Generated from `Microsoft.AspNetCore.Localization.AcceptLanguageHeaderRequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AcceptLanguageHeaderRequestCultureProvider : Microsoft.AspNetCore.Localization.RequestCultureProvider { public AcceptLanguageHeaderRequestCultureProvider() => throw null; @@ -48,7 +45,6 @@ namespace Microsoft public int MaximumAcceptLanguageHeaderValuesToTry { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Localization.CookieRequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieRequestCultureProvider : Microsoft.AspNetCore.Localization.RequestCultureProvider { public string CookieName { get => throw null; set => throw null; } @@ -59,27 +55,23 @@ namespace Microsoft public static Microsoft.AspNetCore.Localization.ProviderCultureResult ParseCookieValue(string value) => throw null; } - // Generated from `Microsoft.AspNetCore.Localization.CustomRequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CustomRequestCultureProvider : Microsoft.AspNetCore.Localization.RequestCultureProvider { public CustomRequestCultureProvider(System.Func> provider) => throw null; public override System.Threading.Tasks.Task DetermineProviderCultureResult(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Localization.IRequestCultureFeature` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestCultureFeature { Microsoft.AspNetCore.Localization.IRequestCultureProvider Provider { get; } Microsoft.AspNetCore.Localization.RequestCulture RequestCulture { get; } } - // Generated from `Microsoft.AspNetCore.Localization.IRequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestCultureProvider { System.Threading.Tasks.Task DetermineProviderCultureResult(Microsoft.AspNetCore.Http.HttpContext httpContext); } - // Generated from `Microsoft.AspNetCore.Localization.ProviderCultureResult` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProviderCultureResult { public System.Collections.Generic.IList Cultures { get => throw null; } @@ -90,7 +82,6 @@ namespace Microsoft public System.Collections.Generic.IList UICultures { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Localization.QueryStringRequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryStringRequestCultureProvider : Microsoft.AspNetCore.Localization.RequestCultureProvider { public override System.Threading.Tasks.Task DetermineProviderCultureResult(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; @@ -99,7 +90,6 @@ namespace Microsoft public string UIQueryStringKey { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Localization.RequestCulture` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestCulture { public System.Globalization.CultureInfo Culture { get => throw null; } @@ -110,7 +100,6 @@ namespace Microsoft public System.Globalization.CultureInfo UICulture { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Localization.RequestCultureFeature` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestCultureFeature : Microsoft.AspNetCore.Localization.IRequestCultureFeature { public Microsoft.AspNetCore.Localization.IRequestCultureProvider Provider { get => throw null; } @@ -118,7 +107,6 @@ namespace Microsoft public RequestCultureFeature(Microsoft.AspNetCore.Localization.RequestCulture requestCulture, Microsoft.AspNetCore.Localization.IRequestCultureProvider provider) => throw null; } - // Generated from `Microsoft.AspNetCore.Localization.RequestCultureProvider` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RequestCultureProvider : Microsoft.AspNetCore.Localization.IRequestCultureProvider { public abstract System.Threading.Tasks.Task DetermineProviderCultureResult(Microsoft.AspNetCore.Http.HttpContext httpContext); @@ -127,7 +115,6 @@ namespace Microsoft protected RequestCultureProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestLocalizationMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -140,7 +127,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.RequestLocalizationServiceCollectionExtensions` in `Microsoft.AspNetCore.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestLocalizationServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRequestLocalization(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Metadata.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Metadata.cs index 1090c4a6dcf..be7d524d89e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Metadata.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Metadata.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Metadata, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,12 +7,10 @@ namespace Microsoft { namespace Authorization { - // Generated from `Microsoft.AspNetCore.Authorization.IAllowAnonymous` in `Microsoft.AspNetCore.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAllowAnonymous { } - // Generated from `Microsoft.AspNetCore.Authorization.IAuthorizeData` in `Microsoft.AspNetCore.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizeData { string AuthenticationSchemes { get; set; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Abstractions.cs index 796013c42ac..a54fc4ec29d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Mvc { - // Generated from `Microsoft.AspNetCore.Mvc.ActionContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionContext { public ActionContext() => throw null; @@ -19,13 +19,11 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteData RouteData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.IActionResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionResult { System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.IUrlHelper` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUrlHelper { string Action(Microsoft.AspNetCore.Mvc.Routing.UrlActionContext actionContext); @@ -38,7 +36,6 @@ namespace Microsoft namespace Abstractions { - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionDescriptor { public System.Collections.Generic.IList ActionConstraints { get => throw null; set => throw null; } @@ -54,21 +51,18 @@ namespace Microsoft public System.Collections.Generic.IDictionary RouteValues { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptorExtensions` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ActionDescriptorExtensions { public static T GetProperty(this Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor actionDescriptor) => throw null; public static void SetProperty(this Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor actionDescriptor, T value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptorProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionDescriptorProviderContext { public ActionDescriptorProviderContext() => throw null; public System.Collections.Generic.IList Results { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.ActionInvokerProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionInvokerProviderContext { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -76,7 +70,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Abstractions.IActionInvoker Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.IActionDescriptorProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionDescriptorProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptorProviderContext context); @@ -84,13 +77,11 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.IActionInvoker` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionInvoker { System.Threading.Tasks.Task InvokeAsync(); } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.IActionInvokerProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionInvokerProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.Abstractions.ActionInvokerProviderContext context); @@ -98,7 +89,6 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ParameterDescriptor { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { get => throw null; set => throw null; } @@ -110,7 +100,6 @@ namespace Microsoft } namespace ActionConstraints { - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionConstraintContext { public ActionConstraintContext() => throw null; @@ -119,7 +108,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteContext RouteContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintItem` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionConstraintItem { public ActionConstraintItem(Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata metadata) => throw null; @@ -128,7 +116,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata Metadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionConstraintProviderContext { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor Action { get => throw null; } @@ -137,7 +124,6 @@ namespace Microsoft public System.Collections.Generic.IList Results { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.ActionSelectorCandidate` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ActionSelectorCandidate { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor Action { get => throw null; } @@ -146,26 +132,22 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList Constraints { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionConstraint : Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata { bool Accept(Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintContext context); int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionConstraintFactory : Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata { Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint CreateInstance(System.IServiceProvider services); bool IsReusable { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionConstraintMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionConstraintProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintProviderContext context); @@ -176,7 +158,6 @@ namespace Microsoft } namespace ApiExplorer { - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescription { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; set => throw null; } @@ -190,7 +171,6 @@ namespace Microsoft public System.Collections.Generic.IList SupportedResponseTypes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescriptionProviderContext { public System.Collections.Generic.IReadOnlyList Actions { get => throw null; } @@ -198,7 +178,6 @@ namespace Microsoft public System.Collections.Generic.IList Results { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterDescription` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiParameterDescription { public ApiParameterDescription() => throw null; @@ -213,7 +192,6 @@ namespace Microsoft public System.Type Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiParameterRouteInfo` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiParameterRouteInfo { public ApiParameterRouteInfo() => throw null; @@ -222,7 +200,6 @@ namespace Microsoft public bool IsOptional { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiRequestFormat` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiRequestFormat { public ApiRequestFormat() => throw null; @@ -230,7 +207,6 @@ namespace Microsoft public string MediaType { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiResponseFormat` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiResponseFormat { public ApiResponseFormat() => throw null; @@ -238,7 +214,6 @@ namespace Microsoft public string MediaType { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiResponseType` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiResponseType { public System.Collections.Generic.IList ApiResponseFormats { get => throw null; set => throw null; } @@ -249,7 +224,6 @@ namespace Microsoft public System.Type Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiDescriptionProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionProviderContext context); @@ -260,7 +234,6 @@ namespace Microsoft } namespace Authorization { - // Generated from `Microsoft.AspNetCore.Mvc.Authorization.IAllowAnonymousFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAllowAnonymousFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } @@ -268,7 +241,6 @@ namespace Microsoft } namespace Filters { - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionExecutedContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public ActionExecutedContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, object controller) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) => throw null; @@ -280,7 +252,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionExecutingContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual System.Collections.Generic.IDictionary ActionArguments { get => throw null; } @@ -289,17 +260,14 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task ActionExecutionDelegate(); - // Generated from `Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizationFilterContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public AuthorizationFilterContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) => throw null; public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ExceptionContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExceptionContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual System.Exception Exception { get => throw null; set => throw null; } @@ -309,7 +277,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FilterContext : Microsoft.AspNetCore.Mvc.ActionContext { public FilterContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters) => throw null; @@ -318,7 +285,6 @@ namespace Microsoft public bool IsEffectivePolicy(TMetadata policy) where TMetadata : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterDescriptor` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FilterDescriptor { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata Filter { get => throw null; } @@ -327,7 +293,6 @@ namespace Microsoft public int Scope { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterItem` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FilterItem { public Microsoft.AspNetCore.Mvc.Filters.FilterDescriptor Descriptor { get => throw null; } @@ -337,7 +302,6 @@ namespace Microsoft public bool IsReusable { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FilterProviderContext { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; set => throw null; } @@ -345,84 +309,70 @@ namespace Microsoft public System.Collections.Generic.IList Results { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnActionExecuted(Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext context); void OnActionExecuting(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAlwaysRunResultFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAlwaysRunResultFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IResultFilter { } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncActionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnActionExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext context, Microsoft.AspNetCore.Mvc.Filters.ActionExecutionDelegate next); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncAlwaysRunResultFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncAlwaysRunResultFilter : Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncAuthorizationFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncAuthorizationFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnAuthorizationAsync(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncExceptionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncExceptionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnExceptionAsync(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncResourceFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncResourceFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnResourceExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext context, Microsoft.AspNetCore.Mvc.Filters.ResourceExecutionDelegate next); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncResultFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnResultExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext context, Microsoft.AspNetCore.Mvc.Filters.ResultExecutionDelegate next); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAuthorizationFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnAuthorization(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IExceptionFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IExceptionFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnException(Microsoft.AspNetCore.Mvc.Filters.ExceptionContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterContainer` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFilterContainer { Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata FilterDefinition { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFilterFactory : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider); bool IsReusable { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IFilterProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFilterProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.Filters.FilterProviderContext context); @@ -430,27 +380,23 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOrderedFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IResourceFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResourceFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnResourceExecuted(Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext context); void OnResourceExecuting(Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IResultFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResultFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnResultExecuted(Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext context); void OnResultExecuting(Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceExecutedContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual bool Canceled { get => throw null; set => throw null; } @@ -461,7 +407,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceExecutingContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public ResourceExecutingContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, System.Collections.Generic.IList valueProviderFactories) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) => throw null; @@ -469,10 +414,8 @@ namespace Microsoft public System.Collections.Generic.IList ValueProviderFactories { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResourceExecutionDelegate` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task ResourceExecutionDelegate(); - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResultExecutedContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual bool Canceled { get => throw null; set => throw null; } @@ -484,7 +427,6 @@ namespace Microsoft public ResultExecutedContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, Microsoft.AspNetCore.Mvc.IActionResult result, object controller) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResultExecutingContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual bool Cancel { get => throw null; set => throw null; } @@ -493,13 +435,11 @@ namespace Microsoft public ResultExecutingContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, System.Collections.Generic.IList filters, Microsoft.AspNetCore.Mvc.IActionResult result, object controller) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(System.Collections.Generic.IList)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResultExecutionDelegate` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task ResultExecutionDelegate(); } namespace Formatters { - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.FormatterCollection<>` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormatterCollection : System.Collections.ObjectModel.Collection { public FormatterCollection() => throw null; @@ -508,27 +448,23 @@ namespace Microsoft public void RemoveType() where T : TFormatter => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IInputFormatter { bool CanRead(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext context); System.Threading.Tasks.Task ReadAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IInputFormatterExceptionPolicy { Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy ExceptionPolicy { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOutputFormatter { bool CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context); System.Threading.Tasks.Task WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputFormatterContext { public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; } @@ -542,7 +478,6 @@ namespace Microsoft public bool TreatEmptyInputAsDefaultValue { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.InputFormatterException` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputFormatterException : System.Exception { public InputFormatterException() => throw null; @@ -550,14 +485,12 @@ namespace Microsoft public InputFormatterException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum InputFormatterExceptionPolicy : int { AllExceptions = 0, MalformedInputExceptions = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.InputFormatterResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputFormatterResult { public static Microsoft.AspNetCore.Mvc.Formatters.InputFormatterResult Failure() => throw null; @@ -571,7 +504,6 @@ namespace Microsoft public static System.Threading.Tasks.Task SuccessAsync(object model) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class OutputFormatterCanWriteContext { public virtual Microsoft.Extensions.Primitives.StringSegment ContentType { get => throw null; set => throw null; } @@ -582,7 +514,6 @@ namespace Microsoft protected OutputFormatterCanWriteContext(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OutputFormatterWriteContext : Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext { public OutputFormatterWriteContext(Microsoft.AspNetCore.Http.HttpContext httpContext, System.Func writerFactory, System.Type objectType, object @object) : base(default(Microsoft.AspNetCore.Http.HttpContext)) => throw null; @@ -592,7 +523,6 @@ namespace Microsoft } namespace ModelBinding { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingInfo { public string BinderModelName { get => throw null; set => throw null; } @@ -608,7 +538,6 @@ namespace Microsoft public bool TryApplyBindingInfo(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingSource : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s1, Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource s2) => throw null; @@ -634,7 +563,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource Special; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeBindingSource : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource { private CompositeBindingSource() : base(default(string), default(string), default(bool), default(bool)) => throw null; @@ -643,7 +571,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Mvc.ModelBinding.CompositeBindingSource Create(System.Collections.Generic.IEnumerable bindingSources, string displayName) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum EmptyBodyBehavior : int { Allow = 1, @@ -651,7 +578,6 @@ namespace Microsoft Disallow = 2, } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.EnumGroupAndName` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct EnumGroupAndName { // Stub generator skipped constructor @@ -661,75 +587,63 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBinderTypeProviderMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBinderTypeProviderMetadata : Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata { System.Type BinderType { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBindingSourceMetadata { Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IConfigureEmptyBodyBehavior` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IConfigureEmptyBodyBehavior { Microsoft.AspNetCore.Mvc.ModelBinding.EmptyBodyBehavior EmptyBodyBehavior { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelBinder { System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelBinderProvider { Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelMetadataProvider { System.Collections.Generic.IEnumerable GetMetadataForProperties(System.Type modelType); Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata GetMetadataForType(System.Type modelType); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelNameProvider { string Name { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPropertyFilterProvider { System.Func PropertyFilter { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IRequestPredicateProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestPredicateProvider { System.Func RequestPredicate { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValueProvider { bool ContainsPrefix(string prefix); Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult GetValue(string key); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValueProviderFactory { System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelBinderProviderContext { public abstract Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { get; } @@ -741,10 +655,8 @@ namespace Microsoft public virtual System.IServiceProvider Services { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelBindingContext { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext+NestedScope` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct NestedScope : System.IDisposable { public void Dispose() => throw null; @@ -775,7 +687,6 @@ namespace Microsoft public abstract Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider ValueProvider { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ModelBindingResult : System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult x, Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult y) => throw null; @@ -791,7 +702,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelError` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelError { public string ErrorMessage { get => throw null; } @@ -801,7 +711,6 @@ namespace Microsoft public ModelError(string errorMessage) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelErrorCollection` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelErrorCollection : System.Collections.ObjectModel.Collection { public void Add(System.Exception exception) => throw null; @@ -809,7 +718,6 @@ namespace Microsoft public ModelErrorCollection() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelMetadata : Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider, System.IEquatable { public abstract System.Collections.Generic.IReadOnlyDictionary AdditionalValues { get; } @@ -878,7 +786,6 @@ namespace Microsoft public abstract System.Collections.Generic.IReadOnlyList ValidatorMetadata { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadataProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider { public virtual Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata GetMetadataForConstructor(System.Reflection.ConstructorInfo constructor, System.Type modelType) => throw null; @@ -890,17 +797,14 @@ namespace Microsoft protected ModelMetadataProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelPropertyCollection` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelPropertyCollection : System.Collections.ObjectModel.ReadOnlyCollection { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata this[string propertyName] { get => throw null; } public ModelPropertyCollection(System.Collections.Generic.IEnumerable properties) : base(default(System.Collections.Generic.IList)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelStateDictionary : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+Enumerator` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -913,7 +817,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+KeyEnumerable` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct KeyEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.KeyEnumerator GetEnumerator() => throw null; @@ -924,7 +827,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+KeyEnumerator` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct KeyEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public string Current { get => throw null; } @@ -937,7 +839,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+PrefixEnumerable` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PrefixEnumerable : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.Enumerator GetEnumerator() => throw null; @@ -948,7 +849,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+ValueEnumerable` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ValueEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary.ValueEnumerator GetEnumerator() => throw null; @@ -959,7 +859,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary+ValueEnumerator` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ValueEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry Current { get => throw null; } @@ -1012,7 +911,6 @@ namespace Microsoft System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateEntry` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelStateEntry { public string AttemptedValue { get => throw null; set => throw null; } @@ -1025,7 +923,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState ValidationState { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelValidationState` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ModelValidationState : int { Invalid = 1, @@ -1034,20 +931,17 @@ namespace Microsoft Valid = 2, } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.TooManyModelErrorsException` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TooManyModelErrorsException : System.Exception { public TooManyModelErrorsException(string message) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderException` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValueProviderException : System.Exception { public ValueProviderException(string message) => throw null; public ValueProviderException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValueProviderFactoryContext { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -1055,7 +949,6 @@ namespace Microsoft public System.Collections.Generic.IList ValueProviders { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ValueProviderResult : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.IEquatable { public static bool operator !=(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult x, Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult y) => throw null; @@ -1080,7 +973,6 @@ namespace Microsoft namespace Metadata { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelBindingMessageProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ModelBindingMessageProvider { public virtual System.Func AttemptedValueIsInvalidAccessor { get => throw null; } @@ -1097,7 +989,6 @@ namespace Microsoft public virtual System.Func ValueMustNotBeNullAccessor { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataIdentity` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ModelMetadataIdentity : System.IEquatable { public System.Reflection.ConstructorInfo ConstructorInfo { get => throw null; } @@ -1119,7 +1010,6 @@ namespace Microsoft public System.Reflection.PropertyInfo PropertyInfo { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelMetadataKind` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ModelMetadataKind : int { Constructor = 3, @@ -1131,14 +1021,12 @@ namespace Microsoft } namespace Validation { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientModelValidationContext : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase { public System.Collections.Generic.IDictionary Attributes { get => throw null; } public ClientModelValidationContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, System.Collections.Generic.IDictionary attributes) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata), default(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorItem` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientValidatorItem { public ClientValidatorItem() => throw null; @@ -1148,7 +1036,6 @@ namespace Microsoft public object ValidatorMetadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientValidatorProviderContext { public ClientValidatorProviderContext(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata, System.Collections.Generic.IList items) => throw null; @@ -1157,43 +1044,36 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList ValidatorMetadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClientModelValidator { void AddValidation(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidatorProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClientModelValidatorProvider { void CreateValidators(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidator` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelValidator { System.Collections.Generic.IEnumerable Validate(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelValidatorProvider { void CreateValidators(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidatorProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPropertyValidationFilter { bool ShouldValidateEntry(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry entry, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry parentEntry); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IValidationStrategy` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValidationStrategy { System.Collections.Generic.IEnumerator GetChildren(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, string key, object model); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelValidationContext : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase { public object Container { get => throw null; } @@ -1201,7 +1081,6 @@ namespace Microsoft public ModelValidationContext(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, object container, object model) : base(default(Microsoft.AspNetCore.Mvc.ActionContext), default(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata), default(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelValidationContextBase { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -1210,7 +1089,6 @@ namespace Microsoft public ModelValidationContextBase(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata modelMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationResult` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelValidationResult { public string MemberName { get => throw null; } @@ -1218,7 +1096,6 @@ namespace Microsoft public ModelValidationResult(string memberName, string message) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidatorProviderContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelValidatorProviderContext { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata ModelMetadata { get => throw null; set => throw null; } @@ -1227,7 +1104,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList ValidatorMetadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ValidationEntry { public string Key { get => throw null; } @@ -1238,7 +1114,6 @@ namespace Microsoft public ValidationEntry(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, string key, object model) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationStateDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { public void Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -1264,7 +1139,6 @@ namespace Microsoft System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateEntry` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationStateEntry { public string Key { get => throw null; set => throw null; } @@ -1274,7 +1148,6 @@ namespace Microsoft public ValidationStateEntry() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidatorItem` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidatorItem { public bool IsReusable { get => throw null; set => throw null; } @@ -1288,7 +1161,6 @@ namespace Microsoft } namespace Routing { - // Generated from `Microsoft.AspNetCore.Mvc.Routing.AttributeRouteInfo` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AttributeRouteInfo { public AttributeRouteInfo() => throw null; @@ -1299,7 +1171,6 @@ namespace Microsoft public string Template { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.UrlActionContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlActionContext { public string Action { get => throw null; set => throw null; } @@ -1311,7 +1182,6 @@ namespace Microsoft public object Values { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.UrlRouteContext` in `Microsoft.AspNetCore.Mvc.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlRouteContext { public string Fragment { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ApiExplorer.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ApiExplorer.cs index 6072fcb9410..4da9d47995d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ApiExplorer.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ApiExplorer.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,14 +9,12 @@ namespace Microsoft { namespace ApiExplorer { - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionExtensions` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ApiDescriptionExtensions { public static T GetProperty(this Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription apiDescription) => throw null; public static void SetProperty(this Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescription apiDescription, T value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroup` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescriptionGroup { public ApiDescriptionGroup(string groupName, System.Collections.Generic.IReadOnlyList items) => throw null; @@ -23,7 +22,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList Items { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroupCollection` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescriptionGroupCollection { public ApiDescriptionGroupCollection(System.Collections.Generic.IReadOnlyList items, int version) => throw null; @@ -31,14 +29,12 @@ namespace Microsoft public int Version { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroupCollectionProvider` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescriptionGroupCollectionProvider : Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupCollectionProvider { public ApiDescriptionGroupCollectionProvider(Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider actionDescriptorCollectionProvider, System.Collections.Generic.IEnumerable apiDescriptionProviders) => throw null; public Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroupCollection ApiDescriptionGroups { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.DefaultApiDescriptionProvider` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultApiDescriptionProvider : Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionProvider { public DefaultApiDescriptionProvider(Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.AspNetCore.Routing.IInlineConstraintResolver constraintResolver, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultTypeMapper mapper, Microsoft.Extensions.Options.IOptions routeOptions) => throw null; @@ -47,7 +43,6 @@ namespace Microsoft public int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupCollectionProvider` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiDescriptionGroupCollectionProvider { Microsoft.AspNetCore.Mvc.ApiExplorer.ApiDescriptionGroupCollection ApiDescriptionGroups { get; } @@ -60,13 +55,11 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.EndpointMetadataApiExplorerServiceCollectionExtensions` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EndpointMetadataApiExplorerServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddEndpointsApiExplorer(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcApiExplorerMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.ApiExplorer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcApiExplorerMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddApiExplorer(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Core.cs index 528a1c9ef1f..f4223ac690f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Core.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ControllerActionEndpointConventionBuilder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerActionEndpointConventionBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ControllerEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ControllerEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.ControllerActionEndpointConventionBuilder MapAreaControllerRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string name, string areaName, string pattern, object defaults = default(object), object constraints = default(object), object dataTokens = default(object)) => throw null; @@ -28,7 +28,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToController(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, string action, string controller) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.MvcApplicationBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcApplicationBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseMvc(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -36,7 +35,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseMvcWithDefaultRoute(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.MvcAreaRouteBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcAreaRouteBuilderExtensions { public static Microsoft.AspNetCore.Routing.IRouteBuilder MapAreaRoute(this Microsoft.AspNetCore.Routing.IRouteBuilder routeBuilder, string name, string areaName, string template) => throw null; @@ -48,7 +46,6 @@ namespace Microsoft } namespace Mvc { - // Generated from `Microsoft.AspNetCore.Mvc.AcceptVerbsAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AcceptVerbsAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider { public AcceptVerbsAttribute(params string[] methods) => throw null; @@ -61,7 +58,6 @@ namespace Microsoft string Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider.Template { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.AcceptedAtActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AcceptedAtActionResult : Microsoft.AspNetCore.Mvc.ObjectResult { public AcceptedAtActionResult(string actionName, string controllerName, object routeValues, object value) : base(default(object)) => throw null; @@ -72,7 +68,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.AcceptedAtRouteResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AcceptedAtRouteResult : Microsoft.AspNetCore.Mvc.ObjectResult { public AcceptedAtRouteResult(object routeValues, object value) : base(default(object)) => throw null; @@ -83,7 +78,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.AcceptedResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AcceptedResult : Microsoft.AspNetCore.Mvc.ObjectResult { public AcceptedResult() : base(default(object)) => throw null; @@ -93,20 +87,17 @@ namespace Microsoft public override void OnFormatting(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ActionContextAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionContextAttribute : System.Attribute { public ActionContextAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ActionNameAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionNameAttribute : System.Attribute { public ActionNameAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ActionResult : Microsoft.AspNetCore.Mvc.IActionResult { protected ActionResult() => throw null; @@ -114,7 +105,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ActionResult<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionResult : Microsoft.AspNetCore.Mvc.Infrastructure.IConvertToActionResult { public ActionResult(Microsoft.AspNetCore.Mvc.ActionResult result) => throw null; @@ -126,17 +116,16 @@ namespace Microsoft public static implicit operator Microsoft.AspNetCore.Mvc.ActionResult(TValue value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.AntiforgeryValidationFailedResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AntiforgeryValidationFailedResult : Microsoft.AspNetCore.Mvc.BadRequestResult, Microsoft.AspNetCore.Mvc.Core.Infrastructure.IAntiforgeryValidationFailedResult, Microsoft.AspNetCore.Mvc.IActionResult { public AntiforgeryValidationFailedResult() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApiBehaviorOptions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiBehaviorOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public ApiBehaviorOptions() => throw null; public System.Collections.Generic.IDictionary ClientErrorMapping { get => throw null; } + public bool DisableImplicitFromServicesParameters { get => throw null; set => throw null; } System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; public System.Func InvalidModelStateResponseFactory { get => throw null; set => throw null; } @@ -146,34 +135,29 @@ namespace Microsoft public bool SuppressModelStateInvalidFilter { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiControllerAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiControllerAttribute : Microsoft.AspNetCore.Mvc.ControllerAttribute, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Infrastructure.IApiBehaviorMetadata { public ApiControllerAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApiConventionMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionMethodAttribute : System.Attribute { public ApiConventionMethodAttribute(System.Type conventionType, string methodName) => throw null; public System.Type ConventionType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiConventionTypeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionTypeAttribute : System.Attribute { public ApiConventionTypeAttribute(System.Type conventionType) => throw null; public System.Type ConventionType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiDescriptionActionData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiDescriptionActionData { public ApiDescriptionActionData() => throw null; public string GroupName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorerSettingsAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiExplorerSettingsAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupNameProvider, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionVisibilityProvider { public ApiExplorerSettingsAttribute() => throw null; @@ -181,26 +165,22 @@ namespace Microsoft public bool IgnoreApi { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.AreaAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AreaAttribute : Microsoft.AspNetCore.Mvc.Routing.RouteValueAttribute { public AreaAttribute(string areaName) : base(default(string), default(string)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.BadRequestObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BadRequestObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public BadRequestObjectResult(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) : base(default(object)) => throw null; public BadRequestObjectResult(object error) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.BadRequestResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BadRequestResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public BadRequestResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.BindAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider { public BindAttribute(params string[] include) => throw null; @@ -210,14 +190,12 @@ namespace Microsoft public System.Func PropertyFilter { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.BindPropertiesAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindPropertiesAttribute : System.Attribute { public BindPropertiesAttribute() => throw null; public bool SupportsGet { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.BindPropertyAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindPropertyAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBinderTypeProviderMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IRequestPredicateProvider { public BindPropertyAttribute() => throw null; @@ -228,7 +206,6 @@ namespace Microsoft public bool SupportsGet { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.CacheProfile` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheProfile { public CacheProfile() => throw null; @@ -239,7 +216,6 @@ namespace Microsoft public string[] VaryByQueryKeys { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ChallengeResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ChallengeResult : Microsoft.AspNetCore.Mvc.ActionResult { public System.Collections.Generic.IList AuthenticationSchemes { get => throw null; set => throw null; } @@ -253,7 +229,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ClientErrorData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientErrorData { public ClientErrorData() => throw null; @@ -261,7 +236,6 @@ namespace Microsoft public string Title { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.CompatibilityVersion` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum CompatibilityVersion : int { Latest = 2147483647, @@ -271,20 +245,17 @@ namespace Microsoft Version_3_0 = 3, } - // Generated from `Microsoft.AspNetCore.Mvc.ConflictObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConflictObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public ConflictObjectResult(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) : base(default(object)) => throw null; public ConflictObjectResult(object error) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ConflictResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConflictResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public ConflictResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ConsumesAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsumesAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IAcceptsMetadata, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiRequestMetadataProvider, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IResourceFilter { public bool Accept(Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintContext context) => throw null; @@ -301,7 +272,6 @@ namespace Microsoft public void SetContentTypes(Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection contentTypes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ContentResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ContentResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public string Content { get => throw null; set => throw null; } @@ -311,13 +281,11 @@ namespace Microsoft public int? StatusCode { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ControllerAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerAttribute : System.Attribute { public ControllerAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ControllerBase` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ControllerBase { public virtual Microsoft.AspNetCore.Mvc.AcceptedResult Accepted() => throw null; @@ -361,6 +329,7 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.CreatedAtRouteResult CreatedAtRoute(object routeValues, object value) => throw null; public virtual Microsoft.AspNetCore.Mvc.CreatedAtRouteResult CreatedAtRoute(string routeName, object value) => throw null; public virtual Microsoft.AspNetCore.Mvc.CreatedAtRouteResult CreatedAtRoute(string routeName, object routeValues, object value) => throw null; + public static Microsoft.AspNetCore.Mvc.EmptyResult Empty { get => throw null; } public virtual Microsoft.AspNetCore.Mvc.FileContentResult File(System.Byte[] fileContents, string contentType) => throw null; public virtual Microsoft.AspNetCore.Mvc.FileContentResult File(System.Byte[] fileContents, string contentType, System.DateTimeOffset? lastModified, Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag) => throw null; public virtual Microsoft.AspNetCore.Mvc.FileContentResult File(System.Byte[] fileContents, string contentType, System.DateTimeOffset? lastModified, Microsoft.Net.Http.Headers.EntityTagHeaderValue entityTag, bool enableRangeProcessing) => throw null; @@ -494,7 +463,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.ActionResult ValidationProblem(string detail = default(string), string instance = default(string), int? statusCode = default(int?), string title = default(string), string type = default(string), Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelStateDictionary = default(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ControllerContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerContext : Microsoft.AspNetCore.Mvc.ActionContext { public Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor ActionDescriptor { get => throw null; set => throw null; } @@ -503,13 +471,11 @@ namespace Microsoft public virtual System.Collections.Generic.IList ValueProviderFactories { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ControllerContextAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerContextAttribute : System.Attribute { public ControllerContextAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.CreatedAtActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CreatedAtActionResult : Microsoft.AspNetCore.Mvc.ObjectResult { public string ActionName { get => throw null; set => throw null; } @@ -520,7 +486,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.CreatedAtRouteResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CreatedAtRouteResult : Microsoft.AspNetCore.Mvc.ObjectResult { public CreatedAtRouteResult(object routeValues, object value) : base(default(object)) => throw null; @@ -531,7 +496,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.CreatedResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CreatedResult : Microsoft.AspNetCore.Mvc.ObjectResult { public CreatedResult(System.Uri location, object value) : base(default(object)) => throw null; @@ -540,7 +504,6 @@ namespace Microsoft public override void OnFormatting(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DefaultApiConventions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DefaultApiConventions { public static void Create(object model) => throw null; @@ -553,23 +516,21 @@ namespace Microsoft public static void Update(object id, object model) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DisableRequestSizeLimitAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class DisableRequestSizeLimitAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter + public class DisableRequestSizeLimitAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IRequestSizeLimitMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; public DisableRequestSizeLimitAttribute() => throw null; public bool IsReusable { get => throw null; } + System.Int64? Microsoft.AspNetCore.Http.Metadata.IRequestSizeLimitMetadata.MaxRequestBodySize { get => throw null; } public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.EmptyResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EmptyResult : Microsoft.AspNetCore.Mvc.ActionResult { public EmptyResult() => throw null; public override void ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.FileContentResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileContentResult : Microsoft.AspNetCore.Mvc.FileResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -578,7 +539,6 @@ namespace Microsoft public System.Byte[] FileContents { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FileResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FileResult : Microsoft.AspNetCore.Mvc.ActionResult { public string ContentType { get => throw null; } @@ -589,7 +549,6 @@ namespace Microsoft public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FileStreamResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileStreamResult : Microsoft.AspNetCore.Mvc.FileResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -598,7 +557,6 @@ namespace Microsoft public FileStreamResult(System.IO.Stream fileStream, string contentType) : base(default(string)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ForbidResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ForbidResult : Microsoft.AspNetCore.Mvc.ActionResult { public System.Collections.Generic.IList AuthenticationSchemes { get => throw null; set => throw null; } @@ -612,7 +570,6 @@ namespace Microsoft public Microsoft.AspNetCore.Authentication.AuthenticationProperties Properties { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FormatFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormatFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; @@ -620,7 +577,6 @@ namespace Microsoft public bool IsReusable { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FromBodyAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FromBodyAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromBodyMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata { bool Microsoft.AspNetCore.Http.Metadata.IFromBodyMetadata.AllowEmpty { get => throw null; } @@ -629,15 +585,13 @@ namespace Microsoft public FromBodyAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.FromFormAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class FromFormAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider + public class FromFormAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromFormMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } public FromFormAttribute() => throw null; public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FromHeaderAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FromHeaderAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromHeaderMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } @@ -645,7 +599,6 @@ namespace Microsoft public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FromQueryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FromQueryAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromQueryMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } @@ -653,7 +606,6 @@ namespace Microsoft public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FromRouteAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FromRouteAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromRouteMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } @@ -661,79 +613,67 @@ namespace Microsoft public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.FromServicesAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FromServicesAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IFromServiceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } public FromServicesAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpDeleteAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpDeleteAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpDeleteAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpDeleteAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpGetAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpGetAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpGetAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpGetAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpHeadAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpHeadAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpHeadAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpHeadAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpOptionsAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpOptionsAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpOptionsAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpOptionsAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpPatchAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpPatchAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpPatchAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpPatchAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpPostAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpPostAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpPostAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpPostAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.HttpPutAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpPutAttribute : Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute { public HttpPutAttribute() : base(default(System.Collections.Generic.IEnumerable)) => throw null; public HttpPutAttribute(string template) : base(default(System.Collections.Generic.IEnumerable)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.IDesignTimeMvcBuilderConfiguration` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDesignTimeMvcBuilderConfiguration { void ConfigureMvc(Microsoft.Extensions.DependencyInjection.IMvcBuilder builder); } - // Generated from `Microsoft.AspNetCore.Mvc.IRequestFormLimitsPolicy` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestFormLimitsPolicy : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.IRequestSizePolicy` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRequestSizePolicy : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.JsonOptions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonOptions { public bool AllowInputFormatterExceptionMessages { get => throw null; set => throw null; } @@ -741,7 +681,6 @@ namespace Microsoft public System.Text.Json.JsonSerializerOptions JsonSerializerOptions { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.JsonResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public string ContentType { get => throw null; set => throw null; } @@ -753,7 +692,6 @@ namespace Microsoft public object Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.LocalRedirectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocalRedirectResult : Microsoft.AspNetCore.Mvc.ActionResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -766,7 +704,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.MiddlewareFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MiddlewareFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public System.Type ConfigurationType { get => throw null; } @@ -776,7 +713,6 @@ namespace Microsoft public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinderAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelBinderAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.IBinderTypeProviderMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.IModelNameProvider { public System.Type BinderType { get => throw null; set => throw null; } @@ -786,14 +722,12 @@ namespace Microsoft public string Name { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelMetadataTypeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelMetadataTypeAttribute : System.Attribute { public System.Type MetadataType { get => throw null; } public ModelMetadataTypeAttribute(System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.MvcOptions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public bool AllowEmptyInputInBodyModelBinding { get => throw null; set => throw null; } @@ -829,43 +763,36 @@ namespace Microsoft public System.Collections.Generic.IList ValueProviderFactories { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.NoContentResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NoContentResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public NoContentResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.NonActionAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NonActionAttribute : System.Attribute { public NonActionAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.NonControllerAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NonControllerAttribute : System.Attribute { public NonControllerAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.NonViewComponentAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NonViewComponentAttribute : System.Attribute { public NonViewComponentAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.NotFoundObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NotFoundObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public NotFoundObjectResult(object value) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.NotFoundResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NotFoundResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public NotFoundResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ObjectResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection ContentTypes { get => throw null; set => throw null; } @@ -878,19 +805,16 @@ namespace Microsoft public object Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.OkObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OkObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public OkObjectResult(object value) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.OkResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OkResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public OkResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.PhysicalFileResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalFileResult : Microsoft.AspNetCore.Mvc.FileResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -899,7 +823,6 @@ namespace Microsoft public PhysicalFileResult(string fileName, string contentType) : base(default(string)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ProducesAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProducesAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseMetadataProvider, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IResultFilter { public Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection ContentTypes { get => throw null; set => throw null; } @@ -913,7 +836,6 @@ namespace Microsoft public System.Type Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ProducesDefaultResponseTypeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProducesDefaultResponseTypeAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDefaultResponseMetadataProvider, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseMetadataProvider, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { public ProducesDefaultResponseTypeAttribute() => throw null; @@ -923,14 +845,12 @@ namespace Microsoft public System.Type Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ProducesErrorResponseTypeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProducesErrorResponseTypeAttribute : System.Attribute { public ProducesErrorResponseTypeAttribute(System.Type type) => throw null; public System.Type Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ProducesResponseTypeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProducesResponseTypeAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseMetadataProvider, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { public ProducesResponseTypeAttribute(System.Type type, int statusCode) => throw null; @@ -941,7 +861,6 @@ namespace Microsoft public System.Type Type { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RedirectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -954,7 +873,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RedirectToActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToActionResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult { public string ActionName { get => throw null; set => throw null; } @@ -973,7 +891,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RedirectToPageResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToPageResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -997,7 +914,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RedirectToRouteResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToRouteResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -1016,7 +932,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IUrlHelper UrlHelper { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RequestFormLimitsAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequestFormLimitsAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public bool BufferBody { get => throw null; set => throw null; } @@ -1035,16 +950,15 @@ namespace Microsoft public int ValueLengthLimit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RequestSizeLimitAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class RequestSizeLimitAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter + public class RequestSizeLimitAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.IRequestSizeLimitMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; public bool IsReusable { get => throw null; } + System.Int64? Microsoft.AspNetCore.Http.Metadata.IRequestSizeLimitMetadata.MaxRequestBodySize { get => throw null; } public int Order { get => throw null; set => throw null; } public RequestSizeLimitAttribute(System.Int64 bytes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RequireHttpsAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequireHttpsAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IAuthorizationFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { protected virtual void HandleNonHttpsRequest(Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext filterContext) => throw null; @@ -1054,7 +968,6 @@ namespace Microsoft public RequireHttpsAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ResponseCacheAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCacheAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public string CacheProfileName { get => throw null; set => throw null; } @@ -1070,7 +983,6 @@ namespace Microsoft public string[] VaryByQueryKeys { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ResponseCacheLocation` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ResponseCacheLocation : int { Any = 0, @@ -1078,7 +990,6 @@ namespace Microsoft None = 2, } - // Generated from `Microsoft.AspNetCore.Mvc.RouteAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider { public string Name { get => throw null; set => throw null; } @@ -1088,14 +999,12 @@ namespace Microsoft public string Template { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.SerializableError` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SerializableError : System.Collections.Generic.Dictionary { public SerializableError() => throw null; public SerializableError(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ServiceFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; @@ -1105,7 +1014,6 @@ namespace Microsoft public System.Type ServiceType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.SignInResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SignInResult : Microsoft.AspNetCore.Mvc.ActionResult { public string AuthenticationScheme { get => throw null; set => throw null; } @@ -1118,7 +1026,6 @@ namespace Microsoft public SignInResult(string authenticationScheme, System.Security.Claims.ClaimsPrincipal principal, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.SignOutResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SignOutResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Http.IResult { public System.Collections.Generic.IList AuthenticationSchemes { get => throw null; set => throw null; } @@ -1133,7 +1040,6 @@ namespace Microsoft public SignOutResult(string authenticationScheme, Microsoft.AspNetCore.Authentication.AuthenticationProperties properties) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.StatusCodeResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StatusCodeResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IClientErrorActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public override void ExecuteResult(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -1142,7 +1048,6 @@ namespace Microsoft public StatusCodeResult(int statusCode) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TypeFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TypeFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public object[] Arguments { get => throw null; set => throw null; } @@ -1153,38 +1058,32 @@ namespace Microsoft public TypeFilterAttribute(System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UnauthorizedObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnauthorizedObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public UnauthorizedObjectResult(object value) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UnauthorizedResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnauthorizedResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public UnauthorizedResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UnprocessableEntityObjectResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnprocessableEntityObjectResult : Microsoft.AspNetCore.Mvc.ObjectResult { public UnprocessableEntityObjectResult(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) : base(default(object)) => throw null; public UnprocessableEntityObjectResult(object error) : base(default(object)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UnprocessableEntityResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnprocessableEntityResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public UnprocessableEntityResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UnsupportedMediaTypeResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnsupportedMediaTypeResult : Microsoft.AspNetCore.Mvc.StatusCodeResult { public UnsupportedMediaTypeResult() : base(default(int)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.UrlHelperExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UrlHelperExtensions { public static string Action(this Microsoft.AspNetCore.Mvc.IUrlHelper helper) => throw null; @@ -1212,7 +1111,6 @@ namespace Microsoft public static string RouteUrl(this Microsoft.AspNetCore.Mvc.IUrlHelper helper, string routeName, object values, string protocol, string host, string fragment) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ValidationProblemDetails` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationProblemDetails : Microsoft.AspNetCore.Http.HttpValidationProblemDetails { public System.Collections.Generic.IDictionary Errors { get => throw null; } @@ -1221,7 +1119,6 @@ namespace Microsoft public ValidationProblemDetails(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.VirtualFileResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class VirtualFileResult : Microsoft.AspNetCore.Mvc.FileResult { public override System.Threading.Tasks.Task ExecuteResultAsync(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -1233,7 +1130,6 @@ namespace Microsoft namespace ActionConstraints { - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.ActionMethodSelectorAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ActionMethodSelectorAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata { public bool Accept(Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintContext context) => throw null; @@ -1242,7 +1138,6 @@ namespace Microsoft public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.HttpMethodActionConstraint` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodActionConstraint : Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata { public virtual bool Accept(Microsoft.AspNetCore.Mvc.ActionConstraints.ActionConstraintContext context) => throw null; @@ -1252,7 +1147,6 @@ namespace Microsoft public int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ActionConstraints.IConsumesActionConstraint` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IConsumesActionConstraint : Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraint, Microsoft.AspNetCore.Mvc.ActionConstraints.IActionConstraintMetadata { } @@ -1260,14 +1154,12 @@ namespace Microsoft } namespace ApiExplorer { - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionNameMatchAttribute : System.Attribute { public ApiConventionNameMatchAttribute(Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior matchBehavior) => throw null; public Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior MatchBehavior { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionNameMatchBehavior` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ApiConventionNameMatchBehavior : int { Any = 0, @@ -1276,57 +1168,48 @@ namespace Microsoft Suffix = 3, } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionResult { public ApiConventionResult(System.Collections.Generic.IReadOnlyList responseMetadataProviders) => throw null; public System.Collections.Generic.IReadOnlyList ResponseMetadataProviders { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionTypeMatchAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionTypeMatchAttribute : System.Attribute { public ApiConventionTypeMatchAttribute(Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionTypeMatchBehavior matchBehavior) => throw null; public Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionTypeMatchBehavior MatchBehavior { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.ApiConventionTypeMatchBehavior` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ApiConventionTypeMatchBehavior : int { Any = 0, AssignableFrom = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDefaultResponseMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiDefaultResponseMetadataProvider : Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseMetadataProvider, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionGroupNameProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiDescriptionGroupNameProvider { string GroupName { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiDescriptionVisibilityProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiDescriptionVisibilityProvider { bool IgnoreApi { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiRequestFormatMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiRequestFormatMetadataProvider { System.Collections.Generic.IReadOnlyList GetSupportedContentTypes(string contentType, System.Type objectType); } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiRequestMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiRequestMetadataProvider : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void SetContentTypes(Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection contentTypes); } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiResponseMetadataProvider : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void SetContentTypes(Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection contentTypes); @@ -1334,7 +1217,6 @@ namespace Microsoft System.Type Type { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseTypeMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiResponseTypeMetadataProvider { System.Collections.Generic.IReadOnlyList GetSupportedContentTypes(string contentType, System.Type objectType); @@ -1343,7 +1225,6 @@ namespace Microsoft } namespace ApplicationModels { - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionModel : Microsoft.AspNetCore.Mvc.ApplicationModels.IApiExplorerModel, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IFilterModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public System.Reflection.MethodInfo ActionMethod { get => throw null; } @@ -1364,7 +1245,6 @@ namespace Microsoft public System.Collections.Generic.IList Selectors { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ApiConventionApplicationModelConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiConventionApplicationModelConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public ApiConventionApplicationModelConvention(Microsoft.AspNetCore.Mvc.ProducesErrorResponseTypeAttribute defaultErrorResponseType) => throw null; @@ -1373,7 +1253,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ApiExplorerModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiExplorerModel { public ApiExplorerModel() => throw null; @@ -1382,7 +1261,6 @@ namespace Microsoft public bool? IsVisible { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ApiVisibilityConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApiVisibilityConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public ApiVisibilityConvention() => throw null; @@ -1390,7 +1268,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationModel : Microsoft.AspNetCore.Mvc.ApplicationModels.IApiExplorerModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IFilterModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public Microsoft.AspNetCore.Mvc.ApplicationModels.ApiExplorerModel ApiExplorer { get => throw null; set => throw null; } @@ -1400,7 +1277,6 @@ namespace Microsoft public System.Collections.Generic.IDictionary Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModelProviderContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationModelProviderContext { public ApplicationModelProviderContext(System.Collections.Generic.IEnumerable controllerTypes) => throw null; @@ -1408,7 +1284,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel Result { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.AttributeRouteModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AttributeRouteModel { public Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider Attribute { get => throw null; } @@ -1428,7 +1303,6 @@ namespace Microsoft public string Template { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ClientErrorResultFilterConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientErrorResultFilterConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; @@ -1436,7 +1310,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ConsumesConstraintForFormFileParameterConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsumesConstraintForFormFileParameterConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; @@ -1444,7 +1317,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerModel : Microsoft.AspNetCore.Mvc.ApplicationModels.IApiExplorerModel, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IFilterModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public System.Collections.Generic.IList Actions { get => throw null; } @@ -1465,25 +1337,21 @@ namespace Microsoft public System.Collections.Generic.IList Selectors { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionModelConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IApiExplorerModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiExplorerModel { Microsoft.AspNetCore.Mvc.ApplicationModels.ApiExplorerModel ApiExplorer { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationModelConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel application); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationModelProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModelProviderContext context); @@ -1491,13 +1359,11 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IBindingModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBindingModel { Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICommonModel : Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { System.Collections.Generic.IReadOnlyList Attributes { get; } @@ -1505,45 +1371,39 @@ namespace Microsoft string Name { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IControllerModelConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IControllerModelConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel controller); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IFilterModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFilterModel { System.Collections.Generic.IList Filters { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IParameterModelBaseConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IParameterModelBaseConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase parameter); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IParameterModelConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IParameterModelConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModel parameter); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPropertyModel { System.Collections.Generic.IDictionary Properties { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.InferParameterBindingInfoConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InferParameterBindingInfoConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; public InferParameterBindingInfoConvention(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider) => throw null; + public InferParameterBindingInfoConvention(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider, Microsoft.Extensions.DependencyInjection.IServiceProviderIsService serviceProviderIsService) => throw null; protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.InvalidModelStateFilterConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InvalidModelStateFilterConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; @@ -1551,7 +1411,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ParameterModel : Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel Action { get => throw null; set => throw null; } @@ -1565,7 +1424,6 @@ namespace Microsoft public System.Collections.Generic.IDictionary Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ParameterModelBase : Microsoft.AspNetCore.Mvc.ApplicationModels.IBindingModel { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -1577,7 +1435,6 @@ namespace Microsoft public System.Collections.Generic.IDictionary Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PropertyModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PropertyModel : Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase, Microsoft.AspNetCore.Mvc.ApplicationModels.IBindingModel, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -1590,7 +1447,6 @@ namespace Microsoft public string PropertyName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.RouteTokenTransformerConvention` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteTokenTransformerConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; @@ -1598,7 +1454,6 @@ namespace Microsoft protected virtual bool ShouldApply(Microsoft.AspNetCore.Mvc.ApplicationModels.ActionModel action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.SelectorModel` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SelectorModel { public System.Collections.Generic.IList ActionConstraints { get => throw null; } @@ -1611,21 +1466,18 @@ namespace Microsoft } namespace ApplicationParts { - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPart` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ApplicationPart { protected ApplicationPart() => throw null; public abstract string Name { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationPartAttribute : System.Attribute { public ApplicationPartAttribute(string assemblyName) => throw null; public string AssemblyName { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ApplicationPartFactory { protected ApplicationPartFactory() => throw null; @@ -1633,7 +1485,6 @@ namespace Microsoft public abstract System.Collections.Generic.IEnumerable GetApplicationParts(System.Reflection.Assembly assembly); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationPartManager { public ApplicationPartManager() => throw null; @@ -1642,7 +1493,6 @@ namespace Microsoft public void PopulateFeature(TFeature feature) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.AssemblyPart` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AssemblyPart : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPart, Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationPartTypeProvider { public System.Reflection.Assembly Assembly { get => throw null; } @@ -1651,7 +1501,6 @@ namespace Microsoft public System.Collections.Generic.IEnumerable Types { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.DefaultApplicationPartFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultApplicationPartFactory : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartFactory { public DefaultApplicationPartFactory() => throw null; @@ -1660,37 +1509,31 @@ namespace Microsoft public static Microsoft.AspNetCore.Mvc.ApplicationParts.DefaultApplicationPartFactory Instance { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationFeatureProvider { } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationFeatureProvider : Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider { void PopulateFeature(System.Collections.Generic.IEnumerable parts, TFeature feature); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationPartTypeProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationPartTypeProvider { System.Collections.Generic.IEnumerable Types { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ICompilationReferencesProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompilationReferencesProvider { System.Collections.Generic.IEnumerable GetReferencePaths(); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.NullApplicationPartFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullApplicationPartFactory : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartFactory { public override System.Collections.Generic.IEnumerable GetApplicationParts(System.Reflection.Assembly assembly) => throw null; public NullApplicationPartFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ProvideApplicationPartFactoryAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProvideApplicationPartFactoryAttribute : System.Attribute { public System.Type GetFactoryType() => throw null; @@ -1698,7 +1541,6 @@ namespace Microsoft public ProvideApplicationPartFactoryAttribute(string factoryTypeName) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RelatedAssemblyAttribute : System.Attribute { public string AssemblyFileName { get => throw null; } @@ -1709,13 +1551,11 @@ namespace Microsoft } namespace Authorization { - // Generated from `Microsoft.AspNetCore.Mvc.Authorization.AllowAnonymousFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AllowAnonymousFilter : Microsoft.AspNetCore.Mvc.Authorization.IAllowAnonymousFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { public AllowAnonymousFilter() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthorizeFilter : Microsoft.AspNetCore.Mvc.Filters.IAsyncAuthorizationFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { public System.Collections.Generic.IEnumerable AuthorizeData { get => throw null; } @@ -1734,7 +1574,6 @@ namespace Microsoft } namespace Controllers { - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerActionDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor { public virtual string ActionName { get => throw null; set => throw null; } @@ -1745,7 +1584,6 @@ namespace Microsoft public System.Reflection.MethodInfo MethodInfo { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerActivatorProvider : Microsoft.AspNetCore.Mvc.Controllers.IControllerActivatorProvider { public ControllerActivatorProvider(Microsoft.AspNetCore.Mvc.Controllers.IControllerActivator controllerActivator) => throw null; @@ -1754,21 +1592,18 @@ namespace Microsoft public System.Action CreateReleaser(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor descriptor) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerBoundPropertyDescriptor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerBoundPropertyDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor, Microsoft.AspNetCore.Mvc.Infrastructure.IPropertyInfoParameterDescriptor { public ControllerBoundPropertyDescriptor() => throw null; public System.Reflection.PropertyInfo PropertyInfo { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerFeature` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerFeature { public ControllerFeature() => throw null; public System.Collections.Generic.IList Controllers { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerFeatureProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerFeatureProvider : Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider, Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider { public ControllerFeatureProvider() => throw null; @@ -1776,14 +1611,12 @@ namespace Microsoft public void PopulateFeature(System.Collections.Generic.IEnumerable parts, Microsoft.AspNetCore.Mvc.Controllers.ControllerFeature feature) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ControllerParameterDescriptor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ControllerParameterDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor, Microsoft.AspNetCore.Mvc.Infrastructure.IParameterInfoParameterDescriptor { public ControllerParameterDescriptor() => throw null; public System.Reflection.ParameterInfo ParameterInfo { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.IControllerActivator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IControllerActivator { object Create(Microsoft.AspNetCore.Mvc.ControllerContext context); @@ -1791,7 +1624,6 @@ namespace Microsoft System.Threading.Tasks.ValueTask ReleaseAsync(Microsoft.AspNetCore.Mvc.ControllerContext context, object controller) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.IControllerActivatorProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IControllerActivatorProvider { System.Func CreateActivator(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor descriptor); @@ -1799,7 +1631,6 @@ namespace Microsoft System.Action CreateReleaser(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.IControllerFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IControllerFactory { object CreateController(Microsoft.AspNetCore.Mvc.ControllerContext context); @@ -1807,7 +1638,6 @@ namespace Microsoft System.Threading.Tasks.ValueTask ReleaseControllerAsync(Microsoft.AspNetCore.Mvc.ControllerContext context, object controller) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.IControllerFactoryProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IControllerFactoryProvider { System.Func CreateAsyncControllerReleaser(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor descriptor) => throw null; @@ -1815,14 +1645,12 @@ namespace Microsoft System.Action CreateControllerReleaser(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.IControllerPropertyActivator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IControllerPropertyActivator { void Activate(Microsoft.AspNetCore.Mvc.ControllerContext context, object controller); System.Action GetActivatorDelegate(Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor actionDescriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceBasedControllerActivator : Microsoft.AspNetCore.Mvc.Controllers.IControllerActivator { public object Create(Microsoft.AspNetCore.Mvc.ControllerContext actionContext) => throw null; @@ -1835,7 +1663,6 @@ namespace Microsoft { namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Mvc.Core.Infrastructure.IAntiforgeryValidationFailedResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAntiforgeryValidationFailedResult : Microsoft.AspNetCore.Mvc.IActionResult { } @@ -1844,7 +1671,6 @@ namespace Microsoft } namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterActionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterActionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1856,7 +1682,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteData RouteData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterActionFilterOnActionExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterActionFilterOnActionExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1868,7 +1693,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterActionFilterOnActionExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterActionFilterOnActionExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1880,7 +1704,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterActionFilterOnActionExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterActionFilterOnActionExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1892,7 +1715,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterActionResultEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterActionResultEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -1903,7 +1725,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterAuthorizationFilterOnAuthorizationEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterAuthorizationFilterOnAuthorizationEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1915,7 +1736,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterControllerActionMethodEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterControllerActionMethodEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -1928,7 +1748,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterExceptionFilterOnExceptionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterExceptionFilterOnExceptionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1940,7 +1759,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResourceFilterOnResourceExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResourceFilterOnResourceExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1952,7 +1770,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext ResourceExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResourceFilterOnResourceExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResourceFilterOnResourceExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1964,7 +1781,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext ResourceExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResourceFilterOnResourceExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResourceFilterOnResourceExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1976,7 +1792,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext ResourceExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResultFilterOnResultExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResultFilterOnResultExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -1988,7 +1803,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext ResultExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResultFilterOnResultExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResultFilterOnResultExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2000,7 +1814,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext ResultExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterResultFilterOnResultExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterResultFilterOnResultExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2012,7 +1825,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext ResultExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeActionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeActionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2024,7 +1836,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteData RouteData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeActionFilterOnActionExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeActionFilterOnActionExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2036,7 +1847,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeActionFilterOnActionExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeActionFilterOnActionExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2048,7 +1858,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeActionFilterOnActionExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeActionFilterOnActionExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2060,7 +1869,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeActionResultEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeActionResultEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -2071,7 +1879,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeAuthorizationFilterOnAuthorizationEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeAuthorizationFilterOnAuthorizationEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2083,7 +1890,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeControllerActionMethodEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeControllerActionMethodEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public System.Collections.Generic.IReadOnlyDictionary ActionArguments { get => throw null; } @@ -2095,7 +1901,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeExceptionFilterOnException` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeExceptionFilterOnException : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2107,7 +1912,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResourceFilterOnResourceExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResourceFilterOnResourceExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2119,7 +1923,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext ResourceExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResourceFilterOnResourceExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResourceFilterOnResourceExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2131,7 +1934,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext ResourceExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResourceFilterOnResourceExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResourceFilterOnResourceExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2143,7 +1945,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext ResourceExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResultFilterOnResultExecutedEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResultFilterOnResultExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2155,7 +1956,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext ResultExecutedContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResultFilterOnResultExecutingEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResultFilterOnResultExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2167,7 +1967,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext ResultExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeResultFilterOnResultExecutionEventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeResultFilterOnResultExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -2179,10 +1978,8 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext ResultExecutingContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.EventData` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class EventData : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyList>, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.EventData+Enumerator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -2207,7 +2004,6 @@ namespace Microsoft } namespace Filters { - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ActionFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ActionFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IActionFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IResultFilter { protected ActionFilterAttribute() => throw null; @@ -2220,7 +2016,6 @@ namespace Microsoft public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ExceptionFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ExceptionFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IAsyncExceptionFilter, Microsoft.AspNetCore.Mvc.Filters.IExceptionFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { protected ExceptionFilterAttribute() => throw null; @@ -2229,7 +2024,6 @@ namespace Microsoft public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterCollection` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FilterCollection : System.Collections.ObjectModel.Collection { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata Add(System.Type filterType) => throw null; @@ -2243,7 +2037,6 @@ namespace Microsoft public FilterCollection() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.FilterScope` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class FilterScope { public static int Action; @@ -2253,7 +2046,6 @@ namespace Microsoft public static int Last; } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.ResultFilterAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ResultFilterAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IAsyncResultFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.Filters.IResultFilter { public virtual void OnResultExecuted(Microsoft.AspNetCore.Mvc.Filters.ResultExecutedContext context) => throw null; @@ -2266,7 +2058,6 @@ namespace Microsoft } namespace Formatters { - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.FormatFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormatFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IResourceFilter, Microsoft.AspNetCore.Mvc.Filters.IResultFilter { public FormatFilter(Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; @@ -2277,7 +2068,6 @@ namespace Microsoft public void OnResultExecuting(Microsoft.AspNetCore.Mvc.Filters.ResultExecutingContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.FormatterMappings` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormatterMappings { public bool ClearMediaTypeMappingForFormat(string format) => throw null; @@ -2287,7 +2077,6 @@ namespace Microsoft public void SetMediaTypeMappingForFormat(string format, string contentType) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.HttpNoContentOutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpNoContentOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter { public bool CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context) => throw null; @@ -2296,13 +2085,11 @@ namespace Microsoft public System.Threading.Tasks.Task WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.IFormatFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IFormatFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { string GetFormat(Microsoft.AspNetCore.Mvc.ActionContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.InputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class InputFormatter : Microsoft.AspNetCore.Mvc.ApiExplorer.IApiRequestFormatMetadataProvider, Microsoft.AspNetCore.Mvc.Formatters.IInputFormatter { public virtual bool CanRead(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext context) => throw null; @@ -2315,7 +2102,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection SupportedMediaTypes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.MediaType` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct MediaType { public Microsoft.Extensions.Primitives.StringSegment Charset { get => throw null; } @@ -2342,7 +2128,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MediaTypeCollection : System.Collections.ObjectModel.Collection { public void Add(Microsoft.Net.Http.Headers.MediaTypeHeaderValue item) => throw null; @@ -2351,7 +2136,6 @@ namespace Microsoft public bool Remove(Microsoft.Net.Http.Headers.MediaTypeHeaderValue item) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.MediaTypeSegmentWithQuality` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct MediaTypeSegmentWithQuality { public Microsoft.Extensions.Primitives.StringSegment MediaType { get => throw null; } @@ -2361,7 +2145,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.OutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class OutputFormatter : Microsoft.AspNetCore.Mvc.ApiExplorer.IApiResponseTypeMetadataProvider, Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter { public virtual bool CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context) => throw null; @@ -2374,7 +2157,6 @@ namespace Microsoft public virtual void WriteResponseHeaders(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.StreamOutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StreamOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter { public bool CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context) => throw null; @@ -2382,7 +2164,6 @@ namespace Microsoft public System.Threading.Tasks.Task WriteAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.StringOutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter { public override bool CanWriteResult(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context) => throw null; @@ -2390,7 +2171,6 @@ namespace Microsoft public override System.Threading.Tasks.Task WriteResponseBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context, System.Text.Encoding encoding) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SystemTextJsonInputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextInputFormatter, Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy { Microsoft.AspNetCore.Mvc.Formatters.InputFormatterExceptionPolicy Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy.ExceptionPolicy { get => throw null; } @@ -2399,7 +2179,6 @@ namespace Microsoft public SystemTextJsonInputFormatter(Microsoft.AspNetCore.Mvc.JsonOptions options, Microsoft.Extensions.Logging.ILogger logger) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SystemTextJsonOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter { public System.Text.Json.JsonSerializerOptions SerializerOptions { get => throw null; } @@ -2407,7 +2186,6 @@ namespace Microsoft public override System.Threading.Tasks.Task WriteResponseBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context, System.Text.Encoding selectedEncoding) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.TextInputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TextInputFormatter : Microsoft.AspNetCore.Mvc.Formatters.InputFormatter { public override System.Threading.Tasks.Task ReadRequestBodyAsync(Microsoft.AspNetCore.Mvc.Formatters.InputFormatterContext context) => throw null; @@ -2419,7 +2197,6 @@ namespace Microsoft protected static System.Text.Encoding UTF8EncodingWithoutBOM; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TextOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.OutputFormatter { public virtual System.Text.Encoding SelectCharacterEncoding(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterWriteContext context) => throw null; @@ -2433,14 +2210,12 @@ namespace Microsoft } namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ActionContextAccessor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionContextAccessor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; set => throw null; } public ActionContextAccessor() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ActionDescriptorCollection` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionDescriptorCollection { public ActionDescriptorCollection(System.Collections.Generic.IReadOnlyList items, int version) => throw null; @@ -2448,7 +2223,6 @@ namespace Microsoft public int Version { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ActionDescriptorCollectionProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ActionDescriptorCollectionProvider : Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider { protected ActionDescriptorCollectionProvider() => throw null; @@ -2456,26 +2230,22 @@ namespace Microsoft public abstract Microsoft.Extensions.Primitives.IChangeToken GetChangeToken(); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ActionResultObjectValueAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionResultObjectValueAttribute : System.Attribute { public ActionResultObjectValueAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ActionResultStatusCodeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActionResultStatusCodeAttribute : System.Attribute { public ActionResultStatusCodeAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.AmbiguousActionException` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AmbiguousActionException : System.InvalidOperationException { protected AmbiguousActionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; public AmbiguousActionException(string message) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.CompatibilitySwitch<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompatibilitySwitch : Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch where TValue : struct { public CompatibilitySwitch(string name) => throw null; @@ -2486,7 +2256,6 @@ namespace Microsoft object Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch.Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ConfigureCompatibilityOptions<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConfigureCompatibilityOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TOptions : class, System.Collections.Generic.IEnumerable { protected ConfigureCompatibilityOptions(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions compatibilityOptions) => throw null; @@ -2495,28 +2264,24 @@ namespace Microsoft protected Microsoft.AspNetCore.Mvc.CompatibilityVersion Version { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ContentResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ContentResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public ContentResultExecutor(Microsoft.Extensions.Logging.ILogger logger, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory httpResponseStreamWriterFactory) => throw null; public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.ContentResult result) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.DefaultOutputFormatterSelector` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultOutputFormatterSelector : Microsoft.AspNetCore.Mvc.Infrastructure.OutputFormatterSelector { public DefaultOutputFormatterSelector(Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public override Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter SelectFormatter(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context, System.Collections.Generic.IList formatters, Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection contentTypes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.DefaultStatusCodeAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultStatusCodeAttribute : System.Attribute { public DefaultStatusCodeAttribute(int statusCode) => throw null; public int StatusCode { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.FileContentResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileContentResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.FileContentResult result) => throw null; @@ -2524,7 +2289,6 @@ namespace Microsoft protected virtual System.Threading.Tasks.Task WriteFileAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.FileContentResult result, Microsoft.Net.Http.Headers.RangeItemHeaderValue range, System.Int64 rangeLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileResultExecutorBase { protected const int BufferSize = default; @@ -2535,7 +2299,6 @@ namespace Microsoft protected static System.Threading.Tasks.Task WriteFileAsync(Microsoft.AspNetCore.Http.HttpContext context, System.IO.Stream fileStream, Microsoft.Net.Http.Headers.RangeItemHeaderValue range, System.Int64 rangeLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.FileStreamResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileStreamResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.FileStreamResult result) => throw null; @@ -2543,67 +2306,56 @@ namespace Microsoft protected virtual System.Threading.Tasks.Task WriteFileAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.FileStreamResult result, Microsoft.Net.Http.Headers.RangeItemHeaderValue range, System.Int64 rangeLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionContextAccessor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionContextAccessor { Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorChangeProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionDescriptorChangeProvider { Microsoft.Extensions.Primitives.IChangeToken GetChangeToken(); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionDescriptorCollectionProvider { Microsoft.AspNetCore.Mvc.Infrastructure.ActionDescriptorCollection ActionDescriptors { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionInvokerFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionInvokerFactory { Microsoft.AspNetCore.Mvc.Abstractions.IActionInvoker CreateInvoker(Microsoft.AspNetCore.Mvc.ActionContext actionContext); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionResultExecutor where TResult : Microsoft.AspNetCore.Mvc.IActionResult { System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, TResult result); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultTypeMapper` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionResultTypeMapper { Microsoft.AspNetCore.Mvc.IActionResult Convert(object value, System.Type returnType); System.Type GetResultDataType(System.Type returnType); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IActionSelector` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionSelector { Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor SelectBestCandidate(Microsoft.AspNetCore.Routing.RouteContext context, System.Collections.Generic.IReadOnlyList candidates); System.Collections.Generic.IReadOnlyList SelectCandidates(Microsoft.AspNetCore.Routing.RouteContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IApiBehaviorMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApiBehaviorMetadata : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IClientErrorActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClientErrorActionResult : Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IClientErrorFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClientErrorFactory { Microsoft.AspNetCore.Mvc.IActionResult GetClientError(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.Infrastructure.IClientErrorActionResult clientError); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ICompatibilitySwitch` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompatibilitySwitch { bool IsValueSet { get; } @@ -2611,50 +2363,42 @@ namespace Microsoft object Value { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IConvertToActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConvertToActionResult { Microsoft.AspNetCore.Mvc.IActionResult Convert(); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IHttpRequestStreamReaderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestStreamReaderFactory { System.IO.TextReader CreateReader(System.IO.Stream stream, System.Text.Encoding encoding); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpResponseStreamWriterFactory { System.IO.TextWriter CreateWriter(System.IO.Stream stream, System.Text.Encoding encoding); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IParameterInfoParameterDescriptor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IParameterInfoParameterDescriptor { System.Reflection.ParameterInfo ParameterInfo { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IPropertyInfoParameterDescriptor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPropertyInfoParameterDescriptor { System.Reflection.PropertyInfo PropertyInfo { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStatusCodeActionResult : Microsoft.AspNetCore.Mvc.IActionResult { int? StatusCode { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.LocalRedirectResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocalRedirectResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.LocalRedirectResult result) => throw null; public LocalRedirectResultExecutor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ModelStateInvalidFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelStateInvalidFilter : Microsoft.AspNetCore.Mvc.Filters.IActionFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public bool IsReusable { get => throw null; } @@ -2664,14 +2408,12 @@ namespace Microsoft public int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.MvcCompatibilityOptions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcCompatibilityOptions { public Microsoft.AspNetCore.Mvc.CompatibilityVersion CompatibilityVersion { get => throw null; set => throw null; } public MvcCompatibilityOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ObjectResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.ObjectResult result) => throw null; @@ -2681,17 +2423,14 @@ namespace Microsoft protected System.Func WriterFactory { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.OutputFormatterSelector` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class OutputFormatterSelector { protected OutputFormatterSelector() => throw null; public abstract Microsoft.AspNetCore.Mvc.Formatters.IOutputFormatter SelectFormatter(Microsoft.AspNetCore.Mvc.Formatters.OutputFormatterCanWriteContext context, System.Collections.Generic.IList formatters, Microsoft.AspNetCore.Mvc.Formatters.MediaTypeCollection mediaTypes); } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.PhysicalFileResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalFileResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.PhysicalFileResultExecutor+FileMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` protected class FileMetadata { public bool Exists { get => throw null; set => throw null; } @@ -2708,7 +2447,6 @@ namespace Microsoft protected virtual System.Threading.Tasks.Task WriteFileAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.PhysicalFileResult result, Microsoft.Net.Http.Headers.RangeItemHeaderValue range, System.Int64 rangeLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.ProblemDetailsFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ProblemDetailsFactory { public abstract Microsoft.AspNetCore.Mvc.ProblemDetails CreateProblemDetails(Microsoft.AspNetCore.Http.HttpContext httpContext, int? statusCode = default(int?), string title = default(string), string type = default(string), string detail = default(string), string instance = default(string)); @@ -2716,35 +2454,30 @@ namespace Microsoft protected ProblemDetailsFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.RedirectResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.RedirectResult result) => throw null; public RedirectResultExecutor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToActionResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToActionResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.RedirectToActionResult result) => throw null; public RedirectToActionResultExecutor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToPageResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToPageResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.RedirectToPageResult result) => throw null; public RedirectToPageResultExecutor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.RedirectToRouteResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RedirectToRouteResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.RedirectToRouteResult result) => throw null; public RedirectToRouteResultExecutor(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Infrastructure.VirtualFileResultExecutor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class VirtualFileResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.FileResultExecutorBase, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.VirtualFileResult result) => throw null; @@ -2756,19 +2489,16 @@ namespace Microsoft } namespace ModelBinding { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindNeverAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindNeverAttribute : Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehaviorAttribute { public BindNeverAttribute() : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehavior)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindRequiredAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindRequiredAttribute : Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehaviorAttribute { public BindRequiredAttribute() : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehavior)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehavior` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum BindingBehavior : int { Never = 1, @@ -2776,14 +2506,12 @@ namespace Microsoft Required = 2, } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehaviorAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingBehaviorAttribute : System.Attribute { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehavior Behavior { get => throw null; } public BindingBehaviorAttribute(Microsoft.AspNetCore.Mvc.ModelBinding.BindingBehavior behavior) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.BindingSourceValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class BindingSourceValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { protected Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } @@ -2793,7 +2521,6 @@ namespace Microsoft public abstract Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult GetValue(string key); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.CompositeValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeValueProvider : System.Collections.ObjectModel.Collection, Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IEnumerableValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IKeyRewriterValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { public CompositeValueProvider() => throw null; @@ -2809,7 +2536,6 @@ namespace Microsoft protected override void SetItem(int index, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider item) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.DefaultModelBindingContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultModelBindingContext : Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext { public override Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; set => throw null; } @@ -2833,7 +2559,6 @@ namespace Microsoft public override Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider ValueProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.DefaultPropertyFilterProvider<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultPropertyFilterProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider where TModel : class { public DefaultPropertyFilterProvider() => throw null; @@ -2842,13 +2567,11 @@ namespace Microsoft public virtual System.Collections.Generic.IEnumerable>> PropertyIncludeExpressions { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.EmptyModelMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EmptyModelMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadataProvider { public EmptyModelMetadataProvider() : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ICompositeMetadataDetailsProvider)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.FormFileValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFileValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { public bool ContainsPrefix(string prefix) => throw null; @@ -2856,14 +2579,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult GetValue(string key) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.FormFileValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFileValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public FormFileValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSourceValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IEnumerableValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { public override bool ContainsPrefix(string prefix) => throw null; @@ -2874,70 +2595,60 @@ namespace Microsoft protected Microsoft.AspNetCore.Mvc.ModelBinding.PrefixContainer PrefixContainer { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.FormValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public FormValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IBindingSourceValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBindingSourceValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider Filter(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ICollectionModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICollectionModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { bool CanCreateInstance(System.Type targetType); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IEnumerableValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEnumerableValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { System.Collections.Generic.IDictionary GetKeysFromPrefix(string prefix); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IKeyRewriterValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeyRewriterValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider Filter(); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelBinderFactory { Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder CreateBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactoryContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.JQueryFormValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JQueryFormValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.JQueryValueProvider { + public override Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult GetValue(string key) => throw null; public JQueryFormValueProvider(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource, System.Collections.Generic.IDictionary values, System.Globalization.CultureInfo culture) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource), default(System.Collections.Generic.IDictionary), default(System.Globalization.CultureInfo)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.JQueryFormValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JQueryFormValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public JQueryFormValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.JQueryQueryStringValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JQueryQueryStringValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.JQueryValueProvider { public JQueryQueryStringValueProvider(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource, System.Collections.Generic.IDictionary values, System.Globalization.CultureInfo culture) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource), default(System.Collections.Generic.IDictionary), default(System.Globalization.CultureInfo)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.JQueryQueryStringValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JQueryQueryStringValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public JQueryQueryStringValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.JQueryValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class JQueryValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSourceValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IEnumerableValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IKeyRewriterValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { public override bool ContainsPrefix(string prefix) => throw null; @@ -2949,7 +2660,6 @@ namespace Microsoft protected Microsoft.AspNetCore.Mvc.ModelBinding.PrefixContainer PrefixContainer { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelAttributes` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelAttributes { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -2963,14 +2673,12 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList TypeAttributes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelBinderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderFactory { public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder CreateBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactoryContext context) => throw null; public ModelBinderFactory(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, Microsoft.Extensions.Options.IOptions options, System.IServiceProvider serviceProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderFactoryContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelBinderFactoryContext { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingInfo BindingInfo { get => throw null; set => throw null; } @@ -2979,20 +2687,17 @@ namespace Microsoft public ModelBinderFactoryContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelBinderProviderExtensions { public static void RemoveType(this System.Collections.Generic.IList list, System.Type type) => throw null; public static void RemoveType(this System.Collections.Generic.IList list) where TModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadataProviderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelMetadataProviderExtensions { public static Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata GetMetadataForProperty(this Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider provider, System.Type containerType, string propertyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelNames` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelNames { public static string CreateIndexModelName(string parentName, int index) => throw null; @@ -3000,7 +2705,6 @@ namespace Microsoft public static string CreatePropertyModelName(string prefix, string propertyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ObjectModelValidator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ObjectModelValidator : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator { public abstract Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor GetValidationVisitor(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider validatorProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidatorCache validatorCache, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary validationState); @@ -3010,7 +2714,6 @@ namespace Microsoft public virtual void Validate(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary validationState, string prefix, object model, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, object container) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ParameterBinder { public virtual System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder modelBinder, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider valueProvider, Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor parameter, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, object value) => throw null; @@ -3019,7 +2722,6 @@ namespace Microsoft public ParameterBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderFactory modelBinderFactory, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator validator, Microsoft.Extensions.Options.IOptions mvcOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.PrefixContainer` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PrefixContainer { public bool ContainsPrefix(string prefix) => throw null; @@ -3027,7 +2729,6 @@ namespace Microsoft public PrefixContainer(System.Collections.Generic.ICollection values) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.QueryStringValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryStringValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSourceValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IEnumerableValueProvider, Microsoft.AspNetCore.Mvc.ModelBinding.IValueProvider { public override bool ContainsPrefix(string prefix) => throw null; @@ -3038,14 +2739,12 @@ namespace Microsoft public QueryStringValueProvider(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource, Microsoft.AspNetCore.Http.IQueryCollection values, System.Globalization.CultureInfo culture) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.QueryStringValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QueryStringValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public QueryStringValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.RouteValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValueProvider : Microsoft.AspNetCore.Mvc.ModelBinding.BindingSourceValueProvider { public override bool ContainsPrefix(string key) => throw null; @@ -3056,14 +2755,12 @@ namespace Microsoft public RouteValueProvider(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource bindingSource, Microsoft.AspNetCore.Routing.RouteValueDictionary values, System.Globalization.CultureInfo culture) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.RouteValueProviderFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValueProviderFactory : Microsoft.AspNetCore.Mvc.ModelBinding.IValueProviderFactory { public System.Threading.Tasks.Task CreateValueProviderAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryContext context) => throw null; public RouteValueProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.SuppressChildValidationMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SuppressChildValidationMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IValidationMetadataProvider { public void CreateValidationMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadataProviderContext context) => throw null; @@ -3073,13 +2770,11 @@ namespace Microsoft public System.Type Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeException` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnsupportedContentTypeException : System.Exception { public UnsupportedContentTypeException(string message) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.UnsupportedContentTypeFilter` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UnsupportedContentTypeFilter : Microsoft.AspNetCore.Mvc.Filters.IActionFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public void OnActionExecuted(Microsoft.AspNetCore.Mvc.Filters.ActionExecutedContext context) => throw null; @@ -3088,7 +2783,6 @@ namespace Microsoft public UnsupportedContentTypeFilter() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderFactoryExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ValueProviderFactoryExtensions { public static void RemoveType(this System.Collections.Generic.IList list, System.Type type) => throw null; @@ -3097,7 +2791,6 @@ namespace Microsoft namespace Binders { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinder<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ArrayModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder { public ArrayModelBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder elementBinder, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder), default(Microsoft.Extensions.Logging.ILoggerFactory)) => throw null; @@ -3109,28 +2802,24 @@ namespace Microsoft protected override object CreateEmptyCollection(System.Type targetType) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ArrayModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ArrayModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public ArrayModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BinderTypeModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BinderTypeModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public BinderTypeModelBinder(System.Type binderType) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BinderTypeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BinderTypeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public BinderTypeModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BodyModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3139,7 +2828,6 @@ namespace Microsoft public BodyModelBinder(System.Collections.Generic.IList formatters, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpRequestStreamReaderFactory readerFactory, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.MvcOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BodyModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public BodyModelBinderProvider(System.Collections.Generic.IList formatters, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpRequestStreamReaderFactory readerFactory) => throw null; @@ -3148,35 +2836,30 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ByteArrayModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public ByteArrayModelBinder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ByteArrayModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ByteArrayModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public ByteArrayModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CancellationTokenModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CancellationTokenModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public CancellationTokenModelBinder() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CancellationTokenModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CancellationTokenModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public CancellationTokenModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder<>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CollectionModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.ICollectionModelBinder, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { protected void AddErrorIfBindingRequired(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3193,27 +2876,23 @@ namespace Microsoft protected Microsoft.Extensions.Logging.ILogger Logger { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CollectionModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public CollectionModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComplexObjectModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexObjectModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComplexObjectModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public ComplexObjectModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComplexTypeModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3225,35 +2904,30 @@ namespace Microsoft protected virtual void SetProperty(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext, string modelName, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata propertyMetadata, Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingResult result) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComplexTypeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public ComplexTypeModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DateTimeModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DateTimeModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public DateTimeModelBinder(System.Globalization.DateTimeStyles supportedStyles, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DateTimeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DateTimeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public DateTimeModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DecimalModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DecimalModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public DecimalModelBinder(System.Globalization.NumberStyles supportedStyles, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinder<,>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DictionaryModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.Binders.CollectionModelBinder> { public override System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3265,77 +2939,66 @@ namespace Microsoft public DictionaryModelBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder keyBinder, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder valueBinder, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, bool allowValidatingTopLevelNodes, Microsoft.AspNetCore.Mvc.MvcOptions mvcOptions) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder), default(Microsoft.Extensions.Logging.ILoggerFactory)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DictionaryModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DictionaryModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public DictionaryModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.DoubleModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DoubleModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public DoubleModelBinder(System.Globalization.NumberStyles supportedStyles, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.EnumTypeModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnumTypeModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder { protected override void CheckModel(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext, Microsoft.AspNetCore.Mvc.ModelBinding.ValueProviderResult valueProviderResult, object model) => throw null; public EnumTypeModelBinder(bool suppressBindingUndefinedValueToEnumType, System.Type modelType, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base(default(System.Type), default(Microsoft.Extensions.Logging.ILoggerFactory)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.EnumTypeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnumTypeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public EnumTypeModelBinderProvider(Microsoft.AspNetCore.Mvc.MvcOptions options) => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FloatModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public FloatModelBinder(System.Globalization.NumberStyles supportedStyles, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FloatingPointTypeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FloatingPointTypeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public FloatingPointTypeModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormCollectionModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public FormCollectionModelBinder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormCollectionModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormCollectionModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public FormCollectionModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFileModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public FormFileModelBinder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.FormFileModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormFileModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public FormFileModelBinderProvider() => throw null; public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeaderModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3343,42 +3006,36 @@ namespace Microsoft public HeaderModelBinder(Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder innerModelBinder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.HeaderModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeaderModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; public HeaderModelBinderProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinder<,>` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyValuePairModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public KeyValuePairModelBinder(Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder keyBinder, Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder valueBinder, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.KeyValuePairModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyValuePairModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; public KeyValuePairModelBinderProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ServicesModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServicesModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; public ServicesModelBinder() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ServicesModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServicesModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; public ServicesModelBinderProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SimpleTypeModelBinder : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder { public System.Threading.Tasks.Task BindModelAsync(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBindingContext bindingContext) => throw null; @@ -3386,17 +3043,21 @@ namespace Microsoft public SimpleTypeModelBinder(System.Type type, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Binders.SimpleTypeModelBinderProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SimpleTypeModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; public SimpleTypeModelBinderProvider() => throw null; } + public class TryParseModelBinderProvider : Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinderProvider + { + public Microsoft.AspNetCore.Mvc.ModelBinding.IModelBinder GetBinder(Microsoft.AspNetCore.Mvc.ModelBinding.ModelBinderProviderContext context) => throw null; + public TryParseModelBinderProvider() => throw null; + } + } namespace Metadata { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingMetadata { public string BinderModelName { get => throw null; set => throw null; } @@ -3411,7 +3072,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.IPropertyFilterProvider PropertyFilterProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadataProviderContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingMetadataProviderContext { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -3423,7 +3083,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList TypeAttributes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingSourceMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BindingSourceMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IBindingMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { public Microsoft.AspNetCore.Mvc.ModelBinding.BindingSource BindingSource { get => throw null; } @@ -3432,7 +3091,6 @@ namespace Microsoft public System.Type Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultMetadataDetails` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultMetadataDetails { public Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadata BindingMetadata { get => throw null; set => throw null; } @@ -3449,7 +3107,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadata ValidationMetadata { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelBindingMessageProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultModelBindingMessageProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ModelBindingMessageProvider { public override System.Func AttemptedValueIsInvalidAccessor { get => throw null; } @@ -3478,7 +3135,6 @@ namespace Microsoft public override System.Func ValueMustNotBeNullAccessor { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultModelMetadata : Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata { public override System.Collections.Generic.IReadOnlyDictionary AdditionalValues { get => throw null; } @@ -3533,7 +3189,6 @@ namespace Microsoft public override System.Collections.Generic.IReadOnlyList ValidatorMetadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultModelMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadataProvider { protected virtual Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata CreateModelMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultMetadataDetails entry) => throw null; @@ -3552,7 +3207,6 @@ namespace Microsoft protected Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DefaultModelBindingMessageProvider ModelBindingMessageProvider { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DisplayMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DisplayMetadata { public System.Collections.Generic.IDictionary AdditionalValues { get => throw null; } @@ -3582,7 +3236,6 @@ namespace Microsoft public string TemplateHint { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DisplayMetadataProviderContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DisplayMetadataProviderContext { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -3593,49 +3246,49 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList TypeAttributes { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ExcludeBindingMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExcludeBindingMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IBindingMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { public void CreateBindingMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadataProviderContext context) => throw null; public ExcludeBindingMetadataProvider(System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IBindingMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IBindingMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { void CreateBindingMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadataProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ICompositeMetadataDetailsProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompositeMetadataDetailsProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IBindingMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IDisplayMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IValidationMetadataProvider { } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IDisplayMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDisplayMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { void CreateDisplayMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DisplayMetadataProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMetadataDetailsProvider { } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IValidationMetadataProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValidationMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { void CreateValidationMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadataProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.MetadataDetailsProviderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MetadataDetailsProviderExtensions { public static void RemoveType(this System.Collections.Generic.IList list, System.Type type) => throw null; public static void RemoveType(this System.Collections.Generic.IList list) where TMetadataDetailsProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadata` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class SystemTextJsonValidationMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IDisplayMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IValidationMetadataProvider + { + public void CreateDisplayMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DisplayMetadataProviderContext context) => throw null; + public void CreateValidationMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadataProviderContext context) => throw null; + public SystemTextJsonValidationMetadataProvider() => throw null; + public SystemTextJsonValidationMetadataProvider(System.Text.Json.JsonNamingPolicy namingPolicy) => throw null; + } + public class ValidationMetadata { public bool? HasValidators { get => throw null; set => throw null; } @@ -3643,10 +3296,10 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter PropertyValidationFilter { get => throw null; set => throw null; } public bool? ValidateChildren { get => throw null; set => throw null; } public ValidationMetadata() => throw null; + public string ValidationModelName { get => throw null; set => throw null; } public System.Collections.Generic.IList ValidatorMetadata { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.ValidationMetadataProviderContext` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationMetadataProviderContext { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -3661,14 +3314,12 @@ namespace Microsoft } namespace Validation { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorCache` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClientValidatorCache { public ClientValidatorCache() => throw null; public System.Collections.Generic.IReadOnlyList GetValidators(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidatorProvider validatorProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.CompositeClientModelValidatorProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeClientModelValidatorProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidatorProvider { public CompositeClientModelValidatorProvider(System.Collections.Generic.IEnumerable providers) => throw null; @@ -3676,7 +3327,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList ValidatorProviders { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.CompositeModelValidatorProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeModelValidatorProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider { public CompositeModelValidatorProvider(System.Collections.Generic.IList providers) => throw null; @@ -3684,36 +3334,30 @@ namespace Microsoft public System.Collections.Generic.IList ValidatorProviders { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IMetadataBasedModelValidatorProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMetadataBasedModelValidatorProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider { bool HasValidators(System.Type modelType, System.Collections.Generic.IList validatorMetadata); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IObjectModelValidator` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IObjectModelValidator { void Validate(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationStateDictionary validationState, string prefix, object model); } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidatorProviderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelValidatorProviderExtensions { public static void RemoveType(this System.Collections.Generic.IList list, System.Type type) => throw null; public static void RemoveType(this System.Collections.Generic.IList list) where TModelValidatorProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidateNeverAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateNeverAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IPropertyValidationFilter { public bool ShouldValidateEntry(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry entry, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationEntry parentEntry) => throw null; public ValidateNeverAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationVisitor { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor+StateManager` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` protected struct StateManager : System.IDisposable { public void Dispose() => throw null; @@ -3749,7 +3393,6 @@ namespace Microsoft protected virtual bool VisitSimpleType() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidatorCache` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidatorCache { public System.Collections.Generic.IReadOnlyList GetValidators(Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IModelValidatorProvider validatorProvider) => throw null; @@ -3760,7 +3403,6 @@ namespace Microsoft } namespace Routing { - // Generated from `Microsoft.AspNetCore.Mvc.Routing.DynamicRouteValueTransformer` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class DynamicRouteValueTransformer { protected DynamicRouteValueTransformer() => throw null; @@ -3769,7 +3411,6 @@ namespace Microsoft public abstract System.Threading.Tasks.ValueTask TransformAsync(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValueDictionary values); } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.HttpMethodAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HttpMethodAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider, Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider { public HttpMethodAttribute(System.Collections.Generic.IEnumerable httpMethods) => throw null; @@ -3781,13 +3422,11 @@ namespace Microsoft public string Template { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IActionHttpMethodProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IActionHttpMethodProvider { System.Collections.Generic.IEnumerable HttpMethods { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteTemplateProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteTemplateProvider { string Name { get; } @@ -3795,27 +3434,23 @@ namespace Microsoft string Template { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IRouteValueProvider` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteValueProvider { string RouteKey { get; } string RouteValue { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUrlHelperFactory { Microsoft.AspNetCore.Mvc.IUrlHelper GetUrlHelper(Microsoft.AspNetCore.Mvc.ActionContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.KnownRouteValueConstraint` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KnownRouteValueConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint { public KnownRouteValueConstraint(Microsoft.AspNetCore.Mvc.Infrastructure.IActionDescriptorCollectionProvider actionDescriptorCollectionProvider) => throw null; public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.RouteValueAttribute` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RouteValueAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Routing.IRouteValueProvider { public string RouteKey { get => throw null; } @@ -3823,7 +3458,6 @@ namespace Microsoft protected RouteValueAttribute(string routeKey, string routeValue) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.UrlHelper` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlHelper : Microsoft.AspNetCore.Mvc.Routing.UrlHelperBase { public override string Action(Microsoft.AspNetCore.Mvc.Routing.UrlActionContext actionContext) => throw null; @@ -3835,7 +3469,6 @@ namespace Microsoft public UrlHelper(Microsoft.AspNetCore.Mvc.ActionContext actionContext) : base(default(Microsoft.AspNetCore.Mvc.ActionContext)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.UrlHelperBase` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class UrlHelperBase : Microsoft.AspNetCore.Mvc.IUrlHelper { public abstract string Action(Microsoft.AspNetCore.Mvc.Routing.UrlActionContext actionContext); @@ -3851,7 +3484,6 @@ namespace Microsoft protected UrlHelperBase(Microsoft.AspNetCore.Mvc.ActionContext actionContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Routing.UrlHelperFactory` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlHelperFactory : Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory { public Microsoft.AspNetCore.Mvc.IUrlHelper GetUrlHelper(Microsoft.AspNetCore.Mvc.ActionContext context) => throw null; @@ -3861,7 +3493,6 @@ namespace Microsoft } namespace ViewFeatures { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IKeepTempDataResult` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IKeepTempDataResult : Microsoft.AspNetCore.Mvc.IActionResult { } @@ -3870,7 +3501,6 @@ namespace Microsoft } namespace Routing { - // Generated from `Microsoft.AspNetCore.Routing.ControllerLinkGeneratorExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ControllerLinkGeneratorExtensions { public static string GetPathByAction(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string action = default(string), string controller = default(string), object values = default(object), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; @@ -3879,7 +3509,6 @@ namespace Microsoft public static string GetUriByAction(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string action, string controller, object values, string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.PageLinkGeneratorExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class PageLinkGeneratorExtensions { public static string GetPathByPage(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string page = default(string), string handler = default(string), object values = default(object), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; @@ -3894,7 +3523,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ApplicationModelConventionExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ApplicationModelConventionExtensions { public static void Add(this System.Collections.Generic.IList conventions, Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention actionModelConvention) => throw null; @@ -3905,21 +3533,18 @@ namespace Microsoft public static void RemoveType(this System.Collections.Generic.IList list) where TApplicationModelConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.IMvcBuilder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMvcBuilder { Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager PartManager { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } - // Generated from `Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMvcCoreBuilder { Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager PartManager { get; } Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcCoreMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcCoreMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddApplicationPart(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Reflection.Assembly assembly) => throw null; @@ -3932,7 +3557,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder SetCompatibilityVersion(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, Microsoft.AspNetCore.Mvc.CompatibilityVersion version) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcCoreMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcCoreMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddApplicationPart(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, System.Reflection.Assembly assembly) => throw null; @@ -3948,7 +3572,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder SetCompatibilityVersion(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, Microsoft.AspNetCore.Mvc.CompatibilityVersion version) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcCoreServiceCollectionExtensions` in `Microsoft.AspNetCore.Mvc.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcCoreServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddMvcCore(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Cors.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Cors.cs index 817984f8330..d261e299d25 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Cors.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Cors.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Cors, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Cors { - // Generated from `Microsoft.AspNetCore.Mvc.Cors.CorsAuthorizationFilter` in `Microsoft.AspNetCore.Mvc.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CorsAuthorizationFilter : Microsoft.AspNetCore.Mvc.Filters.IAsyncAuthorizationFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public CorsAuthorizationFilter(Microsoft.AspNetCore.Cors.Infrastructure.ICorsService corsService, Microsoft.AspNetCore.Cors.Infrastructure.ICorsPolicyProvider policyProvider) => throw null; @@ -18,7 +18,6 @@ namespace Microsoft public string PolicyName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Cors.ICorsAuthorizationFilter` in `Microsoft.AspNetCore.Mvc.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface ICorsAuthorizationFilter : Microsoft.AspNetCore.Mvc.Filters.IAsyncAuthorizationFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { } @@ -30,7 +29,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcCorsMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Cors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcCorsMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddCors(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.DataAnnotations.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.DataAnnotations.cs index fca186c6f10..a280c4ccc09 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.DataAnnotations.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.DataAnnotations.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Mvc { - // Generated from `Microsoft.AspNetCore.Mvc.HiddenInputAttribute` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HiddenInputAttribute : System.Attribute { public bool DisplayValue { get => throw null; set => throw null; } @@ -15,26 +15,22 @@ namespace Microsoft namespace DataAnnotations { - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.AttributeAdapterBase<>` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class AttributeAdapterBase : Microsoft.AspNetCore.Mvc.DataAnnotations.ValidationAttributeAdapter, Microsoft.AspNetCore.Mvc.DataAnnotations.IAttributeAdapter, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator where TAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public AttributeAdapterBase(TAttribute attribute, Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer) : base(default(TAttribute), default(Microsoft.Extensions.Localization.IStringLocalizer)) => throw null; public abstract string GetErrorMessage(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase validationContext); } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.IAttributeAdapter` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAttributeAdapter : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator { string GetErrorMessage(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ModelValidationContextBase validationContext); } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.IValidationAttributeAdapterProvider` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValidationAttributeAdapterProvider { Microsoft.AspNetCore.Mvc.DataAnnotations.IAttributeAdapter GetAttributeAdapter(System.ComponentModel.DataAnnotations.ValidationAttribute attribute, Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer); } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.MvcDataAnnotationsLocalizationOptions` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcDataAnnotationsLocalizationOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public System.Func DataAnnotationLocalizerProvider; @@ -43,7 +39,6 @@ namespace Microsoft public MvcDataAnnotationsLocalizationOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.RequiredAttributeAdapter` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequiredAttributeAdapter : Microsoft.AspNetCore.Mvc.DataAnnotations.AttributeAdapterBase { public override void AddValidation(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context) => throw null; @@ -51,7 +46,6 @@ namespace Microsoft public RequiredAttributeAdapter(System.ComponentModel.DataAnnotations.RequiredAttribute attribute, Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer) : base(default(System.ComponentModel.DataAnnotations.RequiredAttribute), default(Microsoft.Extensions.Localization.IStringLocalizer)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.ValidationAttributeAdapter<>` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ValidationAttributeAdapter : Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator where TAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public abstract void AddValidation(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context); @@ -61,14 +55,12 @@ namespace Microsoft public ValidationAttributeAdapter(TAttribute attribute, Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.ValidationAttributeAdapterProvider` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationAttributeAdapterProvider : Microsoft.AspNetCore.Mvc.DataAnnotations.IValidationAttributeAdapterProvider { public Microsoft.AspNetCore.Mvc.DataAnnotations.IAttributeAdapter GetAttributeAdapter(System.ComponentModel.DataAnnotations.ValidationAttribute attribute, Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer) => throw null; public ValidationAttributeAdapterProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.DataAnnotations.ValidationProviderAttribute` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ValidationProviderAttribute : System.Attribute { public abstract System.Collections.Generic.IEnumerable GetValidationAttributes(); @@ -82,14 +74,12 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcDataAnnotationsMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcDataAnnotationsMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddDataAnnotationsLocalization(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder) => throw null; public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddDataAnnotationsLocalization(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action setupAction) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcDataAnnotationsMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcDataAnnotationsMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddDataAnnotations(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Formatters.Xml.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Formatters.Xml.cs index 4bd39721b4e..3072a22a4da 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Formatters.Xml.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Formatters.Xml.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Formatters { - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerInputFormatter` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlDataContractSerializerInputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextInputFormatter, Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy { protected override bool CanReadType(System.Type type) => throw null; @@ -25,7 +25,6 @@ namespace Microsoft public System.Xml.XmlDictionaryReaderQuotas XmlDictionaryReaderQuotas { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.XmlDataContractSerializerOutputFormatter` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlDataContractSerializerOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter { protected override bool CanWriteType(System.Type type) => throw null; @@ -44,7 +43,6 @@ namespace Microsoft public XmlDataContractSerializerOutputFormatter(System.Xml.XmlWriterSettings writerSettings, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerInputFormatter` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlSerializerInputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextInputFormatter, Microsoft.AspNetCore.Mvc.Formatters.IInputFormatterExceptionPolicy { protected override bool CanReadType(System.Type type) => throw null; @@ -61,7 +59,6 @@ namespace Microsoft public XmlSerializerInputFormatter(Microsoft.AspNetCore.Mvc.MvcOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.XmlSerializerOutputFormatter` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlSerializerOutputFormatter : Microsoft.AspNetCore.Mvc.Formatters.TextOutputFormatter { protected override bool CanWriteType(System.Type type) => throw null; @@ -82,7 +79,6 @@ namespace Microsoft namespace Xml { - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.DelegatingEnumerable<,>` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DelegatingEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public void Add(object item) => throw null; @@ -92,7 +88,6 @@ namespace Microsoft System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.DelegatingEnumerator<,>` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DelegatingEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public TWrapped Current { get => throw null; } @@ -103,7 +98,6 @@ namespace Microsoft public void Reset() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.EnumerableWrapperProvider` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnumerableWrapperProvider : Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider { public EnumerableWrapperProvider(System.Type sourceEnumerableOfT, Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider elementWrapperProvider) => throw null; @@ -111,33 +105,28 @@ namespace Microsoft public System.Type WrappingType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.EnumerableWrapperProviderFactory` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnumerableWrapperProviderFactory : Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProviderFactory { public EnumerableWrapperProviderFactory(System.Collections.Generic.IEnumerable wrapperProviderFactories) => throw null; public Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider GetProvider(Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.IUnwrappable` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUnwrappable { object Unwrap(System.Type declaredType); } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IWrapperProvider { object Wrap(object original); System.Type WrappingType { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProviderFactory` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IWrapperProviderFactory { Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider GetProvider(Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.MvcXmlOptions` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcXmlOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; @@ -145,7 +134,6 @@ namespace Microsoft public MvcXmlOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetailsWrapper` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProblemDetailsWrapper : Microsoft.AspNetCore.Mvc.Formatters.Xml.IUnwrappable, System.Xml.Serialization.IXmlSerializable { protected static string EmptyKey; @@ -158,7 +146,6 @@ namespace Microsoft public virtual void WriteXml(System.Xml.XmlWriter writer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.SerializableErrorWrapper` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SerializableErrorWrapper : Microsoft.AspNetCore.Mvc.Formatters.Xml.IUnwrappable, System.Xml.Serialization.IXmlSerializable { public System.Xml.Schema.XmlSchema GetSchema() => throw null; @@ -170,7 +157,6 @@ namespace Microsoft public void WriteXml(System.Xml.XmlWriter writer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.SerializableErrorWrapperProvider` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SerializableErrorWrapperProvider : Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider { public SerializableErrorWrapperProvider() => throw null; @@ -178,14 +164,12 @@ namespace Microsoft public System.Type WrappingType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.SerializableErrorWrapperProviderFactory` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SerializableErrorWrapperProviderFactory : Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProviderFactory { public Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider GetProvider(Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderContext context) => throw null; public SerializableErrorWrapperProviderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.ValidationProblemDetailsWrapper` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationProblemDetailsWrapper : Microsoft.AspNetCore.Mvc.Formatters.Xml.ProblemDetailsWrapper, Microsoft.AspNetCore.Mvc.Formatters.Xml.IUnwrappable { protected override void ReadValue(System.Xml.XmlReader reader, string name) => throw null; @@ -195,7 +179,6 @@ namespace Microsoft public override void WriteXml(System.Xml.XmlWriter writer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderContext` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WrapperProviderContext { public System.Type DeclaredType { get => throw null; } @@ -203,7 +186,6 @@ namespace Microsoft public WrapperProviderContext(System.Type declaredType, bool isSerialization) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderFactoriesExtensions` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WrapperProviderFactoriesExtensions { public static Microsoft.AspNetCore.Mvc.Formatters.Xml.IWrapperProvider GetWrapperProvider(this System.Collections.Generic.IEnumerable wrapperProviderFactories, Microsoft.AspNetCore.Mvc.Formatters.Xml.WrapperProviderContext wrapperProviderContext) => throw null; @@ -215,7 +197,6 @@ namespace Microsoft { namespace Metadata { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.DataMemberRequiredBindingMetadataProvider` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataMemberRequiredBindingMetadataProvider : Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IBindingMetadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.IMetadataDetailsProvider { public void CreateBindingMetadata(Microsoft.AspNetCore.Mvc.ModelBinding.Metadata.BindingMetadataProviderContext context) => throw null; @@ -230,7 +211,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcXmlMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcXmlMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddXmlDataContractSerializerFormatters(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder) => throw null; @@ -240,7 +220,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddXmlSerializerFormatters(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action setupAction) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcXmlMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Formatters.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcXmlMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddXmlDataContractSerializerFormatters(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Localization.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Localization.cs index f024a16dc78..2e1d41380f9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Localization.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Localization.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Localization, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Localization { - // Generated from `Microsoft.AspNetCore.Mvc.Localization.HtmlLocalizer` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlLocalizer : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer { public virtual System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures) => throw null; @@ -21,7 +21,6 @@ namespace Microsoft protected virtual Microsoft.AspNetCore.Mvc.Localization.LocalizedHtmlString ToHtmlString(Microsoft.Extensions.Localization.LocalizedString result, object[] arguments) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.HtmlLocalizer<>` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlLocalizer : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer, Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer { public virtual System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures) => throw null; @@ -32,7 +31,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.Localization.LocalizedHtmlString this[string name] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.HtmlLocalizerExtensions` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlLocalizerExtensions { public static System.Collections.Generic.IEnumerable GetAllStrings(this Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer htmlLocalizer) => throw null; @@ -40,7 +38,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Mvc.Localization.LocalizedHtmlString GetHtml(this Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer htmlLocalizer, string name, params object[] arguments) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.HtmlLocalizerFactory` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlLocalizerFactory : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizerFactory { public virtual Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer Create(System.Type resourceSource) => throw null; @@ -48,7 +45,6 @@ namespace Microsoft public HtmlLocalizerFactory(Microsoft.Extensions.Localization.IStringLocalizerFactory localizerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlLocalizer { System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures); @@ -58,24 +54,20 @@ namespace Microsoft Microsoft.AspNetCore.Mvc.Localization.LocalizedHtmlString this[string name] { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer<>` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlLocalizer : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer { } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizerFactory` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlLocalizerFactory { Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer Create(System.Type resourceSource); Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer Create(string baseName, string location); } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewLocalizer : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer { } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.LocalizedHtmlString` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocalizedHtmlString : Microsoft.AspNetCore.Html.IHtmlContent { public bool IsResourceNotFound { get => throw null; } @@ -87,7 +79,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Localization.ViewLocalizer` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewLocalizer : Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer, Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer, Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware { public void Contextualize(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext) => throw null; @@ -106,7 +97,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcLocalizationMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcLocalizationMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddMvcLocalization(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder) => throw null; @@ -123,7 +113,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddViewLocalization(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat format, System.Action setupAction) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcLocalizationMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcLocalizationMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddMvcLocalization(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Razor.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Razor.cs index 0ae59044a30..eba7a1fa50f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Razor.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.Razor.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.Razor, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace ApplicationParts { - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.CompiledRazorAssemblyApplicationPartFactory` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompiledRazorAssemblyApplicationPartFactory : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartFactory { public CompiledRazorAssemblyApplicationPartFactory() => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public static System.Collections.Generic.IEnumerable GetDefaultApplicationParts(System.Reflection.Assembly assembly) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.CompiledRazorAssemblyPart` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompiledRazorAssemblyPart : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPart, Microsoft.AspNetCore.Mvc.ApplicationParts.IRazorCompiledItemProvider { public System.Reflection.Assembly Assembly { get => throw null; } @@ -25,14 +24,12 @@ namespace Microsoft public override string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.ConsolidatedAssemblyApplicationPartFactory` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsolidatedAssemblyApplicationPartFactory : Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartFactory { public ConsolidatedAssemblyApplicationPartFactory() => throw null; public override System.Collections.Generic.IEnumerable GetApplicationParts(System.Reflection.Assembly assembly) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationParts.IRazorCompiledItemProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorCompiledItemProvider { System.Collections.Generic.IEnumerable CompiledItems { get; } @@ -41,7 +38,6 @@ namespace Microsoft } namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterViewPageEventData` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterViewPageEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -54,7 +50,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeViewPageEventData` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeViewPageEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -70,7 +65,6 @@ namespace Microsoft } namespace Razor { - // Generated from `Microsoft.AspNetCore.Mvc.Razor.HelperResult` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HelperResult : Microsoft.AspNetCore.Html.IHtmlContent { public HelperResult(System.Func asyncAction) => throw null; @@ -78,12 +72,10 @@ namespace Microsoft public virtual void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IModelTypeProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IModelTypeProvider { } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IRazorPage` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorPage { Microsoft.AspNetCore.Html.IHtmlContent BodyContent { get; set; } @@ -97,19 +89,16 @@ namespace Microsoft Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get; set; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorPageActivator { void Activate(Microsoft.AspNetCore.Mvc.Razor.IRazorPage page, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IRazorPageFactoryProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorPageFactoryProvider { Microsoft.AspNetCore.Mvc.Razor.RazorPageFactoryResult CreateFactory(string relativePath); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorViewEngine : Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine { Microsoft.AspNetCore.Mvc.Razor.RazorPageResult FindPage(Microsoft.AspNetCore.Mvc.ActionContext context, string pageName); @@ -117,32 +106,27 @@ namespace Microsoft Microsoft.AspNetCore.Mvc.Razor.RazorPageResult GetPage(string executingFilePath, string pagePath); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.ITagHelperActivator` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperActivator { TTagHelper Create(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) where TTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.ITagHelperFactory` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperFactory { TTagHelper CreateTagHelper(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) where TTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.ITagHelperInitializer<>` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperInitializer where TTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper { void Initialize(TTagHelper helper, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.IViewLocationExpander` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewLocationExpander { System.Collections.Generic.IEnumerable ExpandViewLocations(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context, System.Collections.Generic.IEnumerable viewLocations); void PopulateValues(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpander` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LanguageViewLocationExpander : Microsoft.AspNetCore.Mvc.Razor.IViewLocationExpander { public virtual System.Collections.Generic.IEnumerable ExpandViewLocations(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context, System.Collections.Generic.IEnumerable viewLocations) => throw null; @@ -151,14 +135,12 @@ namespace Microsoft public void PopulateValues(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum LanguageViewLocationExpanderFormat : int { SubFolder = 0, Suffix = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPage` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RazorPage : Microsoft.AspNetCore.Mvc.Razor.RazorPageBase { public override void BeginContext(int position, int length, bool isLiteral) => throw null; @@ -177,7 +159,6 @@ namespace Microsoft public System.Threading.Tasks.Task RenderSectionAsync(string name, bool required) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPage<>` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RazorPage : Microsoft.AspNetCore.Mvc.Razor.RazorPage { public TModel Model { get => throw null; } @@ -185,14 +166,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPageActivator` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorPageActivator : Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator { public void Activate(Microsoft.AspNetCore.Mvc.Razor.IRazorPage page, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) => throw null; public RazorPageActivator(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, Microsoft.AspNetCore.Mvc.Routing.IUrlHelperFactory urlHelperFactory, Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper jsonHelper, System.Diagnostics.DiagnosticSource diagnosticSource, System.Text.Encodings.Web.HtmlEncoder htmlEncoder, Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider modelExpressionProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPageBase` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RazorPageBase : Microsoft.AspNetCore.Mvc.Razor.IRazorPage { public void AddHtmlAttributeValue(string prefix, int prefixOffset, object value, int valueOffset, int valueLength, bool isLiteral) => throw null; @@ -238,7 +217,6 @@ namespace Microsoft public virtual void WriteLiteral(string value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPageFactoryResult` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RazorPageFactoryResult { public System.Func RazorPageFactory { get => throw null; } @@ -248,7 +226,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Razor.Compilation.CompiledViewDescriptor ViewDescriptor { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorPageResult` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RazorPageResult { public string Name { get => throw null; } @@ -259,7 +236,6 @@ namespace Microsoft public System.Collections.Generic.IEnumerable SearchedLocations { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorView` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorView : Microsoft.AspNetCore.Mvc.ViewEngines.IView { public string Path { get => throw null; } @@ -269,7 +245,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList ViewStartPages { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorViewEngine` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorViewEngine : Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine, Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine { public Microsoft.AspNetCore.Mvc.Razor.RazorPageResult FindPage(Microsoft.AspNetCore.Mvc.ActionContext context, string pageName) => throw null; @@ -283,7 +258,6 @@ namespace Microsoft protected internal Microsoft.Extensions.Caching.Memory.IMemoryCache ViewLookupCache { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RazorViewEngineOptions` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorViewEngineOptions { public System.Collections.Generic.IList AreaPageViewLocationFormats { get => throw null; } @@ -294,17 +268,14 @@ namespace Microsoft public System.Collections.Generic.IList ViewLocationFormats { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.RenderAsyncDelegate` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task RenderAsyncDelegate(); - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelperInitializer<>` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperInitializer : Microsoft.AspNetCore.Mvc.Razor.ITagHelperInitializer where TTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper { public void Initialize(TTagHelper helper, Microsoft.AspNetCore.Mvc.Rendering.ViewContext context) => throw null; public TagHelperInitializer(System.Action action) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewLocationExpanderContext { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -319,7 +290,6 @@ namespace Microsoft namespace Compilation { - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Compilation.CompiledViewDescriptor` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompiledViewDescriptor { public CompiledViewDescriptor() => throw null; @@ -332,19 +302,16 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute ViewAttribute { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Compilation.IViewCompiler` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewCompiler { System.Threading.Tasks.Task CompileAsync(string relativePath); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Compilation.IViewCompilerProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewCompilerProvider { Microsoft.AspNetCore.Mvc.Razor.Compilation.IViewCompiler GetCompiler(); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorViewAttribute : System.Attribute { public string Path { get => throw null; } @@ -352,7 +319,6 @@ namespace Microsoft public System.Type ViewType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Compilation.ViewsFeature` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewsFeature { public System.Collections.Generic.IList ViewDescriptors { get => throw null; } @@ -362,7 +328,6 @@ namespace Microsoft } namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Infrastructure.TagHelperMemoryCacheProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperMemoryCacheProvider { public Microsoft.Extensions.Caching.Memory.IMemoryCache Cache { get => throw null; set => throw null; } @@ -372,7 +337,6 @@ namespace Microsoft } namespace Internal { - // Generated from `Microsoft.AspNetCore.Mvc.Razor.Internal.RazorInjectAttribute` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorInjectAttribute : System.Attribute { public RazorInjectAttribute() => throw null; @@ -381,31 +345,26 @@ namespace Microsoft } namespace TagHelpers { - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.BodyTagHelper` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BodyTagHelper : Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperComponentTagHelper { public BodyTagHelper(Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentManager manager, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base(default(Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentManager), default(Microsoft.Extensions.Logging.ILoggerFactory)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.HeadTagHelper` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HeadTagHelper : Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperComponentTagHelper { public HeadTagHelper(Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentManager manager, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base(default(Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentManager), default(Microsoft.Extensions.Logging.ILoggerFactory)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentManager` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperComponentManager { System.Collections.Generic.ICollection Components { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.ITagHelperComponentPropertyActivator` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperComponentPropertyActivator { void Activate(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context, Microsoft.AspNetCore.Razor.TagHelpers.ITagHelperComponent tagHelperComponent); } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperComponentTagHelper` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TagHelperComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public override void Init(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context) => throw null; @@ -415,14 +374,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperFeature` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperFeature { public TagHelperFeature() => throw null; public System.Collections.Generic.IList TagHelpers { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.TagHelperFeatureProvider` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperFeatureProvider : Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider, Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider { protected virtual bool IncludePart(Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPart part) => throw null; @@ -431,7 +388,6 @@ namespace Microsoft public TagHelperFeatureProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlResolutionTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { protected System.Text.Encodings.Web.HtmlEncoder HtmlEncoder { get => throw null; } @@ -453,7 +409,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcRazorMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcRazorMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddRazorOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action setupAction) => throw null; @@ -461,7 +416,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder InitializeTagHelper(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action initialize) where TTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcRazorMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcRazorMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddRazorViewEngine(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.RazorPages.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.RazorPages.cs index 509885cda09..b1967712e1c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.RazorPages.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.RazorPages.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.RazorPages, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.PageActionEndpointConventionBuilder` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageActionEndpointConventionBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RazorPagesEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RazorPagesEndpointRouteBuilderExtensions { public static void MapDynamicPageRoute(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) where TTransformer : Microsoft.AspNetCore.Mvc.Routing.DynamicRouteValueTransformer => throw null; @@ -30,13 +30,11 @@ namespace Microsoft { namespace ApplicationModels { - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageApplicationModelConvention` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageApplicationModelConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.PageApplicationModel model); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageApplicationModelPartsProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageApplicationModelPartsProvider { Microsoft.AspNetCore.Mvc.ApplicationModels.PageHandlerModel CreateHandlerModel(System.Reflection.MethodInfo method); @@ -45,7 +43,6 @@ namespace Microsoft bool IsHandler(System.Reflection.MethodInfo methodInfo); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageApplicationModelProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageApplicationModelProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.ApplicationModels.PageApplicationModelProviderContext context); @@ -53,24 +50,20 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageConvention { } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageHandlerModelConvention` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageHandlerModelConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.PageHandlerModel model); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageRouteModelConvention` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageRouteModelConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention { void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteModel model); } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.IPageRouteModelProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageRouteModelProvider { void OnProvidersExecuted(Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteModelProviderContext context); @@ -78,7 +71,6 @@ namespace Microsoft int Order { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageApplicationModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageApplicationModel { public Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor ActionDescriptor { get => throw null; } @@ -101,7 +93,6 @@ namespace Microsoft public string ViewEnginePath { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageApplicationModelProviderContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageApplicationModelProviderContext { public Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor ActionDescriptor { get => throw null; } @@ -110,7 +101,6 @@ namespace Microsoft public System.Reflection.TypeInfo PageType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageConventionCollection` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageConventionCollection : System.Collections.ObjectModel.Collection { public Microsoft.AspNetCore.Mvc.ApplicationModels.IPageApplicationModelConvention AddAreaFolderApplicationModelConvention(string areaName, string folderPath, System.Action action) => throw null; @@ -127,7 +117,6 @@ namespace Microsoft public void RemoveType() where TPageConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageHandlerModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageHandlerModel : Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public System.Collections.Generic.IReadOnlyList Attributes { get => throw null; } @@ -143,7 +132,6 @@ namespace Microsoft public System.Collections.Generic.IDictionary Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageParameterModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageParameterModel : Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase, Microsoft.AspNetCore.Mvc.ApplicationModels.IBindingModel, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { public Microsoft.AspNetCore.Mvc.ApplicationModels.PageHandlerModel Handler { get => throw null; set => throw null; } @@ -154,7 +142,6 @@ namespace Microsoft public string ParameterName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PagePropertyModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PagePropertyModel : Microsoft.AspNetCore.Mvc.ApplicationModels.ParameterModelBase, Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel, Microsoft.AspNetCore.Mvc.ApplicationModels.IPropertyModel { System.Reflection.MemberInfo Microsoft.AspNetCore.Mvc.ApplicationModels.ICommonModel.MemberInfo { get => throw null; } @@ -165,7 +152,6 @@ namespace Microsoft public string PropertyName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteMetadata` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageRouteMetadata { public string PageRoute { get => throw null; } @@ -173,7 +159,6 @@ namespace Microsoft public string RouteTemplate { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageRouteModel { public string AreaName { get => throw null; } @@ -188,14 +173,12 @@ namespace Microsoft public string ViewEnginePath { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteModelProviderContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageRouteModelProviderContext { public PageRouteModelProviderContext() => throw null; public System.Collections.Generic.IList RouteModels { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteTransformerConvention` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageRouteTransformerConvention : Microsoft.AspNetCore.Mvc.ApplicationModels.IPageConvention, Microsoft.AspNetCore.Mvc.ApplicationModels.IPageRouteModelConvention { public void Apply(Microsoft.AspNetCore.Mvc.ApplicationModels.PageRouteModel model) => throw null; @@ -206,7 +189,6 @@ namespace Microsoft } namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterHandlerMethodEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterHandlerMethodEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -220,7 +202,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterPageFilterOnPageHandlerExecutedEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterPageFilterOnPageHandlerExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -232,7 +213,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterPageFilterOnPageHandlerExecutingEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterPageFilterOnPageHandlerExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -244,7 +224,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterPageFilterOnPageHandlerExecutionEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterPageFilterOnPageHandlerExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -256,7 +235,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterPageFilterOnPageHandlerSelectedEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterPageFilterOnPageHandlerSelectedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -268,7 +246,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterPageFilterOnPageHandlerSelectionEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterPageFilterOnPageHandlerSelectionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -280,7 +257,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeHandlerMethodEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeHandlerMethodEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -293,7 +269,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforePageFilterOnPageHandlerExecutedEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforePageFilterOnPageHandlerExecutedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -305,7 +280,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforePageFilterOnPageHandlerExecutingEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforePageFilterOnPageHandlerExecutingEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -317,7 +291,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforePageFilterOnPageHandlerExecutionEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforePageFilterOnPageHandlerExecutionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -329,7 +302,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforePageFilterOnPageHandlerSelectedEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforePageFilterOnPageHandlerSelectedEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -341,7 +313,6 @@ namespace Microsoft protected override System.Collections.Generic.KeyValuePair this[int index] { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforePageFilterOnPageHandlerSelectionEventData` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforePageFilterOnPageHandlerSelectionEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -356,14 +327,12 @@ namespace Microsoft } namespace Filters { - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IAsyncPageFilter` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAsyncPageFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { System.Threading.Tasks.Task OnPageHandlerExecutionAsync(Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutingContext context, Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutionDelegate next); System.Threading.Tasks.Task OnPageHandlerSelectionAsync(Microsoft.AspNetCore.Mvc.Filters.PageHandlerSelectedContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.IPageFilter` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageFilter : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { void OnPageHandlerExecuted(Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutedContext context); @@ -371,7 +340,6 @@ namespace Microsoft void OnPageHandlerSelected(Microsoft.AspNetCore.Mvc.Filters.PageHandlerSelectedContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutedContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageHandlerExecutedContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -385,7 +353,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutingContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageHandlerExecutingContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -396,10 +363,8 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Mvc.IActionResult Result { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutionDelegate` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate System.Threading.Tasks.Task PageHandlerExecutionDelegate(); - // Generated from `Microsoft.AspNetCore.Mvc.Filters.PageHandlerSelectedContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageHandlerSelectedContext : Microsoft.AspNetCore.Mvc.Filters.FilterContext { public virtual Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; } @@ -411,7 +376,6 @@ namespace Microsoft } namespace RazorPages { - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompiledPageActionDescriptor : Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor { public CompiledPageActionDescriptor() => throw null; @@ -424,7 +388,6 @@ namespace Microsoft public System.Reflection.TypeInfo PageTypeInfo { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.IPageActivatorProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageActivatorProvider { System.Func CreateActivator(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); @@ -432,7 +395,6 @@ namespace Microsoft System.Action CreateReleaser(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.IPageFactoryProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageFactoryProvider { System.Func CreateAsyncPageDisposer(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor) => throw null; @@ -440,7 +402,6 @@ namespace Microsoft System.Func CreatePageFactory(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.IPageModelActivatorProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageModelActivatorProvider { System.Func CreateActivator(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); @@ -448,7 +409,6 @@ namespace Microsoft System.Action CreateReleaser(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.IPageModelFactoryProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageModelFactoryProvider { System.Func CreateAsyncModelDisposer(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor) => throw null; @@ -456,19 +416,16 @@ namespace Microsoft System.Func CreateModelFactory(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.NonHandlerAttribute` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NonHandlerAttribute : System.Attribute { public NonHandlerAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Page` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Page : Microsoft.AspNetCore.Mvc.RazorPages.PageBase { protected Page() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageActionDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor { public string AreaName { get => throw null; set => throw null; } @@ -479,7 +436,6 @@ namespace Microsoft public string ViewEnginePath { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageBase` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PageBase : Microsoft.AspNetCore.Mvc.Razor.RazorPageBase { public virtual Microsoft.AspNetCore.Mvc.BadRequestResult BadRequest() => throw null; @@ -595,7 +551,6 @@ namespace Microsoft public override Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageContext` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageContext : Microsoft.AspNetCore.Mvc.ActionContext { public virtual Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor ActionDescriptor { get => throw null; set => throw null; } @@ -606,13 +561,11 @@ namespace Microsoft public virtual System.Collections.Generic.IList> ViewStartFactories { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageContextAttribute` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageContextAttribute : System.Attribute { public PageContextAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageModel` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PageModel : Microsoft.AspNetCore.Mvc.Filters.IAsyncPageFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IPageFilter { public virtual Microsoft.AspNetCore.Mvc.BadRequestResult BadRequest() => throw null; @@ -735,7 +688,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.PageResult` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageResult : Microsoft.AspNetCore.Mvc.ActionResult { public string ContentType { get => throw null; set => throw null; } @@ -747,7 +699,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.RazorPagesOptions` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorPagesOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public Microsoft.AspNetCore.Mvc.ApplicationModels.PageConventionCollection Conventions { get => throw null; set => throw null; } @@ -759,7 +710,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.CompiledPageActionDescriptorProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompiledPageActionDescriptorProvider : Microsoft.AspNetCore.Mvc.Abstractions.IActionDescriptorProvider { public CompiledPageActionDescriptorProvider(System.Collections.Generic.IEnumerable pageRouteModelProviders, System.Collections.Generic.IEnumerable applicationModelProviders, Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager applicationPartManager, Microsoft.Extensions.Options.IOptions mvcOptions, Microsoft.Extensions.Options.IOptions pageOptions) => throw null; @@ -768,7 +718,6 @@ namespace Microsoft public int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.HandlerMethodDescriptor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandlerMethodDescriptor { public HandlerMethodDescriptor() => throw null; @@ -778,26 +727,22 @@ namespace Microsoft public System.Collections.Generic.IList Parameters { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.HandlerParameterDescriptor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandlerParameterDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor, Microsoft.AspNetCore.Mvc.Infrastructure.IParameterInfoParameterDescriptor { public HandlerParameterDescriptor() => throw null; public System.Reflection.ParameterInfo ParameterInfo { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.IPageHandlerMethodSelector` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageHandlerMethodSelector { Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.HandlerMethodDescriptor Select(Microsoft.AspNetCore.Mvc.RazorPages.PageContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.IPageLoader` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPageLoader { Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor Load(Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor actionDescriptor); } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionDescriptorProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageActionDescriptorProvider : Microsoft.AspNetCore.Mvc.Abstractions.IActionDescriptorProvider { protected System.Collections.Generic.IList BuildModel() => throw null; @@ -807,7 +752,6 @@ namespace Microsoft public PageActionDescriptorProvider(System.Collections.Generic.IEnumerable pageRouteModelProviders, Microsoft.Extensions.Options.IOptions mvcOptionsAccessor, Microsoft.Extensions.Options.IOptions pagesOptionsAccessor) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageBoundPropertyDescriptor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageBoundPropertyDescriptor : Microsoft.AspNetCore.Mvc.Abstractions.ParameterDescriptor, Microsoft.AspNetCore.Mvc.Infrastructure.IPropertyInfoParameterDescriptor { public PageBoundPropertyDescriptor() => throw null; @@ -815,7 +759,6 @@ namespace Microsoft System.Reflection.PropertyInfo Microsoft.AspNetCore.Mvc.Infrastructure.IPropertyInfoParameterDescriptor.PropertyInfo { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageLoader` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PageLoader : Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.IPageLoader { Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.IPageLoader.Load(Microsoft.AspNetCore.Mvc.RazorPages.PageActionDescriptor actionDescriptor) => throw null; @@ -824,20 +767,17 @@ namespace Microsoft protected PageLoader() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageModelAttribute` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageModelAttribute : System.Attribute { public PageModelAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageResultExecutor` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageResultExecutor : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.RazorPages.PageContext pageContext, Microsoft.AspNetCore.Mvc.RazorPages.PageResult result) => throw null; public PageResultExecutor(Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory writerFactory, Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine compositeViewEngine, Microsoft.AspNetCore.Mvc.Razor.IRazorViewEngine razorViewEngine, Microsoft.AspNetCore.Mvc.Razor.IRazorPageActivator razorPageActivator, System.Diagnostics.DiagnosticListener diagnosticListener, System.Text.Encodings.Web.HtmlEncoder htmlEncoder) : base(default(Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory), default(Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine), default(System.Diagnostics.DiagnosticListener)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageViewLocationExpander` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageViewLocationExpander : Microsoft.AspNetCore.Mvc.Razor.IViewLocationExpander { public System.Collections.Generic.IEnumerable ExpandViewLocations(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context, System.Collections.Generic.IEnumerable viewLocations) => throw null; @@ -845,7 +785,6 @@ namespace Microsoft public void PopulateValues(Microsoft.AspNetCore.Mvc.Razor.ViewLocationExpanderContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAdapter` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorPageAdapter : Microsoft.AspNetCore.Mvc.Razor.IRazorPage { public Microsoft.AspNetCore.Html.IHtmlContent BodyContent { get => throw null; set => throw null; } @@ -860,14 +799,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.RazorPageAttribute` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorPageAttribute : Microsoft.AspNetCore.Mvc.Razor.Compilation.RazorViewAttribute { public RazorPageAttribute(string path, System.Type viewType, string routeTemplate) : base(default(string), default(System.Type)) => throw null; public string RouteTemplate { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ServiceBasedPageModelActivatorProvider` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceBasedPageModelActivatorProvider : Microsoft.AspNetCore.Mvc.RazorPages.IPageModelActivatorProvider { public System.Func CreateActivator(Microsoft.AspNetCore.Mvc.RazorPages.CompiledPageActionDescriptor descriptor) => throw null; @@ -883,7 +820,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcRazorPagesMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcRazorPagesMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddRazorPagesOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action setupAction) => throw null; @@ -891,7 +827,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder WithRazorPagesRoot(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, string rootDirectory) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcRazorPagesMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcRazorPagesMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddRazorPages(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; @@ -899,7 +834,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder WithRazorPagesRoot(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder, string rootDirectory) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.PageConventionCollectionExtensions` in `Microsoft.AspNetCore.Mvc.RazorPages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class PageConventionCollectionExtensions { public static Microsoft.AspNetCore.Mvc.ApplicationModels.PageConventionCollection Add(this Microsoft.AspNetCore.Mvc.ApplicationModels.PageConventionCollection conventions, Microsoft.AspNetCore.Mvc.ApplicationModels.IParameterModelBaseConvention convention) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.TagHelpers.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.TagHelpers.cs index 9af16469d1c..1baf6c52f14 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.TagHelpers.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.TagHelpers.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.TagHelpers, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Rendering { - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.ValidationSummary` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ValidationSummary : int { All = 2, @@ -19,7 +19,6 @@ namespace Microsoft } namespace TagHelpers { - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AnchorTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public string Action { get => throw null; set => throw null; } @@ -39,7 +38,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheTagHelper : Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelperBase { public static string CacheKeyPrefix; @@ -49,7 +47,6 @@ namespace Microsoft public override System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelperBase` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class CacheTagHelperBase : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public CacheTagHelperBase(System.Text.Encodings.Web.HtmlEncoder htmlEncoder) => throw null; @@ -70,21 +67,18 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelperMemoryCacheFactory` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheTagHelperMemoryCacheFactory { public Microsoft.Extensions.Caching.Memory.IMemoryCache Cache { get => throw null; } public CacheTagHelperMemoryCacheFactory(Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelperOptions` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheTagHelperOptions { public CacheTagHelperOptions() => throw null; public System.Int64 SizeLimit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.ComponentTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ComponentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public ComponentTagHelper() => throw null; @@ -95,7 +89,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.DistributedCacheTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheTagHelper : Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelperBase { public static string CacheKeyPrefix; @@ -105,7 +98,6 @@ namespace Microsoft public override System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.EnvironmentTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnvironmentTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public EnvironmentTagHelper(Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment) => throw null; @@ -117,7 +109,6 @@ namespace Microsoft public override void Process(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.FormActionTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormActionTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public string Action { get => throw null; set => throw null; } @@ -135,7 +126,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.FormTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public string Action { get => throw null; set => throw null; } @@ -155,7 +145,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.GlobbingUrlBuilder` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class GlobbingUrlBuilder { public virtual System.Collections.Generic.IReadOnlyList BuildUrlList(string staticUrl, string includePattern, string excludePattern) => throw null; @@ -165,7 +154,6 @@ namespace Microsoft public Microsoft.AspNetCore.Http.PathString RequestPathBase { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.ImageTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ImageTagHelper : Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper { public bool AppendVersion { get => throw null; set => throw null; } @@ -178,7 +166,6 @@ namespace Microsoft public string Src { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.InputTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InputTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression For { get => throw null; set => throw null; } @@ -194,7 +181,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.LabelTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LabelTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression For { get => throw null; set => throw null; } @@ -205,7 +191,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.LinkTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LinkTagHelper : Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper { public bool? AppendVersion { get => throw null; set => throw null; } @@ -228,7 +213,6 @@ namespace Microsoft public bool SuppressFallbackIntegrity { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.OptionTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { protected Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator Generator { get => throw null; } @@ -239,7 +223,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.PartialTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PartialTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public string FallbackName { get => throw null; set => throw null; } @@ -253,7 +236,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.PersistComponentStateTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PersistComponentStateTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public PersistComponentStateTagHelper() => throw null; @@ -262,14 +244,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.PersistenceMode` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum PersistenceMode : int { Server = 0, WebAssembly = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.RenderAtEndOfFormTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RenderAtEndOfFormTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public override void Init(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context) => throw null; @@ -279,7 +259,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.ScriptTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ScriptTagHelper : Microsoft.AspNetCore.Mvc.Razor.TagHelpers.UrlResolutionTagHelper { public bool? AppendVersion { get => throw null; set => throw null; } @@ -300,7 +279,6 @@ namespace Microsoft public bool SuppressFallbackIntegrity { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.SelectTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SelectTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression For { get => throw null; set => throw null; } @@ -314,7 +292,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.TagHelperOutputExtensions` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class TagHelperOutputExtensions { public static void AddClass(this Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput tagHelperOutput, string classValue, System.Text.Encodings.Web.HtmlEncoder htmlEncoder) => throw null; @@ -324,7 +301,6 @@ namespace Microsoft public static void RemoveRange(this Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput tagHelperOutput, System.Collections.Generic.IEnumerable attributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.TextAreaTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TextAreaTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression For { get => throw null; set => throw null; } @@ -336,7 +312,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.ValidationMessageTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationMessageTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression For { get => throw null; set => throw null; } @@ -347,7 +322,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.ValidationSummaryTagHelper` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidationSummaryTagHelper : Microsoft.AspNetCore.Razor.TagHelpers.TagHelper { protected Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator Generator { get => throw null; } @@ -360,7 +334,6 @@ namespace Microsoft namespace Cache { - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.CacheTagKey` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheTagKey : System.IEquatable { public CacheTagKey(Microsoft.AspNetCore.Mvc.TagHelpers.CacheTagHelper tagHelper, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context) => throw null; @@ -372,7 +345,6 @@ namespace Microsoft public override int GetHashCode() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperFormatter` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheTagHelperFormatter : Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperFormatter { public System.Threading.Tasks.Task DeserializeAsync(System.Byte[] value) => throw null; @@ -380,21 +352,18 @@ namespace Microsoft public System.Threading.Tasks.Task SerializeAsync(Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperFormattingContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperFormattingContext` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheTagHelperFormattingContext { public DistributedCacheTagHelperFormattingContext() => throw null; public Microsoft.AspNetCore.Html.HtmlString Html { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperService` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheTagHelperService : Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperService { public DistributedCacheTagHelperService(Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperStorage storage, Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperFormatter formatter, System.Text.Encodings.Web.HtmlEncoder HtmlEncoder, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public System.Threading.Tasks.Task ProcessContentAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output, Microsoft.AspNetCore.Mvc.TagHelpers.Cache.CacheTagKey key, Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperStorage` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheTagHelperStorage : Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperStorage { public DistributedCacheTagHelperStorage(Microsoft.Extensions.Caching.Distributed.IDistributedCache distributedCache) => throw null; @@ -402,20 +371,17 @@ namespace Microsoft public System.Threading.Tasks.Task SetAsync(string key, System.Byte[] value, Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperFormatter` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDistributedCacheTagHelperFormatter { System.Threading.Tasks.Task DeserializeAsync(System.Byte[] value); System.Threading.Tasks.Task SerializeAsync(Microsoft.AspNetCore.Mvc.TagHelpers.Cache.DistributedCacheTagHelperFormattingContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperService` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDistributedCacheTagHelperService { System.Threading.Tasks.Task ProcessContentAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output, Microsoft.AspNetCore.Mvc.TagHelpers.Cache.CacheTagKey key, Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options); } - // Generated from `Microsoft.AspNetCore.Mvc.TagHelpers.Cache.IDistributedCacheTagHelperStorage` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDistributedCacheTagHelperStorage { System.Threading.Tasks.Task GetAsync(string key); @@ -430,7 +396,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.TagHelperServicesExtensions` in `Microsoft.AspNetCore.Mvc.TagHelpers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class TagHelperServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddCacheTagHelper(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ViewFeatures.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ViewFeatures.cs index 52d495db36c..11c24558c6e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ViewFeatures.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.ViewFeatures.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Mvc { - // Generated from `Microsoft.AspNetCore.Mvc.AutoValidateAntiforgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AutoValidateAntiforgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public AutoValidateAntiforgeryTokenAttribute() => throw null; @@ -15,7 +15,6 @@ namespace Microsoft public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Controller` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Controller : Microsoft.AspNetCore.Mvc.ControllerBase, Microsoft.AspNetCore.Mvc.Filters.IActionFilter, Microsoft.AspNetCore.Mvc.Filters.IAsyncActionFilter, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, System.IDisposable { protected Controller() => throw null; @@ -43,35 +42,30 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.CookieTempDataProviderOptions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieTempDataProviderOptions { public Microsoft.AspNetCore.Http.CookieBuilder Cookie { get => throw null; set => throw null; } public CookieTempDataProviderOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.IViewComponentHelper` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentHelper { System.Threading.Tasks.Task InvokeAsync(System.Type componentType, object arguments); System.Threading.Tasks.Task InvokeAsync(string name, object arguments); } - // Generated from `Microsoft.AspNetCore.Mvc.IViewComponentResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentResult { void Execute(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.IgnoreAntiforgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IgnoreAntiforgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter, Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy { public IgnoreAntiforgeryTokenAttribute() => throw null; public int Order { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.MvcViewOptions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcViewOptions : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public System.Collections.Generic.IList ClientModelValidatorProviders { get => throw null; } @@ -82,7 +76,6 @@ namespace Microsoft public System.Collections.Generic.IList ViewEngines { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.PageRemoteAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PageRemoteAttribute : Microsoft.AspNetCore.Mvc.RemoteAttributeBase { protected override string GetUrl(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context) => throw null; @@ -91,7 +84,6 @@ namespace Microsoft public PageRemoteAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.PartialViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PartialViewResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public string ContentType { get => throw null; set => throw null; } @@ -105,7 +97,6 @@ namespace Microsoft public string ViewName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RemoteAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RemoteAttribute : Microsoft.AspNetCore.Mvc.RemoteAttributeBase { protected override string GetUrl(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context) => throw null; @@ -116,7 +107,6 @@ namespace Microsoft protected string RouteName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.RemoteAttributeBase` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RemoteAttributeBase : System.ComponentModel.DataAnnotations.ValidationAttribute, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.IClientModelValidator { public virtual void AddValidation(Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientModelValidationContext context) => throw null; @@ -131,22 +121,19 @@ namespace Microsoft protected Microsoft.AspNetCore.Routing.RouteValueDictionary RouteData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.SkipStatusCodePagesAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class SkipStatusCodePagesAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IResourceFilter + public class SkipStatusCodePagesAttribute : System.Attribute, Microsoft.AspNetCore.Http.Metadata.ISkipStatusCodePagesMetadata, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IResourceFilter { public void OnResourceExecuted(Microsoft.AspNetCore.Mvc.Filters.ResourceExecutedContext context) => throw null; public void OnResourceExecuting(Microsoft.AspNetCore.Mvc.Filters.ResourceExecutingContext context) => throw null; public SkipStatusCodePagesAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.TempDataAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TempDataAttribute : System.Attribute { public string Key { get => throw null; set => throw null; } public TempDataAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ValidateAntiForgeryTokenAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateAntiForgeryTokenAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; @@ -155,7 +142,6 @@ namespace Microsoft public ValidateAntiForgeryTokenAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponent` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ViewComponent { public Microsoft.AspNetCore.Mvc.ViewComponents.ContentViewComponentResult Content(string content) => throw null; @@ -179,14 +165,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine ViewEngine { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponentAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentAttribute : System.Attribute { public string Name { get => throw null; set => throw null; } public ViewComponentAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponentResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public object Arguments { get => throw null; set => throw null; } @@ -201,14 +185,12 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewDataAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataAttribute : System.Attribute { public string Key { get => throw null; set => throw null; } public ViewDataAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewResult : Microsoft.AspNetCore.Mvc.ActionResult, Microsoft.AspNetCore.Mvc.IActionResult, Microsoft.AspNetCore.Mvc.Infrastructure.IStatusCodeActionResult { public string ContentType { get => throw null; set => throw null; } @@ -224,7 +206,6 @@ namespace Microsoft namespace Diagnostics { - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterViewComponentEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterViewComponentEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -237,7 +218,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.IViewComponentResult ViewComponentResult { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.AfterViewEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AfterViewEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public AfterViewEventData(Microsoft.AspNetCore.Mvc.ViewEngines.IView view, Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext) => throw null; @@ -248,7 +228,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeViewComponentEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeViewComponentEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -260,7 +239,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext ViewComponentContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.BeforeViewEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BeforeViewEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public BeforeViewEventData(Microsoft.AspNetCore.Mvc.ViewEngines.IView view, Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext) => throw null; @@ -271,7 +249,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.Rendering.ViewContext ViewContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.ViewComponentAfterViewExecuteEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentAfterViewExecuteEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -283,7 +260,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext ViewComponentContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.ViewComponentBeforeViewExecuteEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentBeforeViewExecuteEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor ActionDescriptor { get => throw null; } @@ -295,7 +271,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext ViewComponentContext { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.ViewFoundEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewFoundEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -309,7 +284,6 @@ namespace Microsoft public string ViewName { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Diagnostics.ViewNotFoundEventData` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewNotFoundEventData : Microsoft.AspNetCore.Mvc.Diagnostics.EventData { public Microsoft.AspNetCore.Mvc.ActionContext ActionContext { get => throw null; } @@ -326,7 +300,6 @@ namespace Microsoft } namespace ModelBinding { - // Generated from `Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionaryExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelStateDictionaryExtensions { public static void AddModelError(this Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState, System.Linq.Expressions.Expression> expression, System.Exception exception, Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata metadata) => throw null; @@ -339,7 +312,6 @@ namespace Microsoft } namespace Rendering { - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.CheckBoxHiddenInputRenderMode` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum CheckBoxHiddenInputRenderMode : int { EndOfForm = 2, @@ -347,21 +319,24 @@ namespace Microsoft None = 0, } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.FormMethod` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public enum FormInputRenderMode : int + { + AlwaysUseCurrentCulture = 1, + DetectCultureFromInputType = 0, + } + public enum FormMethod : int { Get = 0, Post = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.Html5DateRenderingMode` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum Html5DateRenderingMode : int { CurrentCulture = 1, Rfc3339 = 0, } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperComponentExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperComponentExtensions { public static System.Threading.Tasks.Task RenderComponentAsync(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, System.Type componentType, Microsoft.AspNetCore.Mvc.Rendering.RenderMode renderMode, object parameters) => throw null; @@ -369,7 +344,6 @@ namespace Microsoft public static System.Threading.Tasks.Task RenderComponentAsync(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, Microsoft.AspNetCore.Mvc.Rendering.RenderMode renderMode, object parameters) where TComponent : Microsoft.AspNetCore.Components.IComponent => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperDisplayExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperDisplayExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent Display(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -390,14 +364,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent DisplayForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string templateName, string htmlFieldName, object additionalViewData) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperDisplayNameExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperDisplayNameExtensions { public static string DisplayNameFor(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper> htmlHelper, System.Linq.Expressions.Expression> expression) => throw null; public static string DisplayNameForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperEditorExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperEditorExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent Editor(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -418,7 +390,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent EditorForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string templateName, string htmlFieldName, object additionalViewData) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperFormExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperFormExtensions { public static Microsoft.AspNetCore.Mvc.Rendering.MvcForm BeginForm(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper) => throw null; @@ -442,7 +413,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Mvc.Rendering.MvcForm BeginRouteForm(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string routeName, object routeValues, Microsoft.AspNetCore.Mvc.Rendering.FormMethod method) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperInputExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperInputExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent CheckBox(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -474,7 +444,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent TextBoxFor(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, System.Linq.Expressions.Expression> expression, string format) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperLabelExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperLabelExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent Label(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -488,7 +457,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent LabelForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string labelText, object htmlAttributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperLinkExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperLinkExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent ActionLink(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper helper, string linkText, string actionName) => throw null; @@ -504,14 +472,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent RouteLink(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string linkText, string routeName, object routeValues, object htmlAttributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperNameExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperNameExtensions { public static string IdForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper) => throw null; public static string NameForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperPartialExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperPartialExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent Partial(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string partialViewName) => throw null; @@ -530,7 +496,6 @@ namespace Microsoft public static System.Threading.Tasks.Task RenderPartialAsync(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string partialViewName, object model) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperSelectExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperSelectExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent DropDownList(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -546,7 +511,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent ListBoxFor(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, System.Linq.Expressions.Expression> expression, System.Collections.Generic.IEnumerable selectList) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperValidationExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperValidationExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent ValidationMessage(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -569,7 +533,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Html.IHtmlContent ValidationSummary(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string message, string tag) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.HtmlHelperValueExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HtmlHelperValueExtensions { public static string Value(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string expression) => throw null; @@ -578,7 +541,6 @@ namespace Microsoft public static string ValueForModel(this Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper htmlHelper, string format) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlHelper { Microsoft.AspNetCore.Html.IHtmlContent ActionLink(string linkText, string actionName, string controllerName, string protocol, string hostname, string fragment, object routeValues, object htmlAttributes); @@ -625,7 +587,6 @@ namespace Microsoft Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper<>` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlHelper : Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper { Microsoft.AspNetCore.Html.IHtmlContent CheckBoxFor(System.Linq.Expressions.Expression> expression, object htmlAttributes); @@ -653,13 +614,11 @@ namespace Microsoft Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.IJsonHelper` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJsonHelper { Microsoft.AspNetCore.Html.IHtmlContent Serialize(object value); } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MultiSelectList : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public string DataGroupField { get => throw null; } @@ -676,7 +635,6 @@ namespace Microsoft public System.Collections.IEnumerable SelectedValues { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.MvcForm` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MvcForm : System.IDisposable { public void Dispose() => throw null; @@ -685,7 +643,6 @@ namespace Microsoft public MvcForm(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, System.Text.Encodings.Web.HtmlEncoder htmlEncoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.RenderMode` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RenderMode : int { Server = 2, @@ -695,7 +652,6 @@ namespace Microsoft WebAssemblyPrerendered = 5, } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.SelectList` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SelectList : Microsoft.AspNetCore.Mvc.Rendering.MultiSelectList { public SelectList(System.Collections.IEnumerable items) : base(default(System.Collections.IEnumerable)) => throw null; @@ -706,7 +662,6 @@ namespace Microsoft public object SelectedValue { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.SelectListGroup` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SelectListGroup { public bool Disabled { get => throw null; set => throw null; } @@ -714,7 +669,6 @@ namespace Microsoft public SelectListGroup() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SelectListItem { public bool Disabled { get => throw null; set => throw null; } @@ -728,7 +682,6 @@ namespace Microsoft public string Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.TagBuilder` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagBuilder : Microsoft.AspNetCore.Html.IHtmlContent { public void AddCssClass(string value) => throw null; @@ -752,7 +705,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.TagRenderMode` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum TagRenderMode : int { EndTag = 2, @@ -761,7 +713,6 @@ namespace Microsoft StartTag = 1, } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.ViewComponentHelperExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ViewComponentHelperExtensions { public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.Mvc.IViewComponentHelper helper, System.Type componentType) => throw null; @@ -770,7 +721,6 @@ namespace Microsoft public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.Mvc.IViewComponentHelper helper, object arguments) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.Rendering.ViewContext` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewContext : Microsoft.AspNetCore.Mvc.ActionContext { public Microsoft.AspNetCore.Mvc.Rendering.CheckBoxHiddenInputRenderMode CheckBoxHiddenInputRenderMode { get => throw null; set => throw null; } @@ -794,7 +744,6 @@ namespace Microsoft } namespace ViewComponents { - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ContentViewComponentResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ContentViewComponentResult : Microsoft.AspNetCore.Mvc.IViewComponentResult { public string Content { get => throw null; } @@ -803,14 +752,12 @@ namespace Microsoft public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentDescriptorCollectionProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultViewComponentDescriptorCollectionProvider : Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorCollectionProvider { public DefaultViewComponentDescriptorCollectionProvider(Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorProvider descriptorProvider) => throw null; public Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptorCollection ViewComponents { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentDescriptorProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultViewComponentDescriptorProvider : Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorProvider { public DefaultViewComponentDescriptorProvider(Microsoft.AspNetCore.Mvc.ApplicationParts.ApplicationPartManager partManager) => throw null; @@ -818,7 +765,6 @@ namespace Microsoft public virtual System.Collections.Generic.IEnumerable GetViewComponents() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentFactory` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultViewComponentFactory : Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentFactory { public object CreateViewComponent(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context) => throw null; @@ -827,7 +773,6 @@ namespace Microsoft public System.Threading.Tasks.ValueTask ReleaseViewComponentAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context, object component) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentHelper` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultViewComponentHelper : Microsoft.AspNetCore.Mvc.IViewComponentHelper, Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware { public void Contextualize(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext) => throw null; @@ -836,14 +781,12 @@ namespace Microsoft public System.Threading.Tasks.Task InvokeAsync(string name, object arguments) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.DefaultViewComponentSelector` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultViewComponentSelector : Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentSelector { public DefaultViewComponentSelector(Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorCollectionProvider descriptorProvider) => throw null; public Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptor SelectComponent(string componentName) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.HtmlContentViewComponentResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlContentViewComponentResult : Microsoft.AspNetCore.Mvc.IViewComponentResult { public Microsoft.AspNetCore.Html.IHtmlContent EncodedContent { get => throw null; } @@ -852,7 +795,6 @@ namespace Microsoft public HtmlContentViewComponentResult(Microsoft.AspNetCore.Html.IHtmlContent encodedContent) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentActivator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentActivator { object Create(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); @@ -860,19 +802,16 @@ namespace Microsoft System.Threading.Tasks.ValueTask ReleaseAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context, object viewComponent) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorCollectionProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentDescriptorCollectionProvider { Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptorCollection ViewComponents { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentDescriptorProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentDescriptorProvider { System.Collections.Generic.IEnumerable GetViewComponents(); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentFactory` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentFactory { object CreateViewComponent(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); @@ -880,25 +819,21 @@ namespace Microsoft System.Threading.Tasks.ValueTask ReleaseViewComponentAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context, object component) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentInvoker` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentInvoker { System.Threading.Tasks.Task InvokeAsync(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentInvokerFactory` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentInvokerFactory { Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentInvoker CreateInstance(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentSelector` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewComponentSelector { Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptor SelectComponent(string componentName); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ServiceBasedViewComponentActivator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceBasedViewComponentActivator : Microsoft.AspNetCore.Mvc.ViewComponents.IViewComponentActivator { public object Create(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context) => throw null; @@ -906,7 +841,6 @@ namespace Microsoft public ServiceBasedViewComponentActivator() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentContext { public System.Collections.Generic.IDictionary Arguments { get => throw null; set => throw null; } @@ -920,13 +854,11 @@ namespace Microsoft public System.IO.TextWriter Writer { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContextAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentContextAttribute : System.Attribute { public ViewComponentContextAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentConventions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ViewComponentConventions { public static string GetComponentFullName(System.Reflection.TypeInfo componentType) => throw null; @@ -935,7 +867,6 @@ namespace Microsoft public static string ViewComponentSuffix; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptor` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentDescriptor { public string DisplayName { get => throw null; set => throw null; } @@ -948,7 +879,6 @@ namespace Microsoft public ViewComponentDescriptor() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentDescriptorCollection` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentDescriptorCollection { public System.Collections.Generic.IReadOnlyList Items { get => throw null; } @@ -956,21 +886,18 @@ namespace Microsoft public ViewComponentDescriptorCollection(System.Collections.Generic.IEnumerable items, int version) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentFeature` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentFeature { public ViewComponentFeature() => throw null; public System.Collections.Generic.IList ViewComponents { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentFeatureProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentFeatureProvider : Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider, Microsoft.AspNetCore.Mvc.ApplicationParts.IApplicationFeatureProvider { public void PopulateFeature(System.Collections.Generic.IEnumerable parts, Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentFeature feature) => throw null; public ViewComponentFeatureProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewComponents.ViewViewComponentResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewViewComponentResult : Microsoft.AspNetCore.Mvc.IViewComponentResult { public void Execute(Microsoft.AspNetCore.Mvc.ViewComponents.ViewComponentContext context) => throw null; @@ -985,7 +912,6 @@ namespace Microsoft } namespace ViewEngines { - // Generated from `Microsoft.AspNetCore.Mvc.ViewEngines.CompositeViewEngine` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeViewEngine : Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine, Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine { public CompositeViewEngine(Microsoft.Extensions.Options.IOptions optionsAccessor) => throw null; @@ -994,27 +920,23 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList ViewEngines { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompositeViewEngine : Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine { System.Collections.Generic.IReadOnlyList ViewEngines { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewEngines.IView` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IView { string Path { get; } System.Threading.Tasks.Task RenderAsync(Microsoft.AspNetCore.Mvc.Rendering.ViewContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewEngines.IViewEngine` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewEngine { Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult FindView(Microsoft.AspNetCore.Mvc.ActionContext context, string viewName, bool isMainPage); Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult GetView(string executingFilePath, string viewPath, bool isMainPage); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewEngineResult { public Microsoft.AspNetCore.Mvc.ViewEngines.ViewEngineResult EnsureSuccessful(System.Collections.Generic.IEnumerable originalLocations) => throw null; @@ -1029,16 +951,13 @@ namespace Microsoft } namespace ViewFeatures { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.AntiforgeryExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class AntiforgeryExtensions { public static Microsoft.AspNetCore.Html.IHtmlContent GetHtml(this Microsoft.AspNetCore.Antiforgery.IAntiforgery antiforgery, Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.AttributeDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AttributeDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.AttributeDictionary+Enumerator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -1073,7 +992,6 @@ namespace Microsoft System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.CookieTempDataProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieTempDataProvider : Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataProvider { public static string CookieName; @@ -1082,7 +1000,6 @@ namespace Microsoft public void SaveTempData(Microsoft.AspNetCore.Http.HttpContext context, System.Collections.Generic.IDictionary values) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGenerator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultHtmlGenerator : Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator { protected virtual void AddMaxLengthAttribute(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary viewData, Microsoft.AspNetCore.Mvc.Rendering.TagBuilder tagBuilder, Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer modelExplorer, string expression) => throw null; @@ -1120,21 +1037,18 @@ namespace Microsoft public string IdAttributeDotReplacement { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultHtmlGeneratorExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DefaultHtmlGeneratorExtensions { public static Microsoft.AspNetCore.Mvc.Rendering.TagBuilder GenerateForm(this Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator generator, Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, string actionName, string controllerName, string fragment, object routeValues, string method, object htmlAttributes) => throw null; public static Microsoft.AspNetCore.Mvc.Rendering.TagBuilder GenerateRouteForm(this Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator generator, Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, string routeName, object routeValues, string fragment, string method, object htmlAttributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.DefaultValidationHtmlAttributeProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultValidationHtmlAttributeProvider : Microsoft.AspNetCore.Mvc.ViewFeatures.ValidationHtmlAttributeProvider { public override void AddValidationAttributes(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer modelExplorer, System.Collections.Generic.IDictionary attributes) => throw null; public DefaultValidationHtmlAttributeProvider(Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider metadataProvider, Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ClientValidatorCache clientValidatorCache) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.FormContext` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormContext { public bool CanRenderAtEndOfForm { get => throw null; set => throw null; } @@ -1148,7 +1062,6 @@ namespace Microsoft public void RenderedField(string fieldName, bool value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlHelper : Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper, Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware { public Microsoft.AspNetCore.Html.IHtmlContent ActionLink(string linkText, string actionName, string controllerName, string protocol, string hostname, string fragment, object routeValues, object htmlAttributes) => throw null; @@ -1229,7 +1142,6 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper<>` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlHelper : Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelper, Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper, Microsoft.AspNetCore.Mvc.Rendering.IHtmlHelper { public Microsoft.AspNetCore.Html.IHtmlContent CheckBoxFor(System.Linq.Expressions.Expression> expression, object htmlAttributes) => throw null; @@ -1257,11 +1169,11 @@ namespace Microsoft public Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary ViewData { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.HtmlHelperOptions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlHelperOptions { public Microsoft.AspNetCore.Mvc.Rendering.CheckBoxHiddenInputRenderMode CheckBoxHiddenInputRenderMode { get => throw null; set => throw null; } public bool ClientValidationEnabled { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Mvc.Rendering.FormInputRenderMode FormInputRenderMode { get => throw null; set => throw null; } public Microsoft.AspNetCore.Mvc.Rendering.Html5DateRenderingMode Html5DateRenderingMode { get => throw null; set => throw null; } public HtmlHelperOptions() => throw null; public string IdAttributeDotReplacement { get => throw null; set => throw null; } @@ -1269,18 +1181,15 @@ namespace Microsoft public string ValidationSummaryMessageElement { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IAntiforgeryPolicy` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IAntiforgeryPolicy : Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata { } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IFileVersionProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFileVersionProvider { string AddFileVersionToPath(Microsoft.AspNetCore.Http.PathString requestPathBase, string path); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IHtmlGenerator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHtmlGenerator { string Encode(object value); @@ -1310,13 +1219,11 @@ namespace Microsoft string IdAttributeDotReplacement { get; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IModelExpressionProvider { Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression CreateModelExpression(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary viewData, System.Linq.Expressions.Expression> expression); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITempDataDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { void Keep(); @@ -1326,26 +1233,22 @@ namespace Microsoft void Save(); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITempDataDictionaryFactory { Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary GetTempData(Microsoft.AspNetCore.Http.HttpContext context); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITempDataProvider { System.Collections.Generic.IDictionary LoadTempData(Microsoft.AspNetCore.Http.HttpContext context); void SaveTempData(Microsoft.AspNetCore.Http.HttpContext context, System.Collections.Generic.IDictionary values); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.IViewContextAware` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewContextAware { void Contextualize(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.InputType` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum InputType : int { CheckBox = 0, @@ -1355,7 +1258,6 @@ namespace Microsoft Text = 4, } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelExplorer { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer Container { get => throw null; } @@ -1376,13 +1278,11 @@ namespace Microsoft public System.Collections.Generic.IEnumerable Properties { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorerExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelExplorerExtensions { public static string GetSimpleDisplayText(this Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer modelExplorer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelExpression { public Microsoft.AspNetCore.Mvc.ModelBinding.ModelMetadata Metadata { get => throw null; } @@ -1392,7 +1292,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpressionProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ModelExpressionProvider : Microsoft.AspNetCore.Mvc.ViewFeatures.IModelExpressionProvider { public Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExpression CreateModelExpression(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary viewData, System.Linq.Expressions.Expression> expression) => throw null; @@ -1401,13 +1300,11 @@ namespace Microsoft public ModelExpressionProvider(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ModelMetadataProviderExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ModelMetadataProviderExtensions { public static Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer GetModelExplorerForType(this Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider provider, System.Type modelType, object model) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.PartialViewResultExecutor` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PartialViewResultExecutor : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext actionContext, Microsoft.AspNetCore.Mvc.ViewEngines.IView view, Microsoft.AspNetCore.Mvc.PartialViewResult viewResult) => throw null; @@ -1417,7 +1314,6 @@ namespace Microsoft public PartialViewResultExecutor(Microsoft.Extensions.Options.IOptions viewOptions, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory writerFactory, Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine viewEngine, Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory tempDataFactory, System.Diagnostics.DiagnosticListener diagnosticListener, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider) : base(default(Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory), default(Microsoft.AspNetCore.Mvc.ViewEngines.ICompositeViewEngine), default(System.Diagnostics.DiagnosticListener)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.SaveTempDataAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SaveTempDataAttribute : System.Attribute, Microsoft.AspNetCore.Mvc.Filters.IFilterFactory, Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata, Microsoft.AspNetCore.Mvc.Filters.IOrderedFilter { public Microsoft.AspNetCore.Mvc.Filters.IFilterMetadata CreateInstance(System.IServiceProvider serviceProvider) => throw null; @@ -1426,7 +1322,6 @@ namespace Microsoft public SaveTempDataAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.SessionStateTempDataProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SessionStateTempDataProvider : Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataProvider { public virtual System.Collections.Generic.IDictionary LoadTempData(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -1434,14 +1329,12 @@ namespace Microsoft public SessionStateTempDataProvider(Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.TempDataSerializer tempDataSerializer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.StringHtmlContent` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringHtmlContent : Microsoft.AspNetCore.Html.IHtmlContent { public StringHtmlContent(string input) => throw null; public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TempDataDictionary : Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary, System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair keyValuePair) => throw null; @@ -1469,14 +1362,12 @@ namespace Microsoft public System.Collections.Generic.ICollection Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.TempDataDictionaryFactory` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TempDataDictionaryFactory : Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory { public Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionary GetTempData(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public TempDataDictionaryFactory(Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataProvider provider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.TemplateInfo` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplateInfo { public bool AddVisited(object value) => throw null; @@ -1489,16 +1380,13 @@ namespace Microsoft public bool Visited(Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer modelExplorer) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.TryGetValueDelegate` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate bool TryGetValueDelegate(object dictionary, string key, out object value); - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.TryGetValueProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class TryGetValueProvider { public static Microsoft.AspNetCore.Mvc.ViewFeatures.TryGetValueDelegate CreateInstance(System.Type targetType) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ValidationHtmlAttributeProvider` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ValidationHtmlAttributeProvider { public virtual void AddAndTrackValidationAttributes(Microsoft.AspNetCore.Mvc.Rendering.ViewContext viewContext, Microsoft.AspNetCore.Mvc.ViewFeatures.ModelExplorer modelExplorer, string expression, System.Collections.Generic.IDictionary attributes) => throw null; @@ -1506,20 +1394,17 @@ namespace Microsoft protected ValidationHtmlAttributeProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewComponentResultExecutor` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewComponentResultExecutor : Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public virtual System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.ViewComponentResult result) => throw null; public ViewComponentResultExecutor(Microsoft.Extensions.Options.IOptions mvcHelperOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, System.Text.Encodings.Web.HtmlEncoder htmlEncoder, Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider, Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory tempDataDictionaryFactory, Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory writerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewContextAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewContextAttribute : System.Attribute { public ViewContextAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public void Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -1557,7 +1442,6 @@ namespace Microsoft protected ViewDataDictionary(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary source, object model, System.Type declaredModelType) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary<>` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataDictionary : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary { public TModel Model { get => throw null; set => throw null; } @@ -1567,13 +1451,11 @@ namespace Microsoft public ViewDataDictionary(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary source, object model) : base(default(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider)) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionaryAttribute` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataDictionaryAttribute : System.Attribute { public ViewDataDictionaryAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionaryControllerPropertyActivator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataDictionaryControllerPropertyActivator { public void Activate(Microsoft.AspNetCore.Mvc.ControllerContext actionContext, object controller) => throw null; @@ -1581,14 +1463,12 @@ namespace Microsoft public ViewDataDictionaryControllerPropertyActivator(Microsoft.AspNetCore.Mvc.ModelBinding.IModelMetadataProvider modelMetadataProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataEvaluator` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ViewDataEvaluator { public static Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataInfo Eval(Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataDictionary viewData, string expression) => throw null; public static Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataInfo Eval(object indexableObject, string expression) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewDataInfo` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewDataInfo { public object Container { get => throw null; } @@ -1599,7 +1479,6 @@ namespace Microsoft public ViewDataInfo(object container, object value) => throw null; } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewExecutor { public static string DefaultContentType; @@ -1615,7 +1494,6 @@ namespace Microsoft protected Microsoft.AspNetCore.Mvc.Infrastructure.IHttpResponseStreamWriterFactory WriterFactory { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ViewResultExecutor : Microsoft.AspNetCore.Mvc.ViewFeatures.ViewExecutor, Microsoft.AspNetCore.Mvc.Infrastructure.IActionResultExecutor { public System.Threading.Tasks.Task ExecuteAsync(Microsoft.AspNetCore.Mvc.ActionContext context, Microsoft.AspNetCore.Mvc.ViewResult result) => throw null; @@ -1626,7 +1504,6 @@ namespace Microsoft namespace Buffers { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers.IViewBufferScope` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IViewBufferScope { System.IO.TextWriter CreateWriter(System.IO.TextWriter writer); @@ -1634,7 +1511,6 @@ namespace Microsoft void ReturnSegment(Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers.ViewBufferValue[] segment); } - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.Buffers.ViewBufferValue` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct ViewBufferValue { public object Value { get => throw null; } @@ -1646,7 +1522,6 @@ namespace Microsoft } namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.Mvc.ViewFeatures.Infrastructure.TempDataSerializer` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TempDataSerializer { public virtual bool CanSerializeType(System.Type type) => throw null; @@ -1663,7 +1538,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcViewFeaturesMvcBuilderExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcViewFeaturesMvcBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddCookieTempDataProvider(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder) => throw null; @@ -1673,7 +1547,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddViewOptions(this Microsoft.Extensions.DependencyInjection.IMvcBuilder builder, System.Action setupAction) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.MvcViewFeaturesMvcCoreBuilderExtensions` in `Microsoft.AspNetCore.Mvc.ViewFeatures, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcViewFeaturesMvcCoreBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder AddCookieTempDataProvider(this Microsoft.Extensions.DependencyInjection.IMvcCoreBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.cs index 80bae914ef2..d45ae8e2a0f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Mvc.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Mvc, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MvcServiceCollectionExtensions` in `Microsoft.AspNetCore.Mvc, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MvcServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IMvcBuilder AddControllers(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.OutputCaching.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.OutputCaching.cs new file mode 100644 index 00000000000..404c5e60f22 --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.OutputCaching.cs @@ -0,0 +1,138 @@ +// This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.OutputCaching, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. + +namespace Microsoft +{ + namespace AspNetCore + { + namespace Builder + { + public static class OutputCacheApplicationBuilderExtensions + { + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseOutputCache(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; + } + + } + namespace OutputCaching + { + public class CacheVaryByRules + { + public string CacheKeyPrefix { get => throw null; set => throw null; } + public CacheVaryByRules() => throw null; + public Microsoft.Extensions.Primitives.StringValues HeaderNames { get => throw null; set => throw null; } + public Microsoft.Extensions.Primitives.StringValues QueryKeys { get => throw null; set => throw null; } + public Microsoft.Extensions.Primitives.StringValues RouteValueNames { get => throw null; set => throw null; } + public bool VaryByHost { get => throw null; set => throw null; } + public System.Collections.Generic.IDictionary VaryByValues { get => throw null; } + } + + public interface IOutputCacheFeature + { + Microsoft.AspNetCore.OutputCaching.OutputCacheContext Context { get; } + } + + public interface IOutputCachePolicy + { + System.Threading.Tasks.ValueTask CacheRequestAsync(Microsoft.AspNetCore.OutputCaching.OutputCacheContext context, System.Threading.CancellationToken cancellation); + System.Threading.Tasks.ValueTask ServeFromCacheAsync(Microsoft.AspNetCore.OutputCaching.OutputCacheContext context, System.Threading.CancellationToken cancellation); + System.Threading.Tasks.ValueTask ServeResponseAsync(Microsoft.AspNetCore.OutputCaching.OutputCacheContext context, System.Threading.CancellationToken cancellation); + } + + public interface IOutputCacheStore + { + System.Threading.Tasks.ValueTask EvictByTagAsync(string tag, System.Threading.CancellationToken cancellationToken); + System.Threading.Tasks.ValueTask GetAsync(string key, System.Threading.CancellationToken cancellationToken); + System.Threading.Tasks.ValueTask SetAsync(string key, System.Byte[] value, string[] tags, System.TimeSpan validFor, System.Threading.CancellationToken cancellationToken); + } + + public class OutputCacheAttribute : System.Attribute + { + public int Duration { get => throw null; set => throw null; } + public bool NoStore { get => throw null; set => throw null; } + public OutputCacheAttribute() => throw null; + public string PolicyName { get => throw null; set => throw null; } + public string[] VaryByHeaderNames { get => throw null; set => throw null; } + public string[] VaryByQueryKeys { get => throw null; set => throw null; } + public string[] VaryByRouteValueNames { get => throw null; set => throw null; } + } + + public class OutputCacheContext + { + public bool AllowCacheLookup { get => throw null; set => throw null; } + public bool AllowCacheStorage { get => throw null; set => throw null; } + public bool AllowLocking { get => throw null; set => throw null; } + public Microsoft.AspNetCore.OutputCaching.CacheVaryByRules CacheVaryByRules { get => throw null; } + public bool EnableOutputCaching { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; set => throw null; } + public OutputCacheContext() => throw null; + public System.TimeSpan? ResponseExpirationTimeSpan { get => throw null; set => throw null; } + public System.DateTimeOffset? ResponseTime { get => throw null; set => throw null; } + public System.Collections.Generic.HashSet Tags { get => throw null; } + } + + public class OutputCacheOptions + { + public void AddBasePolicy(System.Action build) => throw null; + public void AddBasePolicy(System.Action build, bool excludeDefaultPolicy) => throw null; + public void AddBasePolicy(Microsoft.AspNetCore.OutputCaching.IOutputCachePolicy policy) => throw null; + public void AddPolicy(string name, System.Action build) => throw null; + public void AddPolicy(string name, System.Action build, bool excludeDefaultPolicy) => throw null; + public void AddPolicy(string name, Microsoft.AspNetCore.OutputCaching.IOutputCachePolicy policy) => throw null; + public System.IServiceProvider ApplicationServices { get => throw null; set => throw null; } + public System.TimeSpan DefaultExpirationTimeSpan { get => throw null; set => throw null; } + public System.Int64 MaximumBodySize { get => throw null; set => throw null; } + public OutputCacheOptions() => throw null; + public System.Int64 SizeLimit { get => throw null; set => throw null; } + public bool UseCaseSensitivePaths { get => throw null; set => throw null; } + } + + public class OutputCachePolicyBuilder + { + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder AddPolicy(System.Type policyType) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder AddPolicy() where T : Microsoft.AspNetCore.OutputCaching.IOutputCachePolicy => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder Cache() => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder Expire(System.TimeSpan expiration) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder NoCache() => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetCacheKeyPrefix(System.Func> keyPrefix) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetCacheKeyPrefix(System.Func keyPrefix) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetCacheKeyPrefix(string keyPrefix) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetLocking(bool enabled) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByHeader(string[] headerNames) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByHeader(string headerName, params string[] headerNames) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByHost(bool enabled) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByQuery(string[] queryKeys) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByQuery(string queryKey, params string[] queryKeys) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByRouteValue(string[] routeValueNames) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder SetVaryByRouteValue(string routeValueName, params string[] routeValueNames) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder Tag(params string[] tags) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder VaryByValue(System.Func>> varyBy) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder VaryByValue(System.Func> varyBy) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder VaryByValue(string key, string value) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder With(System.Func> predicate) => throw null; + public Microsoft.AspNetCore.OutputCaching.OutputCachePolicyBuilder With(System.Func predicate) => throw null; + } + + } + } + namespace Extensions + { + namespace DependencyInjection + { + public static class OutputCacheConventionBuilderExtensions + { + public static TBuilder CacheOutput(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder CacheOutput(this TBuilder builder, System.Action policy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder CacheOutput(this TBuilder builder, System.Action policy, bool excludeDefaultPolicy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder CacheOutput(this TBuilder builder, Microsoft.AspNetCore.OutputCaching.IOutputCachePolicy policy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder CacheOutput(this TBuilder builder, string policyName) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + } + + public static class OutputCacheServiceCollectionExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddOutputCache(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddOutputCache(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RateLimiting.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RateLimiting.cs new file mode 100644 index 00000000000..0bb4d3b987e --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RateLimiting.cs @@ -0,0 +1,76 @@ +// This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.RateLimiting, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. + +namespace Microsoft +{ + namespace AspNetCore + { + namespace Builder + { + public static class RateLimiterApplicationBuilderExtensions + { + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRateLimiter(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.RateLimiting.RateLimiterOptions options) => throw null; + } + + public static class RateLimiterEndpointConventionBuilderExtensions + { + public static TBuilder DisableRateLimiting(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder RequireRateLimiting(this TBuilder builder, Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy policy) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder RequireRateLimiting(this TBuilder builder, string policyName) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + } + + public static class RateLimiterServiceCollectionExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRateLimiter(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; + } + + } + namespace RateLimiting + { + public class DisableRateLimitingAttribute : System.Attribute + { + public DisableRateLimitingAttribute() => throw null; + } + + public class EnableRateLimitingAttribute : System.Attribute + { + public EnableRateLimitingAttribute(string policyName) => throw null; + public string PolicyName { get => throw null; } + } + + public interface IRateLimiterPolicy + { + System.Threading.RateLimiting.RateLimitPartition GetPartition(Microsoft.AspNetCore.Http.HttpContext httpContext); + System.Func OnRejected { get; } + } + + public class OnRejectedContext + { + public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; set => throw null; } + public System.Threading.RateLimiting.RateLimitLease Lease { get => throw null; set => throw null; } + public OnRejectedContext() => throw null; + } + + public class RateLimiterOptions + { + public Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddPolicy(string policyName) where TPolicy : Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy => throw null; + public Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddPolicy(string policyName, System.Func> partitioner) => throw null; + public Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddPolicy(string policyName, Microsoft.AspNetCore.RateLimiting.IRateLimiterPolicy policy) => throw null; + public System.Threading.RateLimiting.PartitionedRateLimiter GlobalLimiter { get => throw null; set => throw null; } + public System.Func OnRejected { get => throw null; set => throw null; } + public RateLimiterOptions() => throw null; + public int RejectionStatusCode { get => throw null; set => throw null; } + } + + public static class RateLimiterOptionsExtensions + { + public static Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddConcurrencyLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions options, string policyName, System.Action configureOptions) => throw null; + public static Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddFixedWindowLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions options, string policyName, System.Action configureOptions) => throw null; + public static Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddSlidingWindowLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions options, string policyName, System.Action configureOptions) => throw null; + public static Microsoft.AspNetCore.RateLimiting.RateLimiterOptions AddTokenBucketLimiter(this Microsoft.AspNetCore.RateLimiting.RateLimiterOptions options, string policyName, System.Action configureOptions) => throw null; + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.Runtime.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.Runtime.cs index 567e86bb0a2..fddb3de9a74 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.Runtime.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.Runtime.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Razor.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Razor.Hosting.IRazorSourceChecksumMetadata` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRazorSourceChecksumMetadata { string Checksum { get; } @@ -16,7 +16,6 @@ namespace Microsoft string Identifier { get; } } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItem` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RazorCompiledItem { public abstract string Identifier { get; } @@ -26,7 +25,6 @@ namespace Microsoft public abstract System.Type Type { get; } } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorCompiledItemAttribute : System.Attribute { public string Identifier { get => throw null; } @@ -35,13 +33,11 @@ namespace Microsoft public System.Type Type { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemExtensions` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RazorCompiledItemExtensions { public static System.Collections.Generic.IReadOnlyList GetChecksumMetadata(this Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItem item) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemLoader` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorCompiledItemLoader { protected virtual Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItem CreateItem(Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemAttribute attribute) => throw null; @@ -50,7 +46,6 @@ namespace Microsoft public RazorCompiledItemLoader() => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorCompiledItemMetadataAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorCompiledItemMetadataAttribute : System.Attribute { public string Key { get => throw null; } @@ -58,14 +53,12 @@ namespace Microsoft public string Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorConfigurationNameAttribute : System.Attribute { public string ConfigurationName { get => throw null; } public RazorConfigurationNameAttribute(string configurationName) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorExtensionAssemblyNameAttribute : System.Attribute { public string AssemblyName { get => throw null; } @@ -73,14 +66,12 @@ namespace Microsoft public RazorExtensionAssemblyNameAttribute(string extensionName, string assemblyName) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorLanguageVersionAttribute : System.Attribute { public string LanguageVersion { get => throw null; } public RazorLanguageVersionAttribute(string languageVersion) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Hosting.RazorSourceChecksumAttribute` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RazorSourceChecksumAttribute : System.Attribute, Microsoft.AspNetCore.Razor.Hosting.IRazorSourceChecksumMetadata { public string Checksum { get => throw null; } @@ -94,7 +85,6 @@ namespace Microsoft { namespace TagHelpers { - // Generated from `Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperExecutionContext { public void Add(Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper tagHelper) => throw null; @@ -112,14 +102,12 @@ namespace Microsoft public System.Collections.Generic.IList TagHelpers { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperRunner` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperRunner { public System.Threading.Tasks.Task RunAsync(Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext executionContext) => throw null; public TagHelperRunner() => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperScopeManager` in `Microsoft.AspNetCore.Razor.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperScopeManager { public Microsoft.AspNetCore.Razor.Runtime.TagHelpers.TagHelperExecutionContext Begin(string tagName, Microsoft.AspNetCore.Razor.TagHelpers.TagMode tagMode, string uniqueId, System.Func executeChildContentAsync) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.cs index e8016912666..e0237fcaff4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Razor.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Razor, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace TagHelpers { - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.DefaultTagHelperContent` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultTagHelperContent : Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContent { public override Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContent Append(string unencoded) => throw null; @@ -26,7 +26,6 @@ namespace Microsoft public override void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNameAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlAttributeNameAttribute : System.Attribute { public string DictionaryAttributePrefix { get => throw null; set => throw null; } @@ -36,13 +35,11 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeNotBoundAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlAttributeNotBoundAttribute : System.Attribute { public HtmlAttributeNotBoundAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.HtmlAttributeValueStyle` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HtmlAttributeValueStyle : int { DoubleQuotes = 0, @@ -51,7 +48,6 @@ namespace Microsoft SingleQuotes = 1, } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.HtmlTargetElementAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlTargetElementAttribute : System.Attribute { public string Attributes { get => throw null; set => throw null; } @@ -63,12 +59,10 @@ namespace Microsoft public Microsoft.AspNetCore.Razor.TagHelpers.TagStructure TagStructure { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelperComponent { } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.ITagHelperComponent` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITagHelperComponent { void Init(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context); @@ -76,7 +70,6 @@ namespace Microsoft System.Threading.Tasks.Task ProcessAsync(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context, Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput output); } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.NullHtmlEncoder` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullHtmlEncoder : System.Text.Encodings.Web.HtmlEncoder { public static Microsoft.AspNetCore.Razor.TagHelpers.NullHtmlEncoder Default { get => throw null; } @@ -89,14 +82,12 @@ namespace Microsoft public override bool WillEncode(int unicodeScalar) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.OutputElementHintAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OutputElementHintAttribute : System.Attribute { public string OutputElement { get => throw null; } public OutputElementHintAttribute(string outputElement) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.ReadOnlyTagHelperAttributeList` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ReadOnlyTagHelperAttributeList : System.Collections.ObjectModel.ReadOnlyCollection { public bool ContainsName(string name) => throw null; @@ -109,14 +100,12 @@ namespace Microsoft public bool TryGetAttributes(string name, out System.Collections.Generic.IReadOnlyList attributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.RestrictChildrenAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RestrictChildrenAttribute : System.Attribute { public System.Collections.Generic.IEnumerable ChildTags { get => throw null; } public RestrictChildrenAttribute(string childTag, params string[] childTags) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelper` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TagHelper : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelper, Microsoft.AspNetCore.Razor.TagHelpers.ITagHelperComponent { public virtual void Init(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context) => throw null; @@ -126,7 +115,6 @@ namespace Microsoft protected TagHelper() => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperAttribute : Microsoft.AspNetCore.Html.IHtmlContent, Microsoft.AspNetCore.Html.IHtmlContentContainer { public void CopyTo(Microsoft.AspNetCore.Html.IHtmlContentBuilder destination) => throw null; @@ -143,7 +131,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttributeList` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperAttributeList : Microsoft.AspNetCore.Razor.TagHelpers.ReadOnlyTagHelperAttributeList, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { public void Add(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttribute attribute) => throw null; @@ -162,7 +149,6 @@ namespace Microsoft public TagHelperAttributeList(System.Collections.Generic.List attributes) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperComponent` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TagHelperComponent : Microsoft.AspNetCore.Razor.TagHelpers.ITagHelperComponent { public virtual void Init(Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext context) => throw null; @@ -172,7 +158,6 @@ namespace Microsoft protected TagHelperComponent() => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContent` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TagHelperContent : Microsoft.AspNetCore.Html.IHtmlContent, Microsoft.AspNetCore.Html.IHtmlContentBuilder, Microsoft.AspNetCore.Html.IHtmlContentContainer { public abstract Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContent Append(string unencoded); @@ -199,7 +184,6 @@ namespace Microsoft public abstract void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder); } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperContext` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperContext { public Microsoft.AspNetCore.Razor.TagHelpers.ReadOnlyTagHelperAttributeList AllAttributes { get => throw null; } @@ -212,7 +196,6 @@ namespace Microsoft public string UniqueId { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagHelperOutput` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TagHelperOutput : Microsoft.AspNetCore.Html.IHtmlContent, Microsoft.AspNetCore.Html.IHtmlContentContainer { public Microsoft.AspNetCore.Razor.TagHelpers.TagHelperAttributeList Attributes { get => throw null; } @@ -236,7 +219,6 @@ namespace Microsoft public void WriteTo(System.IO.TextWriter writer, System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagMode` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum TagMode : int { SelfClosing = 1, @@ -244,7 +226,6 @@ namespace Microsoft StartTagOnly = 2, } - // Generated from `Microsoft.AspNetCore.Razor.TagHelpers.TagStructure` in `Microsoft.AspNetCore.Razor, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum TagStructure : int { NormalOrSelfClosing = 1, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RequestDecompression.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RequestDecompression.cs new file mode 100644 index 00000000000..1d9dbeeaa9a --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.RequestDecompression.cs @@ -0,0 +1,48 @@ +// This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.RequestDecompression, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. + +namespace Microsoft +{ + namespace AspNetCore + { + namespace Builder + { + public static class RequestDecompressionBuilderExtensions + { + public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRequestDecompression(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) => throw null; + } + + } + namespace RequestDecompression + { + public interface IDecompressionProvider + { + System.IO.Stream GetDecompressionStream(System.IO.Stream stream); + } + + public interface IRequestDecompressionProvider + { + System.IO.Stream GetDecompressionStream(Microsoft.AspNetCore.Http.HttpContext context); + } + + public class RequestDecompressionOptions + { + public System.Collections.Generic.IDictionary DecompressionProviders { get => throw null; } + public RequestDecompressionOptions() => throw null; + } + + } + } + namespace Extensions + { + namespace DependencyInjection + { + public static class RequestDecompressionServiceExtensions + { + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRequestDecompression(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; + public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRequestDecompression(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configureOptions) => throw null; + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.Abstractions.cs index 07df657fcf0..3221fa5aba7 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.ResponseCaching.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace ResponseCaching { - // Generated from `Microsoft.AspNetCore.ResponseCaching.IResponseCachingFeature` in `Microsoft.AspNetCore.ResponseCaching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResponseCachingFeature { string[] VaryByQueryKeys { get; set; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.cs index 17108514dbb..90b2a5cc97d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCaching.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.ResponseCaching, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ResponseCachingExtensions` in `Microsoft.AspNetCore.ResponseCaching, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ResponseCachingExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseResponseCaching(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -15,21 +15,18 @@ namespace Microsoft } namespace ResponseCaching { - // Generated from `Microsoft.AspNetCore.ResponseCaching.ResponseCachingFeature` in `Microsoft.AspNetCore.ResponseCaching, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCachingFeature : Microsoft.AspNetCore.ResponseCaching.IResponseCachingFeature { public ResponseCachingFeature() => throw null; public string[] VaryByQueryKeys { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.ResponseCaching.ResponseCachingMiddleware` in `Microsoft.AspNetCore.ResponseCaching, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCachingMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; public ResponseCachingMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.ObjectPool.ObjectPoolProvider poolProvider) => throw null; } - // Generated from `Microsoft.AspNetCore.ResponseCaching.ResponseCachingOptions` in `Microsoft.AspNetCore.ResponseCaching, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCachingOptions { public System.Int64 MaximumBodySize { get => throw null; set => throw null; } @@ -44,7 +41,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ResponseCachingServicesExtensions` in `Microsoft.AspNetCore.ResponseCaching, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ResponseCachingServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddResponseCaching(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCompression.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCompression.cs index 27e9ddfb5a7..3e1947b46f2 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCompression.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.ResponseCompression.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.ResponseCompression, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,11 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ResponseCompressionBuilderExtensions` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ResponseCompressionBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseResponseCompression(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ResponseCompressionServicesExtensions` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ResponseCompressionServicesExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddResponseCompression(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -22,7 +21,6 @@ namespace Microsoft } namespace ResponseCompression { - // Generated from `Microsoft.AspNetCore.ResponseCompression.BrotliCompressionProvider` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BrotliCompressionProvider : Microsoft.AspNetCore.ResponseCompression.ICompressionProvider { public BrotliCompressionProvider(Microsoft.Extensions.Options.IOptions options) => throw null; @@ -31,7 +29,6 @@ namespace Microsoft public bool SupportsFlush { get => throw null; } } - // Generated from `Microsoft.AspNetCore.ResponseCompression.BrotliCompressionProviderOptions` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BrotliCompressionProviderOptions : Microsoft.Extensions.Options.IOptions { public BrotliCompressionProviderOptions() => throw null; @@ -39,7 +36,6 @@ namespace Microsoft Microsoft.AspNetCore.ResponseCompression.BrotliCompressionProviderOptions Microsoft.Extensions.Options.IOptions.Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.ResponseCompression.CompressionProviderCollection` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompressionProviderCollection : System.Collections.ObjectModel.Collection { public void Add(System.Type providerType) => throw null; @@ -47,7 +43,6 @@ namespace Microsoft public CompressionProviderCollection() => throw null; } - // Generated from `Microsoft.AspNetCore.ResponseCompression.GzipCompressionProvider` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class GzipCompressionProvider : Microsoft.AspNetCore.ResponseCompression.ICompressionProvider { public System.IO.Stream CreateStream(System.IO.Stream outputStream) => throw null; @@ -56,7 +51,6 @@ namespace Microsoft public bool SupportsFlush { get => throw null; } } - // Generated from `Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class GzipCompressionProviderOptions : Microsoft.Extensions.Options.IOptions { public GzipCompressionProviderOptions() => throw null; @@ -64,7 +58,6 @@ namespace Microsoft Microsoft.AspNetCore.ResponseCompression.GzipCompressionProviderOptions Microsoft.Extensions.Options.IOptions.Value { get => throw null; } } - // Generated from `Microsoft.AspNetCore.ResponseCompression.ICompressionProvider` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICompressionProvider { System.IO.Stream CreateStream(System.IO.Stream outputStream); @@ -72,7 +65,6 @@ namespace Microsoft bool SupportsFlush { get; } } - // Generated from `Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResponseCompressionProvider { bool CheckRequestAcceptsCompression(Microsoft.AspNetCore.Http.HttpContext context); @@ -80,21 +72,18 @@ namespace Microsoft bool ShouldCompressResponse(Microsoft.AspNetCore.Http.HttpContext context); } - // Generated from `Microsoft.AspNetCore.ResponseCompression.ResponseCompressionDefaults` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCompressionDefaults { public static System.Collections.Generic.IEnumerable MimeTypes; public ResponseCompressionDefaults() => throw null; } - // Generated from `Microsoft.AspNetCore.ResponseCompression.ResponseCompressionMiddleware` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCompressionMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public ResponseCompressionMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider provider) => throw null; } - // Generated from `Microsoft.AspNetCore.ResponseCompression.ResponseCompressionOptions` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCompressionOptions { public bool EnableForHttps { get => throw null; set => throw null; } @@ -104,7 +93,6 @@ namespace Microsoft public ResponseCompressionOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.ResponseCompression.ResponseCompressionProvider` in `Microsoft.AspNetCore.ResponseCompression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResponseCompressionProvider : Microsoft.AspNetCore.ResponseCompression.IResponseCompressionProvider { public bool CheckRequestAcceptsCompression(Microsoft.AspNetCore.Http.HttpContext context) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Rewrite.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Rewrite.cs index 65ce3962a0d..d5e6f4d527f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Rewrite.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Rewrite.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Rewrite, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.RewriteBuilderExtensions` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RewriteBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRewriter(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -16,27 +16,23 @@ namespace Microsoft } namespace Rewrite { - // Generated from `Microsoft.AspNetCore.Rewrite.ApacheModRewriteOptionsExtensions` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ApacheModRewriteOptionsExtensions { public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddApacheModRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, Microsoft.Extensions.FileProviders.IFileProvider fileProvider, string filePath) => throw null; public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddApacheModRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, System.IO.TextReader reader) => throw null; } - // Generated from `Microsoft.AspNetCore.Rewrite.IISUrlRewriteOptionsExtensions` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class IISUrlRewriteOptionsExtensions { public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, Microsoft.Extensions.FileProviders.IFileProvider fileProvider, string filePath, bool alwaysUseManagedServerVariables = default(bool)) => throw null; public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddIISUrlRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, System.IO.TextReader reader, bool alwaysUseManagedServerVariables = default(bool)) => throw null; } - // Generated from `Microsoft.AspNetCore.Rewrite.IRule` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRule { void ApplyRule(Microsoft.AspNetCore.Rewrite.RewriteContext context); } - // Generated from `Microsoft.AspNetCore.Rewrite.RewriteContext` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RewriteContext { public Microsoft.AspNetCore.Http.HttpContext HttpContext { get => throw null; set => throw null; } @@ -46,14 +42,12 @@ namespace Microsoft public Microsoft.Extensions.FileProviders.IFileProvider StaticFileProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Rewrite.RewriteMiddleware` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RewriteMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public RewriteMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Rewrite.RewriteOptions` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RewriteOptions { public RewriteOptions() => throw null; @@ -61,7 +55,6 @@ namespace Microsoft public Microsoft.Extensions.FileProviders.IFileProvider StaticFileProvider { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Rewrite.RewriteOptionsExtensions` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RewriteOptionsExtensions { public static Microsoft.AspNetCore.Rewrite.RewriteOptions Add(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, System.Action applyRule) => throw null; @@ -87,7 +80,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Rewrite.RewriteOptions AddRewrite(this Microsoft.AspNetCore.Rewrite.RewriteOptions options, string regex, string replacement, bool skipRemainingRules) => throw null; } - // Generated from `Microsoft.AspNetCore.Rewrite.RuleResult` in `Microsoft.AspNetCore.Rewrite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RuleResult : int { ContinueRules = 0, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.Abstractions.cs index ebe4f26ac82..55aaed4c900 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Routing.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,43 +7,36 @@ namespace Microsoft { namespace Routing { - // Generated from `Microsoft.AspNetCore.Routing.IOutboundParameterTransformer` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOutboundParameterTransformer : Microsoft.AspNetCore.Routing.IParameterPolicy { string TransformOutbound(object value); } - // Generated from `Microsoft.AspNetCore.Routing.IParameterPolicy` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IParameterPolicy { } - // Generated from `Microsoft.AspNetCore.Routing.IRouteConstraint` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy { bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection); } - // Generated from `Microsoft.AspNetCore.Routing.IRouteHandler` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteHandler { Microsoft.AspNetCore.Http.RequestDelegate GetRequestHandler(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteData routeData); } - // Generated from `Microsoft.AspNetCore.Routing.IRouter` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouter { Microsoft.AspNetCore.Routing.VirtualPathData GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext context); System.Threading.Tasks.Task RouteAsync(Microsoft.AspNetCore.Routing.RouteContext context); } - // Generated from `Microsoft.AspNetCore.Routing.IRoutingFeature` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRoutingFeature { Microsoft.AspNetCore.Routing.RouteData RouteData { get; set; } } - // Generated from `Microsoft.AspNetCore.Routing.LinkGenerator` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class LinkGenerator { public abstract string GetPathByAddress(Microsoft.AspNetCore.Http.HttpContext httpContext, TAddress address, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)); @@ -52,7 +46,6 @@ namespace Microsoft protected LinkGenerator() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.LinkOptions` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LinkOptions { public bool? AppendTrailingSlash { get => throw null; set => throw null; } @@ -61,7 +54,6 @@ namespace Microsoft public bool? LowercaseUrls { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteContext` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteContext { public Microsoft.AspNetCore.Http.RequestDelegate Handler { get => throw null; set => throw null; } @@ -70,10 +62,8 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteData RouteData { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteData` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteData { - // Generated from `Microsoft.AspNetCore.Routing.RouteData+RouteDataSnapshot` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct RouteDataSnapshot { public void Restore() => throw null; @@ -91,21 +81,18 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteValueDictionary Values { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteDirection` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RouteDirection : int { IncomingRequest = 0, UrlGeneration = 1, } - // Generated from `Microsoft.AspNetCore.Routing.RoutingHttpContextExtensions` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutingHttpContextExtensions { public static Microsoft.AspNetCore.Routing.RouteData GetRouteData(this Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; public static object GetRouteValue(this Microsoft.AspNetCore.Http.HttpContext httpContext, string key) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.VirtualPathContext` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class VirtualPathContext { public Microsoft.AspNetCore.Routing.RouteValueDictionary AmbientValues { get => throw null; } @@ -116,7 +103,6 @@ namespace Microsoft public VirtualPathContext(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValueDictionary ambientValues, Microsoft.AspNetCore.Routing.RouteValueDictionary values, string routeName) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.VirtualPathData` in `Microsoft.AspNetCore.Routing.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class VirtualPathData { public Microsoft.AspNetCore.Routing.RouteValueDictionary DataTokens { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.cs index f0d38400461..4122a512cec 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Routing.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Routing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Map(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern, System.Delegate handler) => throw null; @@ -19,22 +19,24 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Delegate handler) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Delegate handler) => throw null; public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapGet(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; + public static Microsoft.AspNetCore.Routing.RouteGroupBuilder MapGroup(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, Microsoft.AspNetCore.Routing.Patterns.RoutePattern prefix) => throw null; + public static Microsoft.AspNetCore.Routing.RouteGroupBuilder MapGroup(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string prefix) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Collections.Generic.IEnumerable httpMethods, System.Delegate handler) => throw null; public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapMethods(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Collections.Generic.IEnumerable httpMethods, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; + public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapPatch(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Delegate handler) => throw null; + public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPatch(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Delegate handler) => throw null; public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPost(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Delegate handler) => throw null; public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapPut(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.EndpointRoutingApplicationBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EndpointRoutingApplicationBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseEndpoints(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, System.Action configure) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRouting(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.FallbackEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class FallbackEndpointRouteBuilderExtensions { public static string DefaultPattern; @@ -42,7 +44,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallback(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.MapRouteRouteBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MapRouteRouteBuilderExtensions { public static Microsoft.AspNetCore.Routing.IRouteBuilder MapRoute(this Microsoft.AspNetCore.Routing.IRouteBuilder routeBuilder, string name, string template) => throw null; @@ -51,28 +52,25 @@ namespace Microsoft public static Microsoft.AspNetCore.Routing.IRouteBuilder MapRoute(this Microsoft.AspNetCore.Routing.IRouteBuilder routeBuilder, string name, string template, object defaults, object constraints, object dataTokens) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RouteHandlerBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteHandlerBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; public RouteHandlerBuilder(System.Collections.Generic.IEnumerable endpointConventionBuilders) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RouterMiddleware` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouterMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext httpContext) => throw null; public RouterMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.Routing.IRouter router) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RoutingBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutingBuilderExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRouter(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, System.Action action) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseRouter(this Microsoft.AspNetCore.Builder.IApplicationBuilder builder, Microsoft.AspNetCore.Routing.IRouter router) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.RoutingEndpointConventionBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutingEndpointConventionBuilderExtensions { public static TBuilder RequireHost(this TBuilder builder, params string[] hosts) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; @@ -86,7 +84,16 @@ namespace Microsoft } namespace Http { - // Generated from `Microsoft.AspNetCore.Http.OpenApiRouteHandlerBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public static class EndpointFilterExtensions + { + public static TBuilder AddEndpointFilter(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder where TFilterType : Microsoft.AspNetCore.Http.IEndpointFilter => throw null; + public static TBuilder AddEndpointFilter(this TBuilder builder, System.Func> routeHandlerFilter) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder AddEndpointFilter(this TBuilder builder, Microsoft.AspNetCore.Http.IEndpointFilter filter) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static Microsoft.AspNetCore.Routing.RouteGroupBuilder AddEndpointFilter(this Microsoft.AspNetCore.Routing.RouteGroupBuilder builder) where TFilterType : Microsoft.AspNetCore.Http.IEndpointFilter => throw null; + public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder AddEndpointFilter(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder) where TFilterType : Microsoft.AspNetCore.Http.IEndpointFilter => throw null; + public static TBuilder AddEndpointFilterFactory(this TBuilder builder, System.Func filterFactory) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + } + public static class OpenApiRouteHandlerBuilderExtensions { public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, System.Type requestType, bool isOptional, string contentType, params string[] additionalContentTypes) => throw null; @@ -94,33 +101,36 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, bool isOptional, string contentType, params string[] additionalContentTypes) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Accepts(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, string contentType, params string[] additionalContentTypes) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder ExcludeFromDescription(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder) => throw null; + public static TBuilder ExcludeFromDescription(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Produces(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, int statusCode, System.Type responseType = default(System.Type), string contentType = default(string), params string[] additionalContentTypes) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder Produces(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, int statusCode = default(int), string contentType = default(string), params string[] additionalContentTypes) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder ProducesProblem(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, int statusCode, string contentType = default(string)) => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder ProducesValidationProblem(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, int statusCode = default(int), string contentType = default(string)) => throw null; + public static TBuilder WithDescription(this TBuilder builder, string description) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; + public static TBuilder WithSummary(this TBuilder builder, string summary) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; public static Microsoft.AspNetCore.Builder.RouteHandlerBuilder WithTags(this Microsoft.AspNetCore.Builder.RouteHandlerBuilder builder, params string[] tags) => throw null; + public static TBuilder WithTags(this TBuilder builder, params string[] tags) where TBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder => throw null; } } namespace Routing { - // Generated from `Microsoft.AspNetCore.Routing.CompositeEndpointDataSource` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public class CompositeEndpointDataSource : Microsoft.AspNetCore.Routing.EndpointDataSource + public class CompositeEndpointDataSource : Microsoft.AspNetCore.Routing.EndpointDataSource, System.IDisposable { public CompositeEndpointDataSource(System.Collections.Generic.IEnumerable endpointDataSources) => throw null; public System.Collections.Generic.IEnumerable DataSources { get => throw null; } + public void Dispose() => throw null; public override System.Collections.Generic.IReadOnlyList Endpoints { get => throw null; } public override Microsoft.Extensions.Primitives.IChangeToken GetChangeToken() => throw null; + public override System.Collections.Generic.IReadOnlyList GetGroupedEndpoints(Microsoft.AspNetCore.Routing.RouteGroupContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.DataTokensMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataTokensMetadata : Microsoft.AspNetCore.Routing.IDataTokensMetadata { public System.Collections.Generic.IReadOnlyDictionary DataTokens { get => throw null; } public DataTokensMetadata(System.Collections.Generic.IReadOnlyDictionary dataTokens) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.DefaultEndpointDataSource` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultEndpointDataSource : Microsoft.AspNetCore.Routing.EndpointDataSource { public DefaultEndpointDataSource(System.Collections.Generic.IEnumerable endpoints) => throw null; @@ -129,50 +139,44 @@ namespace Microsoft public override Microsoft.Extensions.Primitives.IChangeToken GetChangeToken() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.DefaultInlineConstraintResolver` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultInlineConstraintResolver : Microsoft.AspNetCore.Routing.IInlineConstraintResolver { public DefaultInlineConstraintResolver(Microsoft.Extensions.Options.IOptions routeOptions, System.IServiceProvider serviceProvider) => throw null; public virtual Microsoft.AspNetCore.Routing.IRouteConstraint ResolveConstraint(string inlineConstraint) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.EndpointDataSource` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class EndpointDataSource { protected EndpointDataSource() => throw null; public abstract System.Collections.Generic.IReadOnlyList Endpoints { get; } public abstract Microsoft.Extensions.Primitives.IChangeToken GetChangeToken(); + public virtual System.Collections.Generic.IReadOnlyList GetGroupedEndpoints(Microsoft.AspNetCore.Routing.RouteGroupContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.EndpointGroupNameAttribute` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointGroupNameAttribute : System.Attribute, Microsoft.AspNetCore.Routing.IEndpointGroupNameMetadata { public string EndpointGroupName { get => throw null; } public EndpointGroupNameAttribute(string endpointGroupName) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.EndpointNameAttribute` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointNameAttribute : System.Attribute, Microsoft.AspNetCore.Routing.IEndpointNameMetadata { public string EndpointName { get => throw null; } public EndpointNameAttribute(string endpointName) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.EndpointNameMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointNameMetadata : Microsoft.AspNetCore.Routing.IEndpointNameMetadata { public string EndpointName { get => throw null; } public EndpointNameMetadata(string endpointName) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExcludeFromDescriptionAttribute : System.Attribute, Microsoft.AspNetCore.Routing.IExcludeFromDescriptionMetadata { public bool ExcludeFromDescription { get => throw null; } public ExcludeFromDescriptionAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.HostAttribute` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostAttribute : System.Attribute, Microsoft.AspNetCore.Routing.IHostMetadata { public HostAttribute(params string[] hosts) => throw null; @@ -180,46 +184,39 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyList Hosts { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.HttpMethodMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodMetadata : Microsoft.AspNetCore.Routing.IHttpMethodMetadata { - public bool AcceptCorsPreflight { get => throw null; } + public bool AcceptCorsPreflight { get => throw null; set => throw null; } public HttpMethodMetadata(System.Collections.Generic.IEnumerable httpMethods) => throw null; public HttpMethodMetadata(System.Collections.Generic.IEnumerable httpMethods, bool acceptCorsPreflight) => throw null; public System.Collections.Generic.IReadOnlyList HttpMethods { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.IDataTokensMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDataTokensMetadata { System.Collections.Generic.IReadOnlyDictionary DataTokens { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IDynamicEndpointMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDynamicEndpointMetadata { bool IsDynamic { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IEndpointAddressScheme<>` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointAddressScheme { System.Collections.Generic.IEnumerable FindEndpoints(TAddress address); } - // Generated from `Microsoft.AspNetCore.Routing.IEndpointGroupNameMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointGroupNameMetadata { string EndpointGroupName { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IEndpointNameMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointNameMetadata { string EndpointName { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IEndpointRouteBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointRouteBuilder { Microsoft.AspNetCore.Builder.IApplicationBuilder CreateApplicationBuilder(); @@ -227,38 +224,32 @@ namespace Microsoft System.IServiceProvider ServiceProvider { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IExcludeFromDescriptionMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IExcludeFromDescriptionMetadata { bool ExcludeFromDescription { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IHostMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostMetadata { System.Collections.Generic.IReadOnlyList Hosts { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IHttpMethodMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpMethodMetadata { - bool AcceptCorsPreflight { get; } + bool AcceptCorsPreflight { get => throw null; set => throw null; } System.Collections.Generic.IReadOnlyList HttpMethods { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IInlineConstraintResolver` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IInlineConstraintResolver { Microsoft.AspNetCore.Routing.IRouteConstraint ResolveConstraint(string inlineConstraint); } - // Generated from `Microsoft.AspNetCore.Routing.INamedRouter` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface INamedRouter : Microsoft.AspNetCore.Routing.IRouter { string Name { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IRouteBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteBuilder { Microsoft.AspNetCore.Builder.IApplicationBuilder ApplicationBuilder { get; } @@ -268,68 +259,66 @@ namespace Microsoft System.IServiceProvider ServiceProvider { get; } } - // Generated from `Microsoft.AspNetCore.Routing.IRouteCollection` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteCollection : Microsoft.AspNetCore.Routing.IRouter { void Add(Microsoft.AspNetCore.Routing.IRouter router); } - // Generated from `Microsoft.AspNetCore.Routing.IRouteNameMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRouteNameMetadata { string RouteName { get; } } - // Generated from `Microsoft.AspNetCore.Routing.ISuppressLinkGenerationMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISuppressLinkGenerationMetadata { bool SuppressLinkGeneration { get; } } - // Generated from `Microsoft.AspNetCore.Routing.ISuppressMatchingMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISuppressMatchingMetadata { bool SuppressMatching { get; } } - // Generated from `Microsoft.AspNetCore.Routing.InlineRouteParameterParser` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class InlineRouteParameterParser { public static Microsoft.AspNetCore.Routing.Template.TemplatePart ParseRouteParameter(string routeParameter) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.LinkGeneratorEndpointNameAddressExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LinkGeneratorEndpointNameAddressExtensions { + public static string GetPathByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string endpointName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetPathByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string endpointName, object values, Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetPathByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string endpointName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetPathByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string endpointName, object values, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetUriByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string endpointName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), string scheme = default(string), Microsoft.AspNetCore.Http.HostString? host = default(Microsoft.AspNetCore.Http.HostString?), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetUriByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string endpointName, object values, string scheme = default(string), Microsoft.AspNetCore.Http.HostString? host = default(Microsoft.AspNetCore.Http.HostString?), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetUriByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string endpointName, Microsoft.AspNetCore.Routing.RouteValueDictionary values, string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetUriByName(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string endpointName, object values, string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.LinkGeneratorRouteValuesAddressExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LinkGeneratorRouteValuesAddressExtensions { + public static string GetPathByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string routeName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetPathByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string routeName, object values, Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetPathByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string routeName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetPathByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string routeName, object values, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetUriByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string routeName, Microsoft.AspNetCore.Routing.RouteValueDictionary values = default(Microsoft.AspNetCore.Routing.RouteValueDictionary), string scheme = default(string), Microsoft.AspNetCore.Http.HostString? host = default(Microsoft.AspNetCore.Http.HostString?), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetUriByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, Microsoft.AspNetCore.Http.HttpContext httpContext, string routeName, object values, string scheme = default(string), Microsoft.AspNetCore.Http.HostString? host = default(Microsoft.AspNetCore.Http.HostString?), Microsoft.AspNetCore.Http.PathString? pathBase = default(Microsoft.AspNetCore.Http.PathString?), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; + public static string GetUriByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string routeName, Microsoft.AspNetCore.Routing.RouteValueDictionary values, string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; public static string GetUriByRouteValues(this Microsoft.AspNetCore.Routing.LinkGenerator generator, string routeName, object values, string scheme, Microsoft.AspNetCore.Http.HostString host, Microsoft.AspNetCore.Http.PathString pathBase = default(Microsoft.AspNetCore.Http.PathString), Microsoft.AspNetCore.Http.FragmentString fragment = default(Microsoft.AspNetCore.Http.FragmentString), Microsoft.AspNetCore.Routing.LinkOptions options = default(Microsoft.AspNetCore.Routing.LinkOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.LinkParser` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class LinkParser { protected LinkParser() => throw null; public abstract Microsoft.AspNetCore.Routing.RouteValueDictionary ParsePathByAddress(TAddress address, Microsoft.AspNetCore.Http.PathString path); } - // Generated from `Microsoft.AspNetCore.Routing.LinkParserEndpointNameAddressExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LinkParserEndpointNameAddressExtensions { public static Microsoft.AspNetCore.Routing.RouteValueDictionary ParsePathByEndpointName(this Microsoft.AspNetCore.Routing.LinkParser parser, string endpointName, Microsoft.AspNetCore.Http.PathString path) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.MatcherPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class MatcherPolicy { protected static bool ContainsDynamicEndpoints(System.Collections.Generic.IReadOnlyList endpoints) => throw null; @@ -337,7 +326,6 @@ namespace Microsoft public abstract int Order { get; } } - // Generated from `Microsoft.AspNetCore.Routing.ParameterPolicyFactory` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ParameterPolicyFactory { public abstract Microsoft.AspNetCore.Routing.IParameterPolicy Create(Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPart parameter, Microsoft.AspNetCore.Routing.IParameterPolicy parameterPolicy); @@ -346,7 +334,6 @@ namespace Microsoft protected ParameterPolicyFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RequestDelegateRouteBuilderExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RequestDelegateRouteBuilderExtensions { public static Microsoft.AspNetCore.Routing.IRouteBuilder MapDelete(this Microsoft.AspNetCore.Routing.IRouteBuilder builder, string template, System.Func handler) => throw null; @@ -368,7 +355,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Routing.IRouteBuilder MapVerb(this Microsoft.AspNetCore.Routing.IRouteBuilder builder, string verb, string template, Microsoft.AspNetCore.Http.RequestDelegate handler) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Route` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Route : Microsoft.AspNetCore.Routing.RouteBase { protected override System.Threading.Tasks.Task OnRouteMatched(Microsoft.AspNetCore.Routing.RouteContext context) => throw null; @@ -379,7 +365,6 @@ namespace Microsoft public string RouteTemplate { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteBase` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RouteBase : Microsoft.AspNetCore.Routing.INamedRouter, Microsoft.AspNetCore.Routing.IRouter { protected virtual Microsoft.AspNetCore.Routing.IInlineConstraintResolver ConstraintResolver { get => throw null; set => throw null; } @@ -398,7 +383,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteBuilder : Microsoft.AspNetCore.Routing.IRouteBuilder { public Microsoft.AspNetCore.Builder.IApplicationBuilder ApplicationBuilder { get => throw null; } @@ -410,7 +394,6 @@ namespace Microsoft public System.IServiceProvider ServiceProvider { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteCollection` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteCollection : Microsoft.AspNetCore.Routing.IRouteCollection, Microsoft.AspNetCore.Routing.IRouter { public void Add(Microsoft.AspNetCore.Routing.IRouter router) => throw null; @@ -421,7 +404,6 @@ namespace Microsoft public RouteCollection() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteConstraintBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteConstraintBuilder { public void AddConstraint(string key, object value) => throw null; @@ -431,20 +413,17 @@ namespace Microsoft public void SetOptional(string key) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteConstraintMatcher` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RouteConstraintMatcher { public static bool Match(System.Collections.Generic.IDictionary constraints, Microsoft.AspNetCore.Routing.RouteValueDictionary routeValues, Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, Microsoft.AspNetCore.Routing.RouteDirection routeDirection, Microsoft.Extensions.Logging.ILogger logger) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteCreationException` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteCreationException : System.Exception { public RouteCreationException(string message) => throw null; public RouteCreationException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteEndpoint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteEndpoint : Microsoft.AspNetCore.Http.Endpoint { public int Order { get => throw null; } @@ -452,7 +431,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Patterns.RoutePattern RoutePattern { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteEndpointBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteEndpointBuilder : Microsoft.AspNetCore.Builder.EndpointBuilder { public override Microsoft.AspNetCore.Http.Endpoint Build() => throw null; @@ -461,7 +439,24 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Patterns.RoutePattern RoutePattern { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteHandler` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class RouteGroupBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder, Microsoft.AspNetCore.Routing.IEndpointRouteBuilder + { + void Microsoft.AspNetCore.Builder.IEndpointConventionBuilder.Add(System.Action convention) => throw null; + Microsoft.AspNetCore.Builder.IApplicationBuilder Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.CreateApplicationBuilder() => throw null; + System.Collections.Generic.ICollection Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.DataSources { get => throw null; } + void Microsoft.AspNetCore.Builder.IEndpointConventionBuilder.Finally(System.Action finalConvention) => throw null; + System.IServiceProvider Microsoft.AspNetCore.Routing.IEndpointRouteBuilder.ServiceProvider { get => throw null; } + } + + public class RouteGroupContext + { + public System.IServiceProvider ApplicationServices { get => throw null; set => throw null; } + public System.Collections.Generic.IReadOnlyList> Conventions { get => throw null; set => throw null; } + public System.Collections.Generic.IReadOnlyList> FinallyConventions { get => throw null; set => throw null; } + public Microsoft.AspNetCore.Routing.Patterns.RoutePattern Prefix { get => throw null; set => throw null; } + public RouteGroupContext() => throw null; + } + public class RouteHandler : Microsoft.AspNetCore.Routing.IRouteHandler, Microsoft.AspNetCore.Routing.IRouter { public Microsoft.AspNetCore.Http.RequestDelegate GetRequestHandler(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteData routeData) => throw null; @@ -470,21 +465,18 @@ namespace Microsoft public RouteHandler(Microsoft.AspNetCore.Http.RequestDelegate requestDelegate) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteHandlerOptions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteHandlerOptions { public RouteHandlerOptions() => throw null; public bool ThrowOnBadRequest { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteNameMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteNameMetadata : Microsoft.AspNetCore.Routing.IRouteNameMetadata { public string RouteName { get => throw null; } public RouteNameMetadata(string routeName) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteOptions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteOptions { public bool AppendTrailingSlash { get => throw null; set => throw null; } @@ -492,10 +484,11 @@ namespace Microsoft public bool LowercaseQueryStrings { get => throw null; set => throw null; } public bool LowercaseUrls { get => throw null; set => throw null; } public RouteOptions() => throw null; + public void SetParameterPolicy(string token, System.Type type) => throw null; + public void SetParameterPolicy(string token) where T : Microsoft.AspNetCore.Routing.IParameterPolicy => throw null; public bool SuppressCheckForUnhandledSecurityMetadata { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.RouteValueEqualityComparer` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValueEqualityComparer : System.Collections.Generic.IEqualityComparer { public static Microsoft.AspNetCore.Routing.RouteValueEqualityComparer Default; @@ -504,30 +497,27 @@ namespace Microsoft public RouteValueEqualityComparer() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RouteValuesAddress` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteValuesAddress { public Microsoft.AspNetCore.Routing.RouteValueDictionary AmbientValues { get => throw null; set => throw null; } public Microsoft.AspNetCore.Routing.RouteValueDictionary ExplicitValues { get => throw null; set => throw null; } public string RouteName { get => throw null; set => throw null; } public RouteValuesAddress() => throw null; + public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.RoutingFeature` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutingFeature : Microsoft.AspNetCore.Routing.IRoutingFeature { public Microsoft.AspNetCore.Routing.RouteData RouteData { get => throw null; set => throw null; } public RoutingFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.SuppressLinkGenerationMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SuppressLinkGenerationMetadata : Microsoft.AspNetCore.Routing.ISuppressLinkGenerationMetadata { public bool SuppressLinkGeneration { get => throw null; } public SuppressLinkGenerationMetadata() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.SuppressMatchingMetadata` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SuppressMatchingMetadata : Microsoft.AspNetCore.Routing.ISuppressMatchingMetadata { public bool SuppressMatching { get => throw null; } @@ -536,13 +526,11 @@ namespace Microsoft namespace Constraints { - // Generated from `Microsoft.AspNetCore.Routing.Constraints.AlphaRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AlphaRouteConstraint : Microsoft.AspNetCore.Routing.Constraints.RegexRouteConstraint { public AlphaRouteConstraint() : base(default(System.Text.RegularExpressions.Regex)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.BoolRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BoolRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public BoolRouteConstraint() => throw null; @@ -550,7 +538,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.CompositeRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public CompositeRouteConstraint(System.Collections.Generic.IEnumerable constraints) => throw null; @@ -559,7 +546,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.DateTimeRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DateTimeRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public DateTimeRouteConstraint() => throw null; @@ -567,7 +553,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.DecimalRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DecimalRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public DecimalRouteConstraint() => throw null; @@ -575,7 +560,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.DoubleRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DoubleRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public DoubleRouteConstraint() => throw null; @@ -583,7 +567,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.FileNameRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileNameRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public FileNameRouteConstraint() => throw null; @@ -591,7 +574,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.FloatRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FloatRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public FloatRouteConstraint() => throw null; @@ -599,7 +581,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.GuidRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class GuidRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public GuidRouteConstraint() => throw null; @@ -607,7 +588,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.HttpMethodRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint { public System.Collections.Generic.IList AllowedMethods { get => throw null; } @@ -615,7 +595,6 @@ namespace Microsoft public virtual bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.IntRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IntRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public IntRouteConstraint() => throw null; @@ -623,7 +602,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.LengthRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LengthRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public LengthRouteConstraint(int length) => throw null; @@ -634,7 +612,6 @@ namespace Microsoft public int MinLength { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.LongRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LongRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public LongRouteConstraint() => throw null; @@ -642,7 +619,6 @@ namespace Microsoft bool Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy.MatchesLiteral(string parameterName, string literal) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.MaxLengthRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MaxLengthRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -651,7 +627,6 @@ namespace Microsoft public MaxLengthRouteConstraint(int maxLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.MaxRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MaxRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -660,7 +635,6 @@ namespace Microsoft public MaxRouteConstraint(System.Int64 max) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.MinLengthRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MinLengthRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -669,7 +643,6 @@ namespace Microsoft public MinLengthRouteConstraint(int minLength) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.MinRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MinRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -678,7 +651,6 @@ namespace Microsoft public MinRouteConstraint(System.Int64 min) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.NonFileNameRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NonFileNameRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -686,7 +658,6 @@ namespace Microsoft public NonFileNameRouteConstraint() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.OptionalRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionalRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint { public Microsoft.AspNetCore.Routing.IRouteConstraint InnerConstraint { get => throw null; } @@ -694,7 +665,6 @@ namespace Microsoft public OptionalRouteConstraint(Microsoft.AspNetCore.Routing.IRouteConstraint innerConstraint) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.RangeRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RangeRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -704,13 +674,11 @@ namespace Microsoft public RangeRouteConstraint(System.Int64 min, System.Int64 max) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.RegexInlineRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RegexInlineRouteConstraint : Microsoft.AspNetCore.Routing.Constraints.RegexRouteConstraint { public RegexInlineRouteConstraint(string regexPattern) : base(default(System.Text.RegularExpressions.Regex)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.RegexRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RegexRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public System.Text.RegularExpressions.Regex Constraint { get => throw null; } @@ -720,14 +688,12 @@ namespace Microsoft public RegexRouteConstraint(string regexPattern) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.RequiredRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RequiredRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; public RequiredRouteConstraint() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Constraints.StringRouteConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringRouteConstraint : Microsoft.AspNetCore.Routing.IParameterPolicy, Microsoft.AspNetCore.Routing.IRouteConstraint, Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy { public bool Match(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.IRouter route, string routeKey, Microsoft.AspNetCore.Routing.RouteValueDictionary values, Microsoft.AspNetCore.Routing.RouteDirection routeDirection) => throw null; @@ -738,7 +704,6 @@ namespace Microsoft } namespace Internal { - // Generated from `Microsoft.AspNetCore.Routing.Internal.DfaGraphWriter` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DfaGraphWriter { public DfaGraphWriter(System.IServiceProvider services) => throw null; @@ -748,7 +713,6 @@ namespace Microsoft } namespace Matching { - // Generated from `Microsoft.AspNetCore.Routing.Matching.CandidateSet` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CandidateSet { public CandidateSet(Microsoft.AspNetCore.Http.Endpoint[] endpoints, Microsoft.AspNetCore.Routing.RouteValueDictionary[] values, int[] scores) => throw null; @@ -760,7 +724,6 @@ namespace Microsoft public void SetValidity(int index, bool value) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Matching.CandidateState` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct CandidateState { // Stub generator skipped constructor @@ -769,13 +732,11 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.RouteValueDictionary Values { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Matching.EndpointMetadataComparer` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointMetadataComparer : System.Collections.Generic.IComparer { int System.Collections.Generic.IComparer.Compare(Microsoft.AspNetCore.Http.Endpoint x, Microsoft.AspNetCore.Http.Endpoint y) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Matching.EndpointMetadataComparer<>` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class EndpointMetadataComparer : System.Collections.Generic.IComparer where TMetadata : class { public int Compare(Microsoft.AspNetCore.Http.Endpoint x, Microsoft.AspNetCore.Http.Endpoint y) => throw null; @@ -785,14 +746,12 @@ namespace Microsoft protected virtual TMetadata GetMetadata(Microsoft.AspNetCore.Http.Endpoint endpoint) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Matching.EndpointSelector` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class EndpointSelector { protected EndpointSelector() => throw null; public abstract System.Threading.Tasks.Task SelectAsync(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.Matching.CandidateSet candidates); } - // Generated from `Microsoft.AspNetCore.Routing.Matching.HostMatcherPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostMatcherPolicy : Microsoft.AspNetCore.Routing.MatcherPolicy, Microsoft.AspNetCore.Routing.Matching.IEndpointComparerPolicy, Microsoft.AspNetCore.Routing.Matching.IEndpointSelectorPolicy, Microsoft.AspNetCore.Routing.Matching.INodeBuilderPolicy { bool Microsoft.AspNetCore.Routing.Matching.IEndpointSelectorPolicy.AppliesToEndpoints(System.Collections.Generic.IReadOnlyList endpoints) => throw null; @@ -805,7 +764,6 @@ namespace Microsoft public override int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Matching.HttpMethodMatcherPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpMethodMatcherPolicy : Microsoft.AspNetCore.Routing.MatcherPolicy, Microsoft.AspNetCore.Routing.Matching.IEndpointComparerPolicy, Microsoft.AspNetCore.Routing.Matching.IEndpointSelectorPolicy, Microsoft.AspNetCore.Routing.Matching.INodeBuilderPolicy { bool Microsoft.AspNetCore.Routing.Matching.IEndpointSelectorPolicy.AppliesToEndpoints(System.Collections.Generic.IReadOnlyList endpoints) => throw null; @@ -818,20 +776,17 @@ namespace Microsoft public override int Order { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Matching.IEndpointComparerPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointComparerPolicy { System.Collections.Generic.IComparer Comparer { get; } } - // Generated from `Microsoft.AspNetCore.Routing.Matching.IEndpointSelectorPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IEndpointSelectorPolicy { bool AppliesToEndpoints(System.Collections.Generic.IReadOnlyList endpoints); System.Threading.Tasks.Task ApplyAsync(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.Matching.CandidateSet candidates); } - // Generated from `Microsoft.AspNetCore.Routing.Matching.INodeBuilderPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface INodeBuilderPolicy { bool AppliesToEndpoints(System.Collections.Generic.IReadOnlyList endpoints); @@ -839,20 +794,17 @@ namespace Microsoft System.Collections.Generic.IReadOnlyList GetEdges(System.Collections.Generic.IReadOnlyList endpoints); } - // Generated from `Microsoft.AspNetCore.Routing.Matching.IParameterLiteralNodeMatchingPolicy` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IParameterLiteralNodeMatchingPolicy : Microsoft.AspNetCore.Routing.IParameterPolicy { bool MatchesLiteral(string parameterName, string literal); } - // Generated from `Microsoft.AspNetCore.Routing.Matching.PolicyJumpTable` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PolicyJumpTable { public abstract int GetDestination(Microsoft.AspNetCore.Http.HttpContext httpContext); protected PolicyJumpTable() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Matching.PolicyJumpTableEdge` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PolicyJumpTableEdge { public int Destination { get => throw null; } @@ -861,7 +813,6 @@ namespace Microsoft public object State { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Matching.PolicyNodeEdge` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PolicyNodeEdge { public System.Collections.Generic.IReadOnlyList Endpoints { get => throw null; } @@ -873,7 +824,6 @@ namespace Microsoft } namespace Patterns { - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePattern` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePattern { public System.Collections.Generic.IReadOnlyDictionary Defaults { get => throw null; } @@ -888,7 +838,6 @@ namespace Microsoft public System.Collections.Generic.IReadOnlyDictionary RequiredValues { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternException` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternException : System.Exception { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -896,9 +845,9 @@ namespace Microsoft public RoutePatternException(string pattern, string message) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternFactory` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutePatternFactory { + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Combine(Microsoft.AspNetCore.Routing.Patterns.RoutePattern left, Microsoft.AspNetCore.Routing.Patterns.RoutePattern right) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference Constraint(Microsoft.AspNetCore.Routing.IRouteConstraint constraint) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference Constraint(object constraint) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference Constraint(string constraint) => throw null; @@ -911,13 +860,19 @@ namespace Microsoft public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference ParameterPolicy(Microsoft.AspNetCore.Routing.IParameterPolicy parameterPolicy) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference ParameterPolicy(string parameterPolicy) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Parse(string pattern) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Parse(string pattern, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Parse(string pattern, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies, Microsoft.AspNetCore.Routing.RouteValueDictionary requiredValues) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Parse(string pattern, object defaults, object parameterPolicies) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Parse(string pattern, object defaults, object parameterPolicies, object requiredValues) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(System.Collections.Generic.IEnumerable segments) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies, System.Collections.Generic.IEnumerable segments) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies, params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(object defaults, object parameterPolicies, System.Collections.Generic.IEnumerable segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(object defaults, object parameterPolicies, params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, System.Collections.Generic.IEnumerable segments) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies, System.Collections.Generic.IEnumerable segments) => throw null; + public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, Microsoft.AspNetCore.Routing.RouteValueDictionary defaults, Microsoft.AspNetCore.Routing.RouteValueDictionary parameterPolicies, params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, object defaults, object parameterPolicies, System.Collections.Generic.IEnumerable segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, object defaults, object parameterPolicies, params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; public static Microsoft.AspNetCore.Routing.Patterns.RoutePattern Pattern(string rawText, params Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment[] segments) => throw null; @@ -926,14 +881,12 @@ namespace Microsoft public static Microsoft.AspNetCore.Routing.Patterns.RoutePatternSeparatorPart SeparatorPart(string content) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternLiteralPart` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternLiteralPart : Microsoft.AspNetCore.Routing.Patterns.RoutePatternPart { public string Content { get => throw null; } internal RoutePatternLiteralPart(string content) : base(default(Microsoft.AspNetCore.Routing.Patterns.RoutePatternPartKind)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterKind` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RoutePatternParameterKind : int { CatchAll = 2, @@ -941,7 +894,6 @@ namespace Microsoft Standard = 0, } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPart` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternParameterPart : Microsoft.AspNetCore.Routing.Patterns.RoutePatternPart { public object Default { get => throw null; } @@ -955,14 +907,12 @@ namespace Microsoft internal RoutePatternParameterPart(string parameterName, object @default, Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterKind parameterKind, Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference[] parameterPolicies, bool encodeSlashes) : base(default(Microsoft.AspNetCore.Routing.Patterns.RoutePatternPartKind)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternParameterPolicyReference` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternParameterPolicyReference { public string Content { get => throw null; } public Microsoft.AspNetCore.Routing.IParameterPolicy ParameterPolicy { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternPart` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RoutePatternPart { public bool IsLiteral { get => throw null; } @@ -972,7 +922,6 @@ namespace Microsoft protected private RoutePatternPart(Microsoft.AspNetCore.Routing.Patterns.RoutePatternPartKind partKind) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternPartKind` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RoutePatternPartKind : int { Literal = 0, @@ -980,31 +929,28 @@ namespace Microsoft Separator = 2, } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternPathSegment { public bool IsSimple { get => throw null; } public System.Collections.Generic.IReadOnlyList Parts { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternSeparatorPart` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoutePatternSeparatorPart : Microsoft.AspNetCore.Routing.Patterns.RoutePatternPart { public string Content { get => throw null; } internal RoutePatternSeparatorPart(string content) : base(default(Microsoft.AspNetCore.Routing.Patterns.RoutePatternPartKind)) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Patterns.RoutePatternTransformer` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RoutePatternTransformer { protected RoutePatternTransformer() => throw null; + public virtual Microsoft.AspNetCore.Routing.Patterns.RoutePattern SubstituteRequiredValues(Microsoft.AspNetCore.Routing.Patterns.RoutePattern original, Microsoft.AspNetCore.Routing.RouteValueDictionary requiredValues) => throw null; public abstract Microsoft.AspNetCore.Routing.Patterns.RoutePattern SubstituteRequiredValues(Microsoft.AspNetCore.Routing.Patterns.RoutePattern original, object requiredValues); } } namespace Template { - // Generated from `Microsoft.AspNetCore.Routing.Template.InlineConstraint` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InlineConstraint { public string Constraint { get => throw null; } @@ -1012,14 +958,12 @@ namespace Microsoft public InlineConstraint(string constraint) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.RoutePrecedence` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutePrecedence { public static System.Decimal ComputeInbound(Microsoft.AspNetCore.Routing.Template.RouteTemplate template) => throw null; public static System.Decimal ComputeOutbound(Microsoft.AspNetCore.Routing.Template.RouteTemplate template) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.RouteTemplate` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RouteTemplate { public Microsoft.AspNetCore.Routing.Template.TemplatePart GetParameter(string name) => throw null; @@ -1032,7 +976,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Patterns.RoutePattern ToRoutePattern() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateBinder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplateBinder { public string BindValues(Microsoft.AspNetCore.Routing.RouteValueDictionary acceptedValues) => throw null; @@ -1041,7 +984,6 @@ namespace Microsoft public bool TryProcessConstraints(Microsoft.AspNetCore.Http.HttpContext httpContext, Microsoft.AspNetCore.Routing.RouteValueDictionary combinedValues, out string parameterName, out Microsoft.AspNetCore.Routing.IRouteConstraint constraint) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateBinderFactory` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TemplateBinderFactory { public abstract Microsoft.AspNetCore.Routing.Template.TemplateBinder Create(Microsoft.AspNetCore.Routing.Patterns.RoutePattern pattern); @@ -1049,7 +991,6 @@ namespace Microsoft protected TemplateBinderFactory() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateMatcher` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplateMatcher { public Microsoft.AspNetCore.Routing.RouteValueDictionary Defaults { get => throw null; } @@ -1058,13 +999,11 @@ namespace Microsoft public bool TryMatch(Microsoft.AspNetCore.Http.PathString path, Microsoft.AspNetCore.Routing.RouteValueDictionary values) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateParser` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class TemplateParser { public static Microsoft.AspNetCore.Routing.Template.RouteTemplate Parse(string routeTemplate) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplatePart` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplatePart { public static Microsoft.AspNetCore.Routing.Template.TemplatePart CreateLiteral(string text) => throw null; @@ -1083,7 +1022,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Patterns.RoutePatternPart ToRoutePatternPart() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateSegment` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplateSegment { public bool IsSimple { get => throw null; } @@ -1093,7 +1031,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment ToRoutePatternPathSegment() => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Template.TemplateValuesResult` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TemplateValuesResult { public Microsoft.AspNetCore.Routing.RouteValueDictionary AcceptedValues { get => throw null; set => throw null; } @@ -1104,7 +1041,6 @@ namespace Microsoft } namespace Tree { - // Generated from `Microsoft.AspNetCore.Routing.Tree.InboundMatch` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InboundMatch { public Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry Entry { get => throw null; set => throw null; } @@ -1112,7 +1048,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Template.TemplateMatcher TemplateMatcher { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.InboundRouteEntry` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InboundRouteEntry { public System.Collections.Generic.IDictionary Constraints { get => throw null; set => throw null; } @@ -1125,7 +1060,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Template.RouteTemplate RouteTemplate { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.OutboundMatch` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OutboundMatch { public Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry Entry { get => throw null; set => throw null; } @@ -1133,7 +1067,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Template.TemplateBinder TemplateBinder { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OutboundRouteEntry { public System.Collections.Generic.IDictionary Constraints { get => throw null; set => throw null; } @@ -1148,7 +1081,6 @@ namespace Microsoft public Microsoft.AspNetCore.Routing.Template.RouteTemplate RouteTemplate { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.TreeRouteBuilder` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TreeRouteBuilder { public Microsoft.AspNetCore.Routing.Tree.TreeRouter Build() => throw null; @@ -1160,7 +1092,6 @@ namespace Microsoft public System.Collections.Generic.IList OutboundEntries { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.TreeRouter` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TreeRouter : Microsoft.AspNetCore.Routing.IRouter { public Microsoft.AspNetCore.Routing.VirtualPathData GetVirtualPath(Microsoft.AspNetCore.Routing.VirtualPathContext context) => throw null; @@ -1169,7 +1100,6 @@ namespace Microsoft public int Version { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Routing.Tree.UrlMatchingNode` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlMatchingNode { public Microsoft.AspNetCore.Routing.Tree.UrlMatchingNode CatchAlls { get => throw null; set => throw null; } @@ -1183,7 +1113,6 @@ namespace Microsoft public UrlMatchingNode(int length) => throw null; } - // Generated from `Microsoft.AspNetCore.Routing.Tree.UrlMatchingTree` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlMatchingTree { public int Order { get => throw null; } @@ -1198,7 +1127,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.RoutingServiceCollectionExtensions` in `Microsoft.AspNetCore.Routing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class RoutingServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddRouting(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.HttpSys.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.HttpSys.cs index 027651684ad..d378a4e9985 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.HttpSys.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.HttpSys.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.HttpSys, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderHttpSysExtensions` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostBuilderHttpSysExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseHttpSys(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder) => throw null; @@ -18,7 +18,6 @@ namespace Microsoft { namespace HttpSys { - // Generated from `Microsoft.AspNetCore.Server.HttpSys.AuthenticationManager` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticationManager { public bool AllowAnonymous { get => throw null; set => throw null; } @@ -27,7 +26,6 @@ namespace Microsoft public Microsoft.AspNetCore.Server.HttpSys.AuthenticationSchemes Schemes { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.AuthenticationSchemes` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum AuthenticationSchemes : int { @@ -38,7 +36,6 @@ namespace Microsoft None = 0, } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.ClientCertificateMethod` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ClientCertificateMethod : int { AllowCertificate = 1, @@ -46,7 +43,6 @@ namespace Microsoft NoCertificate = 0, } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.DelegationRule` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DelegationRule : System.IDisposable { public void Dispose() => throw null; @@ -54,7 +50,6 @@ namespace Microsoft public string UrlPrefix { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.Http503VerbosityLevel` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum Http503VerbosityLevel : long { Basic = 0, @@ -62,19 +57,16 @@ namespace Microsoft Limited = 1, } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.HttpSysDefaults` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpSysDefaults { public const string AuthenticationScheme = default; } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.HttpSysException` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpSysException : System.ComponentModel.Win32Exception { public override int ErrorCode { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.HttpSysOptions` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpSysOptions { public bool AllowSynchronousIO { get => throw null; set => throw null; } @@ -96,26 +88,22 @@ namespace Microsoft public bool UseLatin1RequestHeaders { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.IHttpSysRequestDelegationFeature` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpSysRequestDelegationFeature { bool CanDelegate { get; } void DelegateRequest(Microsoft.AspNetCore.Server.HttpSys.DelegationRule destination); } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.IHttpSysRequestInfoFeature` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpSysRequestInfoFeature { System.Collections.Generic.IReadOnlyDictionary> RequestInfo { get; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.IServerDelegationFeature` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServerDelegationFeature { Microsoft.AspNetCore.Server.HttpSys.DelegationRule CreateDelegationRule(string queueName, string urlPrefix); } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.RequestQueueMode` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum RequestQueueMode : int { Attach = 1, @@ -123,7 +111,6 @@ namespace Microsoft CreateOrAttach = 2, } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.TimeoutManager` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TimeoutManager { public System.TimeSpan DrainEntityBody { get => throw null; set => throw null; } @@ -134,7 +121,6 @@ namespace Microsoft public System.TimeSpan RequestQueue { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.UrlPrefix` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlPrefix { public static Microsoft.AspNetCore.Server.HttpSys.UrlPrefix Create(string prefix) => throw null; @@ -152,7 +138,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Server.HttpSys.UrlPrefixCollection` in `Microsoft.AspNetCore.Server.HttpSys, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlPrefixCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public void Add(Microsoft.AspNetCore.Server.HttpSys.UrlPrefix item) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IIS.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IIS.cs index 111a52e61bb..55673f87da0 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IIS.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IIS.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.IIS, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.IISServerOptions` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISServerOptions { public bool AllowSynchronousIO { get => throw null; set => throw null; } @@ -20,7 +20,6 @@ namespace Microsoft } namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderIISExtensions` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class WebHostBuilderIISExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseIIS(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder) => throw null; @@ -31,34 +30,29 @@ namespace Microsoft { namespace IIS { - // Generated from `Microsoft.AspNetCore.Server.IIS.BadHttpRequestException` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { internal BadHttpRequestException(string message, int statusCode, Microsoft.AspNetCore.Server.IIS.RequestRejectionReason reason) : base(default(string)) => throw null; public int StatusCode { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.IIS.HttpContextExtensions` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpContextExtensions { public static string GetIISServerVariable(this Microsoft.AspNetCore.Http.HttpContext context, string variableName) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.IIS.IISServerDefaults` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISServerDefaults { public const string AuthenticationScheme = default; public IISServerDefaults() => throw null; } - // Generated from `Microsoft.AspNetCore.Server.IIS.RequestRejectionReason` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal enum RequestRejectionReason : int { } namespace Core { - // Generated from `Microsoft.AspNetCore.Server.IIS.Core.IISServerAuthenticationHandler` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISServerAuthenticationHandler : Microsoft.AspNetCore.Authentication.IAuthenticationHandler { public System.Threading.Tasks.Task AuthenticateAsync() => throw null; @@ -68,7 +62,6 @@ namespace Microsoft public System.Threading.Tasks.Task InitializeAsync(Microsoft.AspNetCore.Authentication.AuthenticationScheme scheme, Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.IIS.Core.ThrowingWasUpgradedWriteOnlyStream` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ThrowingWasUpgradedWriteOnlyStream : Microsoft.AspNetCore.Server.IIS.Core.WriteOnlyStream { public override void Flush() => throw null; @@ -79,7 +72,6 @@ namespace Microsoft public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.IIS.Core.WriteOnlyStream` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class WriteOnlyStream : System.IO.Stream { public override bool CanRead { get => throw null; } @@ -89,6 +81,7 @@ namespace Microsoft public override System.Int64 Position { get => throw null; set => throw null; } public override int Read(System.Byte[] buffer, int offset, int count) => throw null; public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null; public override int ReadTimeout { get => throw null; set => throw null; } public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null; public override void SetLength(System.Int64 value) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IISIntegration.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IISIntegration.cs index 9ae689326b1..6ce7423ade8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IISIntegration.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.IISIntegration.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.IISIntegration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.IISOptions` in `Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISOptions { public string AuthenticationDisplayName { get => throw null; set => throw null; } @@ -18,7 +18,6 @@ namespace Microsoft } namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderIISExtensions` in `Microsoft.AspNetCore.Server.IIS, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class WebHostBuilderIISExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseIISIntegration(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder) => throw null; @@ -29,7 +28,6 @@ namespace Microsoft { namespace IISIntegration { - // Generated from `Microsoft.AspNetCore.Server.IISIntegration.IISDefaults` in `Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISDefaults { public const string AuthenticationScheme = default; @@ -38,14 +36,12 @@ namespace Microsoft public const string Ntlm = default; } - // Generated from `Microsoft.AspNetCore.Server.IISIntegration.IISHostingStartup` in `Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISHostingStartup : Microsoft.AspNetCore.Hosting.IHostingStartup { public void Configure(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) => throw null; public IISHostingStartup() => throw null; } - // Generated from `Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware` in `Microsoft.AspNetCore.Server.IISIntegration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IISMiddleware { public IISMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.Extensions.Options.IOptions options, string pairingToken, Microsoft.AspNetCore.Authentication.IAuthenticationSchemeProvider authentication, Microsoft.Extensions.Hosting.IHostApplicationLifetime applicationLifetime) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Core.cs index e006bf8cff6..f2d392840f8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Core.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.Kestrel.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,21 +7,18 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.KestrelServerOptionsSystemdExtensions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class KestrelServerOptionsSystemdExtensions { public static Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions UseSystemd(this Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions options) => throw null; public static Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions UseSystemd(this Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions options, System.Action configure) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.ListenOptionsConnectionLoggingExtensions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ListenOptionsConnectionLoggingExtensions { public static Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions UseConnectionLogging(this Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions listenOptions) => throw null; public static Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions UseConnectionLogging(this Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions listenOptions, string loggerName) => throw null; } - // Generated from `Microsoft.AspNetCore.Hosting.ListenOptionsHttpsExtensions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ListenOptionsHttpsExtensions { public static Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions UseHttps(this Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions listenOptions) => throw null; @@ -45,7 +43,6 @@ namespace Microsoft { namespace Kestrel { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.EndpointConfiguration` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EndpointConfiguration { public Microsoft.Extensions.Configuration.IConfigurationSection ConfigSection { get => throw null; } @@ -54,7 +51,6 @@ namespace Microsoft public Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions ListenOptions { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KestrelConfigurationLoader { public Microsoft.AspNetCore.Server.Kestrel.KestrelConfigurationLoader AnyIPEndpoint(int port) => throw null; @@ -77,7 +73,6 @@ namespace Microsoft namespace Core { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BadHttpRequestException : Microsoft.AspNetCore.Http.BadHttpRequestException { internal BadHttpRequestException(string message, int statusCode, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.RequestRejectionReason reason) : base(default(string)) => throw null; @@ -85,7 +80,6 @@ namespace Microsoft public int StatusCode { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Http2Limits` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Http2Limits { public int HeaderTableSize { get => throw null; set => throw null; } @@ -99,14 +93,12 @@ namespace Microsoft public int MaxStreamsPerConnection { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Http3Limits` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Http3Limits { public Http3Limits() => throw null; public int MaxRequestHeaderFieldSize { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum HttpProtocols : int { @@ -118,7 +110,6 @@ namespace Microsoft None = 0, } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServer` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KestrelServer : Microsoft.AspNetCore.Hosting.Server.IServer, System.IDisposable { public void Dispose() => throw null; @@ -129,7 +120,6 @@ namespace Microsoft public System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerLimits` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KestrelServerLimits { public Microsoft.AspNetCore.Server.Kestrel.Core.Http2Limits Http2 { get => throw null; } @@ -149,7 +139,6 @@ namespace Microsoft public System.TimeSpan RequestHeadersTimeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KestrelServerOptions { public bool AddServerHeader { get => throw null; set => throw null; } @@ -185,7 +174,6 @@ namespace Microsoft public System.Func ResponseHeaderEncodingSelector { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.ListenOptions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ListenOptions : Microsoft.AspNetCore.Connections.IConnectionBuilder, Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder { public System.IServiceProvider ApplicationServices { get => throw null; } @@ -204,7 +192,6 @@ namespace Microsoft Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder Microsoft.AspNetCore.Connections.IMultiplexedConnectionBuilder.Use(System.Func middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.MinDataRate` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MinDataRate { public double BytesPerSecond { get => throw null; } @@ -215,7 +202,6 @@ namespace Microsoft namespace Features { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.IConnectionTimeoutFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConnectionTimeoutFeature { void CancelTimeout(); @@ -223,31 +209,26 @@ namespace Microsoft void SetTimeout(System.TimeSpan timeSpan); } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.IDecrementConcurrentConnectionCountFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDecrementConcurrentConnectionCountFeature { void ReleaseConnection(); } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttp2StreamIdFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttp2StreamIdFeature { int StreamId { get; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinRequestBodyDataRateFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpMinRequestBodyDataRateFeature { Microsoft.AspNetCore.Server.Kestrel.Core.MinDataRate MinDataRate { get; set; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.IHttpMinResponseDataRateFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpMinResponseDataRateFeature { Microsoft.AspNetCore.Server.Kestrel.Core.MinDataRate MinDataRate { get; set; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Features.ITlsApplicationProtocolFeature` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITlsApplicationProtocolFeature { System.ReadOnlyMemory ApplicationProtocol { get; } @@ -258,7 +239,6 @@ namespace Microsoft { namespace Http { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpMethod` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HttpMethod : byte { Connect = 7, @@ -274,7 +254,6 @@ namespace Microsoft Trace = 5, } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpParser<>` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpParser where TRequestHandler : Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpHeadersHandler, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpRequestLineHandler { public HttpParser() => throw null; @@ -283,7 +262,6 @@ namespace Microsoft public bool ParseRequestLine(TRequestHandler handler, ref System.Buffers.SequenceReader reader) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpScheme` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HttpScheme : int { Http = 0, @@ -291,7 +269,6 @@ namespace Microsoft Unknown = -1, } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpVersion` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HttpVersion : sbyte { Http10 = 0, @@ -301,7 +278,6 @@ namespace Microsoft Unknown = -1, } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpVersionAndMethod` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct HttpVersionAndMethod { // Stub generator skipped constructor @@ -311,7 +287,6 @@ namespace Microsoft public Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpVersion Version { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpHeadersHandler` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpHeadersHandler { void OnHeader(System.ReadOnlySpan name, System.ReadOnlySpan value); @@ -320,23 +295,19 @@ namespace Microsoft void OnStaticIndexedHeader(int index, System.ReadOnlySpan value); } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpParser<>` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IHttpParser where TRequestHandler : Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpHeadersHandler, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpRequestLineHandler { } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.IHttpRequestLineHandler` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpRequestLineHandler { void OnStartLine(Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpVersionAndMethod versionAndMethod, Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.TargetOffsetPathLength targetPath, System.Span startLine); } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.RequestRejectionReason` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal enum RequestRejectionReason : int { } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.TargetOffsetPathLength` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct TargetOffsetPathLength { public bool IsEncoded { get => throw null; } @@ -351,13 +322,11 @@ namespace Microsoft } namespace Https { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Https.CertificateLoader` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CertificateLoader { public static System.Security.Cryptography.X509Certificates.X509Certificate2 LoadFromStoreCert(string subject, string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, bool allowInvalid) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ClientCertificateMode : int { AllowCertificate = 1, @@ -366,7 +335,6 @@ namespace Microsoft RequireCertificate = 2, } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Https.HttpsConnectionAdapterOptions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpsConnectionAdapterOptions { public void AllowAnyClientCertificate() => throw null; @@ -377,11 +345,11 @@ namespace Microsoft public HttpsConnectionAdapterOptions() => throw null; public System.Action OnAuthenticate { get => throw null; set => throw null; } public System.Security.Cryptography.X509Certificates.X509Certificate2 ServerCertificate { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection ServerCertificateChain { get => throw null; set => throw null; } public System.Func ServerCertificateSelector { get => throw null; set => throw null; } public System.Security.Authentication.SslProtocols SslProtocols { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Https.TlsHandshakeCallbackContext` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TlsHandshakeCallbackContext { public bool AllowDelayedClientCertificateNegotation { get => throw null; set => throw null; } @@ -393,7 +361,6 @@ namespace Microsoft public TlsHandshakeCallbackContext() => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Https.TlsHandshakeCallbackOptions` in `Microsoft.AspNetCore.Server.Kestrel.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TlsHandshakeCallbackOptions { public System.TimeSpan HandshakeTimeout { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.cs index 979ffc7221f..d5561036f80 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Quic, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderQuicExtensions` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Quic, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostBuilderQuicExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseQuic(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder) => throw null; @@ -22,14 +22,14 @@ namespace Microsoft { namespace Quic { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Quic.QuicTransportOptions` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Quic, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class QuicTransportOptions { public int Backlog { get => throw null; set => throw null; } - public System.TimeSpan IdleTimeout { get => throw null; set => throw null; } - public System.UInt16 MaxBidirectionalStreamCount { get => throw null; set => throw null; } + public System.Int64 DefaultCloseErrorCode { get => throw null; set => throw null; } + public System.Int64 DefaultStreamErrorCode { get => throw null; set => throw null; } + public int MaxBidirectionalStreamCount { get => throw null; set => throw null; } public System.Int64? MaxReadBufferSize { get => throw null; set => throw null; } - public System.UInt16 MaxUnidirectionalStreamCount { get => throw null; set => throw null; } + public int MaxUnidirectionalStreamCount { get => throw null; set => throw null; } public System.Int64? MaxWriteBufferSize { get => throw null; set => throw null; } public QuicTransportOptions() => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.cs index 5c3c77a5b97..7ad604b14b3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderSocketExtensions` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostBuilderSocketExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder UseSockets(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder) => throw null; @@ -22,7 +22,6 @@ namespace Microsoft { namespace Sockets { - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionContextFactory` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SocketConnectionContextFactory : System.IDisposable { public Microsoft.AspNetCore.Connections.ConnectionContext Create(System.Net.Sockets.Socket socket) => throw null; @@ -30,7 +29,6 @@ namespace Microsoft public SocketConnectionContextFactory(Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionFactoryOptions options, Microsoft.Extensions.Logging.ILogger logger) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketConnectionFactoryOptions` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SocketConnectionFactoryOptions { public int IOQueueCount { get => throw null; set => throw null; } @@ -41,14 +39,12 @@ namespace Microsoft public bool WaitForDataBeforeAllocatingBuffer { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportFactory` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SocketTransportFactory : Microsoft.AspNetCore.Connections.IConnectionListenerFactory { public System.Threading.Tasks.ValueTask BindAsync(System.Net.EndPoint endpoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public SocketTransportFactory(Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.SocketTransportOptions` in `Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SocketTransportOptions { public int Backlog { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.cs index 71b47d54f4b..c823cee8ba8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Server.Kestrel.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Server.Kestrel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.AspNetCore.Hosting.WebHostBuilderKestrelExtensions` in `Microsoft.AspNetCore.Server.Kestrel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHostBuilderKestrelExtensions { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder ConfigureKestrel(this Microsoft.AspNetCore.Hosting.IWebHostBuilder hostBuilder, System.Action options) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Session.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Session.cs index 4daf5ac5360..28e8d10f164 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Session.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.Session.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.Session, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.SessionMiddlewareExtensions` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SessionMiddlewareExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseSession(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseSession(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.SessionOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.SessionOptions` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SessionOptions { public Microsoft.AspNetCore.Http.CookieBuilder Cookie { get => throw null; set => throw null; } @@ -25,7 +24,6 @@ namespace Microsoft } namespace Session { - // Generated from `Microsoft.AspNetCore.Session.DistributedSession` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedSession : Microsoft.AspNetCore.Http.ISession { public void Clear() => throw null; @@ -40,34 +38,29 @@ namespace Microsoft public bool TryGetValue(string key, out System.Byte[] value) => throw null; } - // Generated from `Microsoft.AspNetCore.Session.DistributedSessionStore` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedSessionStore : Microsoft.AspNetCore.Session.ISessionStore { public Microsoft.AspNetCore.Http.ISession Create(string sessionKey, System.TimeSpan idleTimeout, System.TimeSpan ioTimeout, System.Func tryEstablishSession, bool isNewSessionKey) => throw null; public DistributedSessionStore(Microsoft.Extensions.Caching.Distributed.IDistributedCache cache, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Session.ISessionStore` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISessionStore { Microsoft.AspNetCore.Http.ISession Create(string sessionKey, System.TimeSpan idleTimeout, System.TimeSpan ioTimeout, System.Func tryEstablishSession, bool isNewSessionKey); } - // Generated from `Microsoft.AspNetCore.Session.SessionDefaults` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SessionDefaults { public static string CookieName; public static string CookiePath; } - // Generated from `Microsoft.AspNetCore.Session.SessionFeature` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SessionFeature : Microsoft.AspNetCore.Http.Features.ISessionFeature { public Microsoft.AspNetCore.Http.ISession Session { get => throw null; set => throw null; } public SessionFeature() => throw null; } - // Generated from `Microsoft.AspNetCore.Session.SessionMiddleware` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SessionMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; @@ -80,7 +73,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.SessionServiceCollectionExtensions` in `Microsoft.AspNetCore.Session, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SessionServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddSession(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Common.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Common.cs index 65af8652b83..3cd6eb28f50 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Common.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Common.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.SignalR.Common, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SignalR { - // Generated from `Microsoft.AspNetCore.SignalR.HubException` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubException : System.Exception { public HubException() => throw null; @@ -15,15 +15,14 @@ namespace Microsoft public HubException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.IInvocationBinder` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IInvocationBinder { System.Collections.Generic.IReadOnlyList GetParameterTypes(string methodName); System.Type GetReturnType(string invocationId); System.Type GetStreamItemType(string streamId); + string GetTarget(System.ReadOnlySpan utf8Bytes) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.ISignalRBuilder` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISignalRBuilder { Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } @@ -31,13 +30,11 @@ namespace Microsoft namespace Protocol { - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.CancelInvocationMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CancelInvocationMessage : Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage { public CancelInvocationMessage(string invocationId) : base(default(string)) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.CloseMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CloseMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public bool AllowReconnect { get => throw null; } @@ -47,7 +44,6 @@ namespace Microsoft public string Error { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.CompletionMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompletionMessage : Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage { public CompletionMessage(string invocationId, string error, object result, bool hasResult) : base(default(string)) => throw null; @@ -60,7 +56,6 @@ namespace Microsoft public static Microsoft.AspNetCore.SignalR.Protocol.CompletionMessage WithResult(string invocationId, object payload) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HandshakeProtocol` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HandshakeProtocol { public static System.ReadOnlySpan GetSuccessfulHandshake(Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol protocol) => throw null; @@ -70,7 +65,6 @@ namespace Microsoft public static void WriteResponseMessage(Microsoft.AspNetCore.SignalR.Protocol.HandshakeResponseMessage responseMessage, System.Buffers.IBufferWriter output) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HandshakeRequestMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandshakeRequestMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public HandshakeRequestMessage(string protocol, int version) => throw null; @@ -78,7 +72,6 @@ namespace Microsoft public int Version { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HandshakeResponseMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HandshakeResponseMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public static Microsoft.AspNetCore.SignalR.Protocol.HandshakeResponseMessage Empty; @@ -86,7 +79,6 @@ namespace Microsoft public HandshakeResponseMessage(string error) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HubInvocationMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public System.Collections.Generic.IDictionary Headers { get => throw null; set => throw null; } @@ -94,13 +86,11 @@ namespace Microsoft public string InvocationId { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HubMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HubMessage { protected HubMessage() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HubMethodInvocationMessage : Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage { public object[] Arguments { get => throw null; } @@ -110,7 +100,6 @@ namespace Microsoft public string Target { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HubProtocolConstants` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HubProtocolConstants { public const int CancelInvocationMessageType = default; @@ -122,13 +111,11 @@ namespace Microsoft public const int StreamItemMessageType = default; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.HubProtocolExtensions` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HubProtocolExtensions { public static System.Byte[] GetMessageBytes(this Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol hubProtocol, Microsoft.AspNetCore.SignalR.Protocol.HubMessage message) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubProtocol { System.ReadOnlyMemory GetMessageBytes(Microsoft.AspNetCore.SignalR.Protocol.HubMessage message); @@ -140,7 +127,6 @@ namespace Microsoft void WriteMessage(Microsoft.AspNetCore.SignalR.Protocol.HubMessage message, System.Buffers.IBufferWriter output); } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.InvocationBindingFailureMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InvocationBindingFailureMessage : Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage { public System.Runtime.ExceptionServices.ExceptionDispatchInfo BindingFailure { get => throw null; } @@ -148,7 +134,6 @@ namespace Microsoft public string Target { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.InvocationMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InvocationMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage { public InvocationMessage(string target, object[] arguments) : base(default(string), default(string), default(object[])) => throw null; @@ -157,13 +142,17 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.PingMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PingMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public static Microsoft.AspNetCore.SignalR.Protocol.PingMessage Instance; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.StreamBindingFailureMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class RawResult + { + public RawResult(System.Buffers.ReadOnlySequence rawBytes) => throw null; + public System.Buffers.ReadOnlySequence RawSerializedData { get => throw null; } + } + public class StreamBindingFailureMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMessage { public System.Runtime.ExceptionServices.ExceptionDispatchInfo BindingFailure { get => throw null; } @@ -171,7 +160,6 @@ namespace Microsoft public StreamBindingFailureMessage(string id, System.Runtime.ExceptionServices.ExceptionDispatchInfo bindingFailure) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.StreamInvocationMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StreamInvocationMessage : Microsoft.AspNetCore.SignalR.Protocol.HubMethodInvocationMessage { public StreamInvocationMessage(string invocationId, string target, object[] arguments) : base(default(string), default(string), default(object[])) => throw null; @@ -179,7 +167,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.StreamItemMessage` in `Microsoft.AspNetCore.SignalR.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StreamItemMessage : Microsoft.AspNetCore.SignalR.Protocol.HubInvocationMessage { public object Item { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Core.cs index 44ffcf4361c..2858ce517d6 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Core.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.SignalR.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,9 +7,19 @@ namespace Microsoft { namespace SignalR { - // Generated from `Microsoft.AspNetCore.SignalR.ClientProxyExtensions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ClientProxyExtensions { + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task InvokeAsync(this Microsoft.AspNetCore.SignalR.ISingleClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken) => throw null; public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.IClientProxy clientProxy, string method, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.IClientProxy clientProxy, string method, object arg1, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.IClientProxy clientProxy, string method, object arg1, object arg2, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -22,11 +33,11 @@ namespace Microsoft public static System.Threading.Tasks.Task SendAsync(this Microsoft.AspNetCore.SignalR.IClientProxy clientProxy, string method, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.DefaultHubLifetimeManager<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultHubLifetimeManager : Microsoft.AspNetCore.SignalR.HubLifetimeManager where THub : Microsoft.AspNetCore.SignalR.Hub { public override System.Threading.Tasks.Task AddToGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public DefaultHubLifetimeManager(Microsoft.Extensions.Logging.ILogger> logger) => throw null; + public override System.Threading.Tasks.Task InvokeConnectionAsync(string connectionId, string methodName, object[] args, System.Threading.CancellationToken cancellationToken) => throw null; public override System.Threading.Tasks.Task OnConnectedAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) => throw null; public override System.Threading.Tasks.Task OnDisconnectedAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) => throw null; public override System.Threading.Tasks.Task RemoveFromGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -39,23 +50,22 @@ namespace Microsoft public override System.Threading.Tasks.Task SendGroupsAsync(System.Collections.Generic.IReadOnlyList groupNames, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public override System.Threading.Tasks.Task SendUserAsync(string userId, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public override System.Threading.Tasks.Task SendUsersAsync(System.Collections.Generic.IReadOnlyList userIds, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override System.Threading.Tasks.Task SetConnectionResultAsync(string connectionId, Microsoft.AspNetCore.SignalR.Protocol.CompletionMessage result) => throw null; + public override bool TryGetReturnType(string invocationId, out System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.DefaultUserIdProvider` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultUserIdProvider : Microsoft.AspNetCore.SignalR.IUserIdProvider { public DefaultUserIdProvider() => throw null; public virtual string GetUserId(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.DynamicHub` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class DynamicHub : Microsoft.AspNetCore.SignalR.Hub { public Microsoft.AspNetCore.SignalR.DynamicHubClients Clients { get => throw null; set => throw null; } protected DynamicHub() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.DynamicHubClients` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DynamicHubClients { public dynamic All { get => throw null; } @@ -73,7 +83,6 @@ namespace Microsoft public dynamic Users(System.Collections.Generic.IReadOnlyList userIds) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Hub` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Hub : System.IDisposable { public Microsoft.AspNetCore.SignalR.IHubCallerClients Clients { get => throw null; set => throw null; } @@ -86,14 +95,12 @@ namespace Microsoft public virtual System.Threading.Tasks.Task OnDisconnectedAsync(System.Exception exception) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.Hub<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class Hub : Microsoft.AspNetCore.SignalR.Hub where T : class { public Microsoft.AspNetCore.SignalR.IHubCallerClients Clients { get => throw null; set => throw null; } protected Hub() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubCallerContext` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HubCallerContext { public abstract void Abort(); @@ -106,7 +113,6 @@ namespace Microsoft public abstract string UserIdentifier { get; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubClientsExtensions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HubClientsExtensions { public static T AllExcept(this Microsoft.AspNetCore.SignalR.IHubClients hubClients, System.Collections.Generic.IEnumerable excludedConnectionIds) => throw null; @@ -156,7 +162,6 @@ namespace Microsoft public static T Users(this Microsoft.AspNetCore.SignalR.IHubClients hubClients, string user1, string user2, string user3, string user4, string user5, string user6, string user7, string user8) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubConnectionContext` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubConnectionContext { public virtual void Abort() => throw null; @@ -172,7 +177,6 @@ namespace Microsoft public virtual System.Threading.Tasks.ValueTask WriteAsync(Microsoft.AspNetCore.SignalR.SerializedHubMessage message, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubConnectionContextOptions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubConnectionContextOptions { public System.TimeSpan ClientTimeoutInterval { get => throw null; set => throw null; } @@ -183,17 +187,14 @@ namespace Microsoft public int StreamBufferCapacity { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubConnectionHandler<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubConnectionHandler : Microsoft.AspNetCore.Connections.ConnectionHandler where THub : Microsoft.AspNetCore.SignalR.Hub { public HubConnectionHandler(Microsoft.AspNetCore.SignalR.HubLifetimeManager lifetimeManager, Microsoft.AspNetCore.SignalR.IHubProtocolResolver protocolResolver, Microsoft.Extensions.Options.IOptions globalHubOptions, Microsoft.Extensions.Options.IOptions> hubOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory, Microsoft.AspNetCore.SignalR.IUserIdProvider userIdProvider, Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory) => throw null; public override System.Threading.Tasks.Task OnConnectedAsync(Microsoft.AspNetCore.Connections.ConnectionContext connection) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubConnectionStore` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubConnectionStore { - // Generated from `Microsoft.AspNetCore.SignalR.HubConnectionStore+Enumerator` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public Microsoft.AspNetCore.SignalR.HubConnectionContext Current { get => throw null; } @@ -214,7 +215,6 @@ namespace Microsoft public void Remove(Microsoft.AspNetCore.SignalR.HubConnectionContext connection) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubInvocationContext` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubInvocationContext { public Microsoft.AspNetCore.SignalR.HubCallerContext Context { get => throw null; } @@ -226,7 +226,6 @@ namespace Microsoft public System.IServiceProvider ServiceProvider { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubLifetimeContext` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubLifetimeContext { public Microsoft.AspNetCore.SignalR.HubCallerContext Context { get => throw null; } @@ -235,11 +234,11 @@ namespace Microsoft public System.IServiceProvider ServiceProvider { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubLifetimeManager<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HubLifetimeManager where THub : Microsoft.AspNetCore.SignalR.Hub { public abstract System.Threading.Tasks.Task AddToGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); protected HubLifetimeManager() => throw null; + public virtual System.Threading.Tasks.Task InvokeConnectionAsync(string connectionId, string methodName, object[] args, System.Threading.CancellationToken cancellationToken) => throw null; public abstract System.Threading.Tasks.Task OnConnectedAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection); public abstract System.Threading.Tasks.Task OnDisconnectedAsync(Microsoft.AspNetCore.SignalR.HubConnectionContext connection); public abstract System.Threading.Tasks.Task RemoveFromGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -252,26 +251,26 @@ namespace Microsoft public abstract System.Threading.Tasks.Task SendGroupsAsync(System.Collections.Generic.IReadOnlyList groupNames, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); public abstract System.Threading.Tasks.Task SendUserAsync(string userId, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); public abstract System.Threading.Tasks.Task SendUsersAsync(System.Collections.Generic.IReadOnlyList userIds, string methodName, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); + public virtual System.Threading.Tasks.Task SetConnectionResultAsync(string connectionId, Microsoft.AspNetCore.SignalR.Protocol.CompletionMessage result) => throw null; + public virtual bool TryGetReturnType(string invocationId, out System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubMetadata` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubMetadata { public HubMetadata(System.Type hubType) => throw null; public System.Type HubType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubMethodNameAttribute` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubMethodNameAttribute : System.Attribute { public HubMethodNameAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubOptions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubOptions { public System.TimeSpan? ClientTimeoutInterval { get => throw null; set => throw null; } + public bool DisableImplicitFromServicesParameters { get => throw null; set => throw null; } public bool? EnableDetailedErrors { get => throw null; set => throw null; } public System.TimeSpan? HandshakeTimeout { get => throw null; set => throw null; } public HubOptions() => throw null; @@ -282,13 +281,11 @@ namespace Microsoft public System.Collections.Generic.IList SupportedProtocols { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.SignalR.HubOptions<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubOptions : Microsoft.AspNetCore.SignalR.HubOptions where THub : Microsoft.AspNetCore.SignalR.Hub { public HubOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubOptionsExtensions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HubOptionsExtensions { public static void AddFilter(this Microsoft.AspNetCore.SignalR.HubOptions options, Microsoft.AspNetCore.SignalR.IHubFilter hubFilter) => throw null; @@ -296,46 +293,41 @@ namespace Microsoft public static void AddFilter(this Microsoft.AspNetCore.SignalR.HubOptions options) where TFilter : Microsoft.AspNetCore.SignalR.IHubFilter => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubOptionsSetup` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubOptionsSetup : Microsoft.Extensions.Options.IConfigureOptions { public void Configure(Microsoft.AspNetCore.SignalR.HubOptions options) => throw null; public HubOptionsSetup(System.Collections.Generic.IEnumerable protocols) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.HubOptionsSetup<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubOptionsSetup : Microsoft.Extensions.Options.IConfigureOptions> where THub : Microsoft.AspNetCore.SignalR.Hub { public void Configure(Microsoft.AspNetCore.SignalR.HubOptions options) => throw null; public HubOptionsSetup(Microsoft.Extensions.Options.IOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.IClientProxy` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IClientProxy { System.Threading.Tasks.Task SendCoreAsync(string method, object[] args, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.SignalR.IGroupManager` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IGroupManager { System.Threading.Tasks.Task AddToGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); System.Threading.Tasks.Task RemoveFromGroupAsync(string connectionId, string groupName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.SignalR.IHubActivator<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubActivator where THub : Microsoft.AspNetCore.SignalR.Hub { THub Create(); void Release(THub hub); } - // Generated from `Microsoft.AspNetCore.SignalR.IHubCallerClients` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubCallerClients : Microsoft.AspNetCore.SignalR.IHubCallerClients, Microsoft.AspNetCore.SignalR.IHubClients { + Microsoft.AspNetCore.SignalR.ISingleClientProxy Caller { get => throw null; } + Microsoft.AspNetCore.SignalR.ISingleClientProxy Client(string connectionId) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.IHubCallerClients<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubCallerClients : Microsoft.AspNetCore.SignalR.IHubClients { T Caller { get; } @@ -343,12 +335,11 @@ namespace Microsoft T OthersInGroup(string groupName); } - // Generated from `Microsoft.AspNetCore.SignalR.IHubClients` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubClients : Microsoft.AspNetCore.SignalR.IHubClients { + Microsoft.AspNetCore.SignalR.ISingleClientProxy Client(string connectionId) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.IHubClients<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubClients { T All { get; } @@ -362,28 +353,24 @@ namespace Microsoft T Users(System.Collections.Generic.IReadOnlyList userIds); } - // Generated from `Microsoft.AspNetCore.SignalR.IHubContext` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubContext { Microsoft.AspNetCore.SignalR.IHubClients Clients { get; } Microsoft.AspNetCore.SignalR.IGroupManager Groups { get; } } - // Generated from `Microsoft.AspNetCore.SignalR.IHubContext<,>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubContext where T : class where THub : Microsoft.AspNetCore.SignalR.Hub { Microsoft.AspNetCore.SignalR.IHubClients Clients { get; } Microsoft.AspNetCore.SignalR.IGroupManager Groups { get; } } - // Generated from `Microsoft.AspNetCore.SignalR.IHubContext<>` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubContext where THub : Microsoft.AspNetCore.SignalR.Hub { Microsoft.AspNetCore.SignalR.IHubClients Clients { get; } Microsoft.AspNetCore.SignalR.IGroupManager Groups { get; } } - // Generated from `Microsoft.AspNetCore.SignalR.IHubFilter` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubFilter { System.Threading.Tasks.ValueTask InvokeMethodAsync(Microsoft.AspNetCore.SignalR.HubInvocationContext invocationContext, System.Func> next) => throw null; @@ -391,25 +378,26 @@ namespace Microsoft System.Threading.Tasks.Task OnDisconnectedAsync(Microsoft.AspNetCore.SignalR.HubLifetimeContext context, System.Exception exception, System.Func next) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.IHubProtocolResolver` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubProtocolResolver { System.Collections.Generic.IReadOnlyList AllProtocols { get; } Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol GetProtocol(string protocolName, System.Collections.Generic.IReadOnlyList supportedProtocols); } - // Generated from `Microsoft.AspNetCore.SignalR.ISignalRServerBuilder` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISignalRServerBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder { } - // Generated from `Microsoft.AspNetCore.SignalR.IUserIdProvider` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public interface ISingleClientProxy : Microsoft.AspNetCore.SignalR.IClientProxy + { + System.Threading.Tasks.Task InvokeCoreAsync(string method, object[] args, System.Threading.CancellationToken cancellationToken); + } + public interface IUserIdProvider { string GetUserId(Microsoft.AspNetCore.SignalR.HubConnectionContext connection); } - // Generated from `Microsoft.AspNetCore.SignalR.SerializedHubMessage` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SerializedHubMessage { public System.ReadOnlyMemory GetSerializedMessage(Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol protocol) => throw null; @@ -418,7 +406,6 @@ namespace Microsoft public SerializedHubMessage(System.Collections.Generic.IReadOnlyList messages) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.SerializedMessage` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct SerializedMessage { public string ProtocolName { get => throw null; } @@ -427,7 +414,6 @@ namespace Microsoft public SerializedMessage(string protocolName, System.ReadOnlyMemory serialized) => throw null; } - // Generated from `Microsoft.AspNetCore.SignalR.SignalRConnectionBuilderExtensions` in `Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class SignalRConnectionBuilderExtensions { public static Microsoft.AspNetCore.Connections.IConnectionBuilder UseHub(this Microsoft.AspNetCore.Connections.IConnectionBuilder connectionBuilder) where THub : Microsoft.AspNetCore.SignalR.Hub => throw null; @@ -439,7 +425,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.SignalRDependencyInjectionExtensions` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class SignalRDependencyInjectionExtensions { public static Microsoft.AspNetCore.SignalR.ISignalRServerBuilder AddSignalRCore(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Protocols.Json.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Protocols.Json.cs index de932678c6a..ff4830b57ee 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Protocols.Json.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.Protocols.Json.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.SignalR.Protocols.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SignalR { - // Generated from `Microsoft.AspNetCore.SignalR.JsonHubProtocolOptions` in `Microsoft.AspNetCore.SignalR.Protocols.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonHubProtocolOptions { public JsonHubProtocolOptions() => throw null; @@ -15,7 +15,6 @@ namespace Microsoft namespace Protocol { - // Generated from `Microsoft.AspNetCore.SignalR.Protocol.JsonHubProtocol` in `Microsoft.AspNetCore.SignalR.Protocols.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonHubProtocol : Microsoft.AspNetCore.SignalR.Protocol.IHubProtocol { public System.ReadOnlyMemory GetMessageBytes(Microsoft.AspNetCore.SignalR.Protocol.HubMessage message) => throw null; @@ -36,7 +35,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.JsonProtocolDependencyInjectionExtensions` in `Microsoft.AspNetCore.SignalR.Protocols.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JsonProtocolDependencyInjectionExtensions { public static TBuilder AddJsonProtocol(this TBuilder builder) where TBuilder : Microsoft.AspNetCore.SignalR.ISignalRBuilder => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.cs index aa92dae4ff4..9eb2652e6dc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.SignalR.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.SignalR, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,20 +7,18 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.HubEndpointConventionBuilder` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HubEndpointConventionBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder, Microsoft.AspNetCore.Builder.IHubEndpointConventionBuilder { public void Add(System.Action convention) => throw null; + public void Finally(System.Action finalConvention) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.HubEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HubEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.HubEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern) where THub : Microsoft.AspNetCore.SignalR.Hub => throw null; public static Microsoft.AspNetCore.Builder.HubEndpointConventionBuilder MapHub(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string pattern, System.Action configureOptions) where THub : Microsoft.AspNetCore.SignalR.Hub => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.IHubEndpointConventionBuilder` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHubEndpointConventionBuilder : Microsoft.AspNetCore.Builder.IEndpointConventionBuilder { } @@ -27,7 +26,6 @@ namespace Microsoft } namespace SignalR { - // Generated from `Microsoft.AspNetCore.SignalR.GetHttpContextExtensions` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class GetHttpContextExtensions { public static Microsoft.AspNetCore.Http.HttpContext GetHttpContext(this Microsoft.AspNetCore.SignalR.HubCallerContext connection) => throw null; @@ -40,7 +38,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.SignalRDependencyInjectionExtensions` in `Microsoft.AspNetCore.SignalR, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.AspNetCore.SignalR.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class SignalRDependencyInjectionExtensions { public static Microsoft.AspNetCore.SignalR.ISignalRServerBuilder AddHubOptions(this Microsoft.AspNetCore.SignalR.ISignalRServerBuilder signalrBuilder, System.Action> configure) where THub : Microsoft.AspNetCore.SignalR.Hub => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.StaticFiles.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.StaticFiles.cs index 4b68bca97bf..6e68ef66b36 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.StaticFiles.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.StaticFiles.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.StaticFiles, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.DefaultFilesExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DefaultFilesExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDefaultFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -14,7 +14,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDefaultFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string requestPath) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.DefaultFilesOptions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultFilesOptions : Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptionsBase { public System.Collections.Generic.IList DefaultFileNames { get => throw null; set => throw null; } @@ -22,7 +21,6 @@ namespace Microsoft public DefaultFilesOptions(Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions sharedOptions) : base(default(Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.DirectoryBrowserExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DirectoryBrowserExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDirectoryBrowser(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -30,7 +28,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseDirectoryBrowser(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string requestPath) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.DirectoryBrowserOptions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DirectoryBrowserOptions : Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptionsBase { public DirectoryBrowserOptions() : base(default(Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions)) => throw null; @@ -38,7 +35,6 @@ namespace Microsoft public Microsoft.AspNetCore.StaticFiles.IDirectoryFormatter Formatter { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.FileServerExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class FileServerExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseFileServer(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -47,7 +43,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseFileServer(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string requestPath) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.FileServerOptions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileServerOptions : Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptionsBase { public Microsoft.AspNetCore.Builder.DefaultFilesOptions DefaultFilesOptions { get => throw null; } @@ -58,7 +53,6 @@ namespace Microsoft public Microsoft.AspNetCore.Builder.StaticFileOptions StaticFileOptions { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.StaticFileExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StaticFileExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseStaticFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; @@ -66,7 +60,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseStaticFiles(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, string requestPath) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.StaticFileOptions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StaticFileOptions : Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptionsBase { public Microsoft.AspNetCore.StaticFiles.IContentTypeProvider ContentTypeProvider { get => throw null; set => throw null; } @@ -78,7 +71,6 @@ namespace Microsoft public StaticFileOptions(Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions sharedOptions) : base(default(Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.StaticFilesEndpointRouteBuilderExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StaticFilesEndpointRouteBuilderExtensions { public static Microsoft.AspNetCore.Builder.IEndpointConventionBuilder MapFallbackToFile(this Microsoft.AspNetCore.Routing.IEndpointRouteBuilder endpoints, string filePath) => throw null; @@ -90,14 +82,12 @@ namespace Microsoft } namespace StaticFiles { - // Generated from `Microsoft.AspNetCore.StaticFiles.DefaultFilesMiddleware` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultFilesMiddleware { public DefaultFilesMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnv, Microsoft.Extensions.Options.IOptions options) => throw null; public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.DirectoryBrowserMiddleware` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DirectoryBrowserMiddleware { public DirectoryBrowserMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnv, System.Text.Encodings.Web.HtmlEncoder encoder, Microsoft.Extensions.Options.IOptions options) => throw null; @@ -105,7 +95,6 @@ namespace Microsoft public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileExtensionContentTypeProvider : Microsoft.AspNetCore.StaticFiles.IContentTypeProvider { public FileExtensionContentTypeProvider() => throw null; @@ -114,33 +103,28 @@ namespace Microsoft public bool TryGetContentType(string subpath, out string contentType) => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.HtmlDirectoryFormatter` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlDirectoryFormatter : Microsoft.AspNetCore.StaticFiles.IDirectoryFormatter { public virtual System.Threading.Tasks.Task GenerateContentAsync(Microsoft.AspNetCore.Http.HttpContext context, System.Collections.Generic.IEnumerable contents) => throw null; public HtmlDirectoryFormatter(System.Text.Encodings.Web.HtmlEncoder encoder) => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.IContentTypeProvider` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IContentTypeProvider { bool TryGetContentType(string subpath, out string contentType); } - // Generated from `Microsoft.AspNetCore.StaticFiles.IDirectoryFormatter` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDirectoryFormatter { System.Threading.Tasks.Task GenerateContentAsync(Microsoft.AspNetCore.Http.HttpContext context, System.Collections.Generic.IEnumerable contents); } - // Generated from `Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StaticFileMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public StaticFileMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnv, Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.StaticFileResponseContext` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StaticFileResponseContext { public Microsoft.AspNetCore.Http.HttpContext Context { get => throw null; } @@ -150,7 +134,6 @@ namespace Microsoft namespace Infrastructure { - // Generated from `Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SharedOptions { public Microsoft.Extensions.FileProviders.IFileProvider FileProvider { get => throw null; set => throw null; } @@ -159,7 +142,6 @@ namespace Microsoft public SharedOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.StaticFiles.Infrastructure.SharedOptionsBase` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class SharedOptionsBase { public Microsoft.Extensions.FileProviders.IFileProvider FileProvider { get => throw null; set => throw null; } @@ -176,7 +158,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.DirectoryBrowserServiceExtensions` in `Microsoft.AspNetCore.StaticFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DirectoryBrowserServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddDirectoryBrowser(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebSockets.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebSockets.cs index abcc6d38188..72f1e6ca3ca 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebSockets.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebSockets.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.WebSockets, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.WebSocketMiddlewareExtensions` in `Microsoft.AspNetCore.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebSocketMiddlewareExtensions { public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseWebSockets(this Microsoft.AspNetCore.Builder.IApplicationBuilder app) => throw null; public static Microsoft.AspNetCore.Builder.IApplicationBuilder UseWebSockets(this Microsoft.AspNetCore.Builder.IApplicationBuilder app, Microsoft.AspNetCore.Builder.WebSocketOptions options) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.WebSocketOptions` in `Microsoft.AspNetCore.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebSocketOptions { public System.Collections.Generic.IList AllowedOrigins { get => throw null; } @@ -25,7 +24,6 @@ namespace Microsoft } namespace WebSockets { - // Generated from `Microsoft.AspNetCore.WebSockets.ExtendedWebSocketAcceptContext` in `Microsoft.AspNetCore.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ExtendedWebSocketAcceptContext : Microsoft.AspNetCore.Http.WebSocketAcceptContext { public ExtendedWebSocketAcceptContext() => throw null; @@ -34,14 +32,12 @@ namespace Microsoft public override string SubProtocol { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.WebSockets.WebSocketMiddleware` in `Microsoft.AspNetCore.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebSocketMiddleware { public System.Threading.Tasks.Task Invoke(Microsoft.AspNetCore.Http.HttpContext context) => throw null; public WebSocketMiddleware(Microsoft.AspNetCore.Http.RequestDelegate next, Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.WebSockets.WebSocketsDependencyInjectionExtensions` in `Microsoft.AspNetCore.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebSocketsDependencyInjectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddWebSockets(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Action configure) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebUtilities.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebUtilities.cs index 1b3b474f451..8ffc0cbc62e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebUtilities.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.WebUtilities.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore.WebUtilities, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace WebUtilities { - // Generated from `Microsoft.AspNetCore.WebUtilities.Base64UrlTextEncoder` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Base64UrlTextEncoder { public static System.Byte[] Decode(string text) => throw null; public static string Encode(System.Byte[] data) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.BufferedReadStream` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BufferedReadStream : System.IO.Stream { public System.ArraySegment BufferedData { get => throw null; } @@ -41,9 +40,9 @@ namespace Microsoft public override void SetLength(System.Int64 value) => throw null; public override void Write(System.Byte[] buffer, int offset, int count) => throw null; public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileBufferingReadStream : System.IO.Stream { public override bool CanRead { get => throw null; } @@ -71,9 +70,9 @@ namespace Microsoft public string TempFileName { get => throw null; } public override void Write(System.Byte[] buffer, int offset, int count) => throw null; public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.FileBufferingWriteStream` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileBufferingWriteStream : System.IO.Stream { public override bool CanRead { get => throw null; } @@ -91,6 +90,7 @@ namespace Microsoft public override System.Int64 Position { get => throw null; set => throw null; } public override int Read(System.Byte[] buffer, int offset, int count) => throw null; public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null; public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null; public override void SetLength(System.Int64 value) => throw null; public override void Write(System.Byte[] buffer, int offset, int count) => throw null; @@ -98,7 +98,6 @@ namespace Microsoft public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.FileMultipartSection` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileMultipartSection { public FileMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section) => throw null; @@ -109,17 +108,16 @@ namespace Microsoft public Microsoft.AspNetCore.WebUtilities.MultipartSection Section { get => throw null; } } - // Generated from `Microsoft.AspNetCore.WebUtilities.FormMultipartSection` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormMultipartSection { public FormMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section) => throw null; public FormMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section, Microsoft.Net.Http.Headers.ContentDispositionHeaderValue header) => throw null; public System.Threading.Tasks.Task GetValueAsync() => throw null; + public System.Threading.Tasks.ValueTask GetValueAsync(System.Threading.CancellationToken cancellationToken) => throw null; public string Name { get => throw null; } public Microsoft.AspNetCore.WebUtilities.MultipartSection Section { get => throw null; } } - // Generated from `Microsoft.AspNetCore.WebUtilities.FormPipeReader` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormPipeReader { public FormPipeReader(System.IO.Pipelines.PipeReader pipeReader) => throw null; @@ -130,7 +128,6 @@ namespace Microsoft public int ValueLengthLimit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.WebUtilities.FormReader` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FormReader : System.IDisposable { public const int DefaultKeyLengthLimit = default; @@ -151,7 +148,6 @@ namespace Microsoft public int ValueLengthLimit { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.WebUtilities.HttpRequestStreamReader` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpRequestStreamReader : System.IO.TextReader { protected override void Dispose(bool disposing) => throw null; @@ -169,7 +165,6 @@ namespace Microsoft public override System.Threading.Tasks.Task ReadToEndAsync() => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.HttpResponseStreamWriter` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpResponseStreamWriter : System.IO.TextWriter { protected override void Dispose(bool disposing) => throw null; @@ -189,10 +184,12 @@ namespace Microsoft public override System.Threading.Tasks.Task WriteAsync(System.Char value) => throw null; public override System.Threading.Tasks.Task WriteAsync(string value) => throw null; public override void WriteLine(System.ReadOnlySpan value) => throw null; + public override System.Threading.Tasks.Task WriteLineAsync(System.Char[] values, int index, int count) => throw null; public override System.Threading.Tasks.Task WriteLineAsync(System.ReadOnlyMemory value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override System.Threading.Tasks.Task WriteLineAsync(System.Char value) => throw null; + public override System.Threading.Tasks.Task WriteLineAsync(string value) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.KeyValueAccumulator` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct KeyValueAccumulator { public void Append(string key, string value) => throw null; @@ -203,7 +200,6 @@ namespace Microsoft public int ValueCount { get => throw null; } } - // Generated from `Microsoft.AspNetCore.WebUtilities.MultipartReader` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MultipartReader { public System.Int64? BodyLengthLimit { get => throw null; set => throw null; } @@ -216,7 +212,6 @@ namespace Microsoft public System.Threading.Tasks.Task ReadNextSectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.MultipartSection` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MultipartSection { public System.Int64? BaseStreamOffset { get => throw null; set => throw null; } @@ -227,7 +222,6 @@ namespace Microsoft public MultipartSection() => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.MultipartSectionConverterExtensions` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MultipartSectionConverterExtensions { public static Microsoft.AspNetCore.WebUtilities.FileMultipartSection AsFileSection(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) => throw null; @@ -235,13 +229,12 @@ namespace Microsoft public static Microsoft.Net.Http.Headers.ContentDispositionHeaderValue GetContentDispositionHeader(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.MultipartSectionStreamExtensions` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MultipartSectionStreamExtensions { public static System.Threading.Tasks.Task ReadAsStringAsync(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) => throw null; + public static System.Threading.Tasks.ValueTask ReadAsStringAsync(this Microsoft.AspNetCore.WebUtilities.MultipartSection section, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.QueryHelpers` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class QueryHelpers { public static string AddQueryString(string uri, System.Collections.Generic.IDictionary queryString) => throw null; @@ -252,10 +245,8 @@ namespace Microsoft public static System.Collections.Generic.Dictionary ParseQuery(string queryString) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.QueryStringEnumerable` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct QueryStringEnumerable { - // Generated from `Microsoft.AspNetCore.WebUtilities.QueryStringEnumerable+EncodedNameValuePair` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct EncodedNameValuePair { public System.ReadOnlyMemory DecodeName() => throw null; @@ -266,7 +257,6 @@ namespace Microsoft } - // Generated from `Microsoft.AspNetCore.WebUtilities.QueryStringEnumerable+Enumerator` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator { public Microsoft.AspNetCore.WebUtilities.QueryStringEnumerable.EncodedNameValuePair Current { get => throw null; } @@ -281,13 +271,11 @@ namespace Microsoft public QueryStringEnumerable(string queryString) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.ReasonPhrases` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ReasonPhrases { public static string GetReasonPhrase(int statusCode) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.StreamHelperExtensions` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StreamHelperExtensions { public static System.Threading.Tasks.Task DrainAsync(this System.IO.Stream stream, System.Buffers.ArrayPool bytePool, System.Int64? limit, System.Threading.CancellationToken cancellationToken) => throw null; @@ -295,7 +283,6 @@ namespace Microsoft public static System.Threading.Tasks.Task DrainAsync(this System.IO.Stream stream, System.Int64? limit, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.AspNetCore.WebUtilities.WebEncoders` in `Microsoft.AspNetCore.WebUtilities, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebEncoders { public static System.Byte[] Base64UrlDecode(string input) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.cs index c0af0af75b4..be27bb030ef 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.AspNetCore.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `Microsoft.AspNetCore, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { namespace AspNetCore { - // Generated from `Microsoft.AspNetCore.WebHost` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class WebHost { public static Microsoft.AspNetCore.Hosting.IWebHostBuilder CreateDefaultBuilder() => throw null; @@ -20,7 +20,6 @@ namespace Microsoft namespace Builder { - // Generated from `Microsoft.AspNetCore.Builder.ConfigureHostBuilder` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureHostBuilder : Microsoft.AspNetCore.Hosting.Infrastructure.ISupportsConfigureWebHost, Microsoft.Extensions.Hosting.IHostBuilder { Microsoft.Extensions.Hosting.IHost Microsoft.Extensions.Hosting.IHostBuilder.Build() => throw null; @@ -34,7 +33,6 @@ namespace Microsoft public Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.ConfigureWebHostBuilder` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureWebHostBuilder : Microsoft.AspNetCore.Hosting.IWebHostBuilder, Microsoft.AspNetCore.Hosting.Infrastructure.ISupportsStartup { Microsoft.AspNetCore.Hosting.IWebHost Microsoft.AspNetCore.Hosting.IWebHostBuilder.Build() => throw null; @@ -49,7 +47,6 @@ namespace Microsoft Microsoft.AspNetCore.Hosting.IWebHostBuilder Microsoft.AspNetCore.Hosting.Infrastructure.ISupportsStartup.UseStartup(System.Func startupFactory) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.WebApplication` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebApplication : Microsoft.AspNetCore.Builder.IApplicationBuilder, Microsoft.AspNetCore.Routing.IEndpointRouteBuilder, Microsoft.Extensions.Hosting.IHost, System.IAsyncDisposable, System.IDisposable { System.IServiceProvider Microsoft.AspNetCore.Builder.IApplicationBuilder.ApplicationServices { get => throw null; set => throw null; } @@ -76,10 +73,9 @@ namespace Microsoft public System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Collections.Generic.ICollection Urls { get => throw null; } - Microsoft.AspNetCore.Builder.IApplicationBuilder Microsoft.AspNetCore.Builder.IApplicationBuilder.Use(System.Func middleware) => throw null; + public Microsoft.AspNetCore.Builder.IApplicationBuilder Use(System.Func middleware) => throw null; } - // Generated from `Microsoft.AspNetCore.Builder.WebApplicationBuilder` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebApplicationBuilder { public Microsoft.AspNetCore.Builder.WebApplication Build() => throw null; @@ -91,7 +87,6 @@ namespace Microsoft public Microsoft.AspNetCore.Builder.ConfigureWebHostBuilder WebHost { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Builder.WebApplicationOptions` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebApplicationOptions { public string ApplicationName { get => throw null; set => throw null; } @@ -108,10 +103,10 @@ namespace Microsoft { namespace Hosting { - // Generated from `Microsoft.Extensions.Hosting.GenericHostBuilderExtensions` in `Microsoft.AspNetCore, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class GenericHostBuilderExtensions { public static Microsoft.Extensions.Hosting.IHostBuilder ConfigureWebHostDefaults(this Microsoft.Extensions.Hosting.IHostBuilder builder, System.Action configure) => throw null; + public static Microsoft.Extensions.Hosting.IHostBuilder ConfigureWebHostDefaults(this Microsoft.Extensions.Hosting.IHostBuilder builder, System.Action configure, System.Action configureOptions) => throw null; } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Abstractions.cs index 75b401a91e8..0dd4639daa7 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Caching.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Distributed { - // Generated from `Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryExtensions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DistributedCacheEntryExtensions { public static Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions SetAbsoluteExpiration(this Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options, System.DateTimeOffset absolute) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public static Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions SetSlidingExpiration(this Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options, System.TimeSpan offset) => throw null; } - // Generated from `Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DistributedCacheEntryOptions { public System.DateTimeOffset? AbsoluteExpiration { get => throw null; set => throw null; } @@ -25,7 +24,6 @@ namespace Microsoft public System.TimeSpan? SlidingExpiration { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Caching.Distributed.DistributedCacheExtensions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DistributedCacheExtensions { public static string GetString(this Microsoft.Extensions.Caching.Distributed.IDistributedCache cache, string key) => throw null; @@ -38,7 +36,6 @@ namespace Microsoft public static System.Threading.Tasks.Task SetStringAsync(this Microsoft.Extensions.Caching.Distributed.IDistributedCache cache, string key, string value, Microsoft.Extensions.Caching.Distributed.DistributedCacheEntryOptions options, System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.Extensions.Caching.Distributed.IDistributedCache` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDistributedCache { System.Byte[] Get(string key); @@ -54,7 +51,6 @@ namespace Microsoft } namespace Memory { - // Generated from `Microsoft.Extensions.Caching.Memory.CacheEntryExtensions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CacheEntryExtensions { public static Microsoft.Extensions.Caching.Memory.ICacheEntry AddExpirationToken(this Microsoft.Extensions.Caching.Memory.ICacheEntry entry, Microsoft.Extensions.Primitives.IChangeToken expirationToken) => throw null; @@ -69,7 +65,6 @@ namespace Microsoft public static Microsoft.Extensions.Caching.Memory.ICacheEntry SetValue(this Microsoft.Extensions.Caching.Memory.ICacheEntry entry, object value) => throw null; } - // Generated from `Microsoft.Extensions.Caching.Memory.CacheExtensions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CacheExtensions { public static object Get(this Microsoft.Extensions.Caching.Memory.IMemoryCache cache, object key) => throw null; @@ -84,7 +79,6 @@ namespace Microsoft public static bool TryGetValue(this Microsoft.Extensions.Caching.Memory.IMemoryCache cache, object key, out TItem value) => throw null; } - // Generated from `Microsoft.Extensions.Caching.Memory.CacheItemPriority` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum CacheItemPriority : int { High = 2, @@ -93,7 +87,6 @@ namespace Microsoft Normal = 1, } - // Generated from `Microsoft.Extensions.Caching.Memory.EvictionReason` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum EvictionReason : int { Capacity = 5, @@ -104,7 +97,6 @@ namespace Microsoft TokenExpired = 4, } - // Generated from `Microsoft.Extensions.Caching.Memory.ICacheEntry` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ICacheEntry : System.IDisposable { System.DateTimeOffset? AbsoluteExpiration { get; set; } @@ -118,15 +110,14 @@ namespace Microsoft object Value { get; set; } } - // Generated from `Microsoft.Extensions.Caching.Memory.IMemoryCache` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IMemoryCache : System.IDisposable { Microsoft.Extensions.Caching.Memory.ICacheEntry CreateEntry(object key); + Microsoft.Extensions.Caching.Memory.MemoryCacheStatistics GetCurrentStatistics() => throw null; void Remove(object key); bool TryGetValue(object key, out object value); } - // Generated from `Microsoft.Extensions.Caching.Memory.MemoryCacheEntryExtensions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MemoryCacheEntryExtensions { public static Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions AddExpirationToken(this Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions options, Microsoft.Extensions.Primitives.IChangeToken expirationToken) => throw null; @@ -139,7 +130,6 @@ namespace Microsoft public static Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions SetSlidingExpiration(this Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions options, System.TimeSpan offset) => throw null; } - // Generated from `Microsoft.Extensions.Caching.Memory.MemoryCacheEntryOptions` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryCacheEntryOptions { public System.DateTimeOffset? AbsoluteExpiration { get => throw null; set => throw null; } @@ -152,7 +142,15 @@ namespace Microsoft public System.TimeSpan? SlidingExpiration { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Caching.Memory.PostEvictionCallbackRegistration` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class MemoryCacheStatistics + { + public System.Int64 CurrentEntryCount { get => throw null; set => throw null; } + public System.Int64? CurrentEstimatedSize { get => throw null; set => throw null; } + public MemoryCacheStatistics() => throw null; + public System.Int64 TotalHits { get => throw null; set => throw null; } + public System.Int64 TotalMisses { get => throw null; set => throw null; } + } + public class PostEvictionCallbackRegistration { public Microsoft.Extensions.Caching.Memory.PostEvictionDelegate EvictionCallback { get => throw null; set => throw null; } @@ -160,20 +158,17 @@ namespace Microsoft public object State { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Caching.Memory.PostEvictionDelegate` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate void PostEvictionDelegate(object key, object value, Microsoft.Extensions.Caching.Memory.EvictionReason reason, object state); } } namespace Internal { - // Generated from `Microsoft.Extensions.Internal.ISystemClock` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISystemClock { System.DateTimeOffset UtcNow { get; } } - // Generated from `Microsoft.Extensions.Internal.SystemClock` in `Microsoft.Extensions.Caching.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SystemClock : Microsoft.Extensions.Internal.ISystemClock { public SystemClock() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Memory.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Memory.cs index f029be7013f..c6e3f69b3c5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Memory.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Caching.Memory.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Caching.Memory, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Distributed { - // Generated from `Microsoft.Extensions.Caching.Distributed.MemoryDistributedCache` in `Microsoft.Extensions.Caching.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryDistributedCache : Microsoft.Extensions.Caching.Distributed.IDistributedCache { public System.Byte[] Get(string key) => throw null; @@ -26,14 +26,15 @@ namespace Microsoft } namespace Memory { - // Generated from `Microsoft.Extensions.Caching.Memory.MemoryCache` in `Microsoft.Extensions.Caching.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryCache : Microsoft.Extensions.Caching.Memory.IMemoryCache, System.IDisposable { + public void Clear() => throw null; public void Compact(double percentage) => throw null; public int Count { get => throw null; } public Microsoft.Extensions.Caching.Memory.ICacheEntry CreateEntry(object key) => throw null; public void Dispose() => throw null; protected virtual void Dispose(bool disposing) => throw null; + public Microsoft.Extensions.Caching.Memory.MemoryCacheStatistics GetCurrentStatistics() => throw null; public MemoryCache(Microsoft.Extensions.Options.IOptions optionsAccessor) => throw null; public MemoryCache(Microsoft.Extensions.Options.IOptions optionsAccessor, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; public void Remove(object key) => throw null; @@ -41,7 +42,6 @@ namespace Microsoft // ERR: Stub generator didn't handle member: ~MemoryCache } - // Generated from `Microsoft.Extensions.Caching.Memory.MemoryCacheOptions` in `Microsoft.Extensions.Caching.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryCacheOptions : Microsoft.Extensions.Options.IOptions { public Microsoft.Extensions.Internal.ISystemClock Clock { get => throw null; set => throw null; } @@ -49,10 +49,11 @@ namespace Microsoft public System.TimeSpan ExpirationScanFrequency { get => throw null; set => throw null; } public MemoryCacheOptions() => throw null; public System.Int64? SizeLimit { get => throw null; set => throw null; } + public bool TrackLinkedCacheEntries { get => throw null; set => throw null; } + public bool TrackStatistics { get => throw null; set => throw null; } Microsoft.Extensions.Caching.Memory.MemoryCacheOptions Microsoft.Extensions.Options.IOptions.Value { get => throw null; } } - // Generated from `Microsoft.Extensions.Caching.Memory.MemoryDistributedCacheOptions` in `Microsoft.Extensions.Caching.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryDistributedCacheOptions : Microsoft.Extensions.Caching.Memory.MemoryCacheOptions { public MemoryDistributedCacheOptions() => throw null; @@ -62,7 +63,6 @@ namespace Microsoft } namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.MemoryCacheServiceCollectionExtensions` in `Microsoft.Extensions.Caching.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MemoryCacheServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddDistributedMemoryCache(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Abstractions.cs index 3e565035cc6..8018c018121 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,16 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.ConfigurationExtensions` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public struct ConfigurationDebugViewContext + { + // Stub generator skipped constructor + public ConfigurationDebugViewContext(string path, string key, string value, Microsoft.Extensions.Configuration.IConfigurationProvider configurationProvider) => throw null; + public Microsoft.Extensions.Configuration.IConfigurationProvider ConfigurationProvider { get => throw null; } + public string Key { get => throw null; } + public string Path { get => throw null; } + public string Value { get => throw null; } + } + public static class ConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder Add(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) where TSource : Microsoft.Extensions.Configuration.IConfigurationSource, new() => throw null; @@ -17,14 +27,12 @@ namespace Microsoft public static Microsoft.Extensions.Configuration.IConfigurationSection GetRequiredSection(this Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationKeyNameAttribute` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationKeyNameAttribute : System.Attribute { public ConfigurationKeyNameAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationPath` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConfigurationPath { public static string Combine(System.Collections.Generic.IEnumerable pathSegments) => throw null; @@ -34,13 +42,12 @@ namespace Microsoft public static string KeyDelimiter; } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationRootExtensions` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConfigurationRootExtensions { public static string GetDebugView(this Microsoft.Extensions.Configuration.IConfigurationRoot root) => throw null; + public static string GetDebugView(this Microsoft.Extensions.Configuration.IConfigurationRoot root, System.Func processValue) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.IConfiguration` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfiguration { System.Collections.Generic.IEnumerable GetChildren(); @@ -49,7 +56,6 @@ namespace Microsoft string this[string key] { get; set; } } - // Generated from `Microsoft.Extensions.Configuration.IConfigurationBuilder` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigurationBuilder { Microsoft.Extensions.Configuration.IConfigurationBuilder Add(Microsoft.Extensions.Configuration.IConfigurationSource source); @@ -58,7 +64,6 @@ namespace Microsoft System.Collections.Generic.IList Sources { get; } } - // Generated from `Microsoft.Extensions.Configuration.IConfigurationProvider` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigurationProvider { System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string parentPath); @@ -68,14 +73,12 @@ namespace Microsoft bool TryGet(string key, out string value); } - // Generated from `Microsoft.Extensions.Configuration.IConfigurationRoot` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigurationRoot : Microsoft.Extensions.Configuration.IConfiguration { System.Collections.Generic.IEnumerable Providers { get; } void Reload(); } - // Generated from `Microsoft.Extensions.Configuration.IConfigurationSection` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigurationSection : Microsoft.Extensions.Configuration.IConfiguration { string Key { get; } @@ -83,7 +86,6 @@ namespace Microsoft string Value { get; set; } } - // Generated from `Microsoft.Extensions.Configuration.IConfigurationSource` in `Microsoft.Extensions.Configuration.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigurationSource { Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Binder.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Binder.cs index 812d09413ee..cec49289494 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Binder.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Binder.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.Binder, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.BinderOptions` in `Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class BinderOptions { public bool BindNonPublicProperties { get => throw null; set => throw null; } @@ -14,7 +14,6 @@ namespace Microsoft public bool ErrorOnUnknownConfiguration { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationBinder` in `Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConfigurationBinder { public static void Bind(this Microsoft.Extensions.Configuration.IConfiguration configuration, object instance) => throw null; @@ -33,18 +32,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'RequiresUnreferencedCodeAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.CommandLine.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.CommandLine.cs index 2ef4bf5e895..19426be86bd 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.CommandLine.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.CommandLine.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.CommandLine, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.CommandLineConfigurationExtensions` in `Microsoft.Extensions.Configuration.CommandLine, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class CommandLineConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddCommandLine(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft namespace CommandLine { - // Generated from `Microsoft.Extensions.Configuration.CommandLine.CommandLineConfigurationProvider` in `Microsoft.Extensions.Configuration.CommandLine, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CommandLineConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider { protected System.Collections.Generic.IEnumerable Args { get => throw null; } @@ -24,7 +23,6 @@ namespace Microsoft public override void Load() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.CommandLine.CommandLineConfigurationSource` in `Microsoft.Extensions.Configuration.CommandLine, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CommandLineConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public System.Collections.Generic.IEnumerable Args { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.EnvironmentVariables.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.EnvironmentVariables.cs index fb82427659e..532a50ee8d9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.EnvironmentVariables.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.EnvironmentVariables.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.EnvironmentVariables, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.EnvironmentVariablesExtensions` in `Microsoft.Extensions.Configuration.EnvironmentVariables, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EnvironmentVariablesExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddEnvironmentVariables(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft namespace EnvironmentVariables { - // Generated from `Microsoft.Extensions.Configuration.EnvironmentVariables.EnvironmentVariablesConfigurationProvider` in `Microsoft.Extensions.Configuration.EnvironmentVariables, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnvironmentVariablesConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider { public EnvironmentVariablesConfigurationProvider() => throw null; @@ -25,7 +24,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.EnvironmentVariables.EnvironmentVariablesConfigurationSource` in `Microsoft.Extensions.Configuration.EnvironmentVariables, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EnvironmentVariablesConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.FileExtensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.FileExtensions.cs index 50b21452fc6..e6c8244ac62 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.FileExtensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.FileExtensions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.FileExtensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.FileConfigurationExtensions` in `Microsoft.Extensions.Configuration.FileExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class FileConfigurationExtensions { public static System.Action GetFileLoadExceptionHandler(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public static Microsoft.Extensions.Configuration.IConfigurationBuilder SetFileProvider(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, Microsoft.Extensions.FileProviders.IFileProvider fileProvider) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.FileConfigurationProvider` in `Microsoft.Extensions.Configuration.FileExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FileConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider, System.IDisposable { public void Dispose() => throw null; @@ -28,7 +27,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.FileConfigurationSource` in `Microsoft.Extensions.Configuration.FileExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FileConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public abstract Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder); @@ -43,7 +41,6 @@ namespace Microsoft public void ResolveFileProvider() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.FileLoadExceptionContext` in `Microsoft.Extensions.Configuration.FileExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileLoadExceptionContext { public System.Exception Exception { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Ini.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Ini.cs index 45549101d20..781201b7ff3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Ini.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Ini.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.Ini, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.IniConfigurationExtensions` in `Microsoft.Extensions.Configuration.Ini, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class IniConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddIniFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) => throw null; @@ -19,21 +19,18 @@ namespace Microsoft namespace Ini { - // Generated from `Microsoft.Extensions.Configuration.Ini.IniConfigurationProvider` in `Microsoft.Extensions.Configuration.Ini, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IniConfigurationProvider : Microsoft.Extensions.Configuration.FileConfigurationProvider { public IniConfigurationProvider(Microsoft.Extensions.Configuration.Ini.IniConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.FileConfigurationSource)) => throw null; public override void Load(System.IO.Stream stream) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Ini.IniConfigurationSource` in `Microsoft.Extensions.Configuration.Ini, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IniConfigurationSource : Microsoft.Extensions.Configuration.FileConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; public IniConfigurationSource() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Ini.IniStreamConfigurationProvider` in `Microsoft.Extensions.Configuration.Ini, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IniStreamConfigurationProvider : Microsoft.Extensions.Configuration.StreamConfigurationProvider { public IniStreamConfigurationProvider(Microsoft.Extensions.Configuration.Ini.IniStreamConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.StreamConfigurationSource)) => throw null; @@ -41,7 +38,6 @@ namespace Microsoft public static System.Collections.Generic.IDictionary Read(System.IO.Stream stream) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Ini.IniStreamConfigurationSource` in `Microsoft.Extensions.Configuration.Ini, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IniStreamConfigurationSource : Microsoft.Extensions.Configuration.StreamConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Json.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Json.cs index 732cdf75dda..f506e72a30f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Json.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Json.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.JsonConfigurationExtensions` in `Microsoft.Extensions.Configuration.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JsonConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) => throw null; @@ -19,28 +19,24 @@ namespace Microsoft namespace Json { - // Generated from `Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider` in `Microsoft.Extensions.Configuration.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonConfigurationProvider : Microsoft.Extensions.Configuration.FileConfigurationProvider { public JsonConfigurationProvider(Microsoft.Extensions.Configuration.Json.JsonConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.FileConfigurationSource)) => throw null; public override void Load(System.IO.Stream stream) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Json.JsonConfigurationSource` in `Microsoft.Extensions.Configuration.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonConfigurationSource : Microsoft.Extensions.Configuration.FileConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; public JsonConfigurationSource() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Json.JsonStreamConfigurationProvider` in `Microsoft.Extensions.Configuration.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonStreamConfigurationProvider : Microsoft.Extensions.Configuration.StreamConfigurationProvider { public JsonStreamConfigurationProvider(Microsoft.Extensions.Configuration.Json.JsonStreamConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.StreamConfigurationSource)) => throw null; public override void Load(System.IO.Stream stream) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Json.JsonStreamConfigurationSource` in `Microsoft.Extensions.Configuration.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JsonStreamConfigurationSource : Microsoft.Extensions.Configuration.StreamConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.KeyPerFile.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.KeyPerFile.cs index 92c2850f211..44168c165bf 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.KeyPerFile.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.KeyPerFile.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.KeyPerFile, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.KeyPerFileConfigurationBuilderExtensions` in `Microsoft.Extensions.Configuration.KeyPerFile, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class KeyPerFileConfigurationBuilderExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddKeyPerFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) => throw null; @@ -17,7 +17,6 @@ namespace Microsoft namespace KeyPerFile { - // Generated from `Microsoft.Extensions.Configuration.KeyPerFile.KeyPerFileConfigurationProvider` in `Microsoft.Extensions.Configuration.KeyPerFile, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyPerFileConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider, System.IDisposable { public void Dispose() => throw null; @@ -26,7 +25,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.KeyPerFile.KeyPerFileConfigurationSource` in `Microsoft.Extensions.Configuration.KeyPerFile, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class KeyPerFileConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.UserSecrets.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.UserSecrets.cs index b1c3fb8f20c..c19f4ae0880 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.UserSecrets.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.UserSecrets.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.UserSecrets, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.UserSecretsConfigurationExtensions` in `Microsoft.Extensions.Configuration.UserSecrets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class UserSecretsConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddUserSecrets(this Microsoft.Extensions.Configuration.IConfigurationBuilder configuration, System.Reflection.Assembly assembly) => throw null; @@ -21,14 +21,12 @@ namespace Microsoft namespace UserSecrets { - // Generated from `Microsoft.Extensions.Configuration.UserSecrets.PathHelper` in `Microsoft.Extensions.Configuration.UserSecrets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PathHelper { public static string GetSecretsPathFromSecretsId(string userSecretsId) => throw null; public PathHelper() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.UserSecrets.UserSecretsIdAttribute` in `Microsoft.Extensions.Configuration.UserSecrets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserSecretsIdAttribute : System.Attribute { public string UserSecretsId { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Xml.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Xml.cs index 213b2d1e24e..34bceff70a4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Xml.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.Xml.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration.Xml, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.XmlConfigurationExtensions` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class XmlConfigurationExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddXmlFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action configureSource) => throw null; @@ -19,21 +19,18 @@ namespace Microsoft namespace Xml { - // Generated from `Microsoft.Extensions.Configuration.Xml.XmlConfigurationProvider` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlConfigurationProvider : Microsoft.Extensions.Configuration.FileConfigurationProvider { public override void Load(System.IO.Stream stream) => throw null; public XmlConfigurationProvider(Microsoft.Extensions.Configuration.Xml.XmlConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.FileConfigurationSource)) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Xml.XmlConfigurationSource` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlConfigurationSource : Microsoft.Extensions.Configuration.FileConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; public XmlConfigurationSource() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Xml.XmlDocumentDecryptor` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlDocumentDecryptor { public System.Xml.XmlReader CreateDecryptingXmlReader(System.IO.Stream input, System.Xml.XmlReaderSettings settings) => throw null; @@ -42,7 +39,6 @@ namespace Microsoft protected XmlDocumentDecryptor() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Xml.XmlStreamConfigurationProvider` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlStreamConfigurationProvider : Microsoft.Extensions.Configuration.StreamConfigurationProvider { public override void Load(System.IO.Stream stream) => throw null; @@ -50,7 +46,6 @@ namespace Microsoft public XmlStreamConfigurationProvider(Microsoft.Extensions.Configuration.Xml.XmlStreamConfigurationSource source) : base(default(Microsoft.Extensions.Configuration.StreamConfigurationSource)) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Xml.XmlStreamConfigurationSource` in `Microsoft.Extensions.Configuration.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class XmlStreamConfigurationSource : Microsoft.Extensions.Configuration.StreamConfigurationSource { public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.cs index 9ccfc052940..9cb343bf310 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Configuration.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Configuration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,17 +7,16 @@ namespace Microsoft { namespace Configuration { - // Generated from `Microsoft.Extensions.Configuration.ChainedBuilderExtensions` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ChainedBuilderExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddConfiguration(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder, Microsoft.Extensions.Configuration.IConfiguration config) => throw null; public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddConfiguration(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder, Microsoft.Extensions.Configuration.IConfiguration config, bool shouldDisposeConfiguration) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ChainedConfigurationProvider` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ChainedConfigurationProvider : Microsoft.Extensions.Configuration.IConfigurationProvider, System.IDisposable { public ChainedConfigurationProvider(Microsoft.Extensions.Configuration.ChainedConfigurationSource source) => throw null; + public Microsoft.Extensions.Configuration.IConfiguration Configuration { get => throw null; } public void Dispose() => throw null; public System.Collections.Generic.IEnumerable GetChildKeys(System.Collections.Generic.IEnumerable earlierKeys, string parentPath) => throw null; public Microsoft.Extensions.Primitives.IChangeToken GetReloadToken() => throw null; @@ -25,7 +25,6 @@ namespace Microsoft public bool TryGet(string key, out string value) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ChainedConfigurationSource` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ChainedConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; @@ -34,7 +33,6 @@ namespace Microsoft public bool ShouldDisposeConfiguration { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationBuilder` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationBuilder : Microsoft.Extensions.Configuration.IConfigurationBuilder { public Microsoft.Extensions.Configuration.IConfigurationBuilder Add(Microsoft.Extensions.Configuration.IConfigurationSource source) => throw null; @@ -44,7 +42,6 @@ namespace Microsoft public System.Collections.Generic.IList Sources { get => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationKeyComparer` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationKeyComparer : System.Collections.Generic.IComparer { public int Compare(string x, string y) => throw null; @@ -52,7 +49,6 @@ namespace Microsoft public static Microsoft.Extensions.Configuration.ConfigurationKeyComparer Instance { get => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationManager` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationManager : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationBuilder, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable { Microsoft.Extensions.Configuration.IConfigurationBuilder Microsoft.Extensions.Configuration.IConfigurationBuilder.Add(Microsoft.Extensions.Configuration.IConfigurationSource source) => throw null; @@ -66,10 +62,9 @@ namespace Microsoft System.Collections.Generic.IDictionary Microsoft.Extensions.Configuration.IConfigurationBuilder.Properties { get => throw null; } System.Collections.Generic.IEnumerable Microsoft.Extensions.Configuration.IConfigurationRoot.Providers { get => throw null; } void Microsoft.Extensions.Configuration.IConfigurationRoot.Reload() => throw null; - System.Collections.Generic.IList Microsoft.Extensions.Configuration.IConfigurationBuilder.Sources { get => throw null; } + public System.Collections.Generic.IList Sources { get => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationProvider` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConfigurationProvider : Microsoft.Extensions.Configuration.IConfigurationProvider { protected ConfigurationProvider() => throw null; @@ -83,7 +78,6 @@ namespace Microsoft public virtual bool TryGet(string key, out string value) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationReloadToken` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationReloadToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } @@ -93,7 +87,6 @@ namespace Microsoft public System.IDisposable RegisterChangeCallback(System.Action callback, object state) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationRoot` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationRoot : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationRoot, System.IDisposable { public ConfigurationRoot(System.Collections.Generic.IList providers) => throw null; @@ -106,7 +99,6 @@ namespace Microsoft public void Reload() => throw null; } - // Generated from `Microsoft.Extensions.Configuration.ConfigurationSection` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationSection : Microsoft.Extensions.Configuration.IConfiguration, Microsoft.Extensions.Configuration.IConfigurationSection { public ConfigurationSection(Microsoft.Extensions.Configuration.IConfigurationRoot root, string path) => throw null; @@ -119,14 +111,12 @@ namespace Microsoft public string Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Configuration.MemoryConfigurationBuilderExtensions` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MemoryConfigurationBuilderExtensions { public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddInMemoryCollection(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder) => throw null; public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddInMemoryCollection(this Microsoft.Extensions.Configuration.IConfigurationBuilder configurationBuilder, System.Collections.Generic.IEnumerable> initialData) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.StreamConfigurationProvider` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class StreamConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider { public override void Load() => throw null; @@ -135,7 +125,6 @@ namespace Microsoft public StreamConfigurationProvider(Microsoft.Extensions.Configuration.StreamConfigurationSource source) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.StreamConfigurationSource` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class StreamConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public abstract Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder); @@ -145,7 +134,6 @@ namespace Microsoft namespace Memory { - // Generated from `Microsoft.Extensions.Configuration.Memory.MemoryConfigurationProvider` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryConfigurationProvider : Microsoft.Extensions.Configuration.ConfigurationProvider, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public void Add(string key, string value) => throw null; @@ -154,7 +142,6 @@ namespace Microsoft public MemoryConfigurationProvider(Microsoft.Extensions.Configuration.Memory.MemoryConfigurationSource source) => throw null; } - // Generated from `Microsoft.Extensions.Configuration.Memory.MemoryConfigurationSource` in `Microsoft.Extensions.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MemoryConfigurationSource : Microsoft.Extensions.Configuration.IConfigurationSource { public Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.Abstractions.cs index 14241cca435..8d7706b9823 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.DependencyInjection.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ActivatorUtilities` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ActivatorUtilities { public static Microsoft.Extensions.DependencyInjection.ObjectFactory CreateFactory(System.Type instanceType, System.Type[] argumentTypes) => throw null; @@ -16,13 +16,11 @@ namespace Microsoft public static T GetServiceOrCreateInstance(System.IServiceProvider provider) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ActivatorUtilitiesConstructorAttribute` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ActivatorUtilitiesConstructorAttribute : System.Attribute { public ActivatorUtilitiesConstructorAttribute() => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.AsyncServiceScope` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct AsyncServiceScope : Microsoft.Extensions.DependencyInjection.IServiceScope, System.IAsyncDisposable, System.IDisposable { // Stub generator skipped constructor @@ -32,46 +30,38 @@ namespace Microsoft public System.IServiceProvider ServiceProvider { get => throw null; } } - // Generated from `Microsoft.Extensions.DependencyInjection.IServiceCollection` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { } - // Generated from `Microsoft.Extensions.DependencyInjection.IServiceProviderFactory<>` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceProviderFactory { TContainerBuilder CreateBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection services); System.IServiceProvider CreateServiceProvider(TContainerBuilder containerBuilder); } - // Generated from `Microsoft.Extensions.DependencyInjection.IServiceProviderIsService` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceProviderIsService { bool IsService(System.Type serviceType); } - // Generated from `Microsoft.Extensions.DependencyInjection.IServiceScope` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceScope : System.IDisposable { System.IServiceProvider ServiceProvider { get; } } - // Generated from `Microsoft.Extensions.DependencyInjection.IServiceScopeFactory` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IServiceScopeFactory { Microsoft.Extensions.DependencyInjection.IServiceScope CreateScope(); } - // Generated from `Microsoft.Extensions.DependencyInjection.ISupportRequiredService` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISupportRequiredService { object GetRequiredService(System.Type serviceType); } - // Generated from `Microsoft.Extensions.DependencyInjection.ObjectFactory` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public delegate object ObjectFactory(System.IServiceProvider serviceProvider, object[] arguments); - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceCollection` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceCollection : Microsoft.Extensions.DependencyInjection.IServiceCollection, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { void System.Collections.Generic.ICollection.Add(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) => throw null; @@ -85,12 +75,12 @@ namespace Microsoft public void Insert(int index, Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) => throw null; public bool IsReadOnly { get => throw null; } public Microsoft.Extensions.DependencyInjection.ServiceDescriptor this[int index] { get => throw null; set => throw null; } + public void MakeReadOnly() => throw null; public bool Remove(Microsoft.Extensions.DependencyInjection.ServiceDescriptor item) => throw null; public void RemoveAt(int index) => throw null; public ServiceCollection() => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceCollectionServiceExtensions` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServiceCollectionServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddScoped(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Type serviceType) => throw null; @@ -118,7 +108,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddTransient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, System.Func implementationFactory) where TService : class => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceDescriptor` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceDescriptor { public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Describe(System.Type serviceType, System.Func implementationFactory, Microsoft.Extensions.DependencyInjection.ServiceLifetime lifetime) => throw null; @@ -151,7 +140,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.ServiceDescriptor Transient(System.Func implementationFactory) where TService : class => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceLifetime` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ServiceLifetime : int { Scoped = 1, @@ -159,7 +147,6 @@ namespace Microsoft Transient = 2, } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServiceProviderServiceExtensions { public static Microsoft.Extensions.DependencyInjection.AsyncServiceScope CreateAsyncScope(this System.IServiceProvider provider) => throw null; @@ -174,7 +161,6 @@ namespace Microsoft namespace Extensions { - // Generated from `Microsoft.Extensions.DependencyInjection.Extensions.ServiceCollectionDescriptorExtensions` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServiceCollectionDescriptorExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection Add(this Microsoft.Extensions.DependencyInjection.IServiceCollection collection, System.Collections.Generic.IEnumerable descriptors) => throw null; @@ -211,20 +197,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'MemberNotNullAttribute' is not stubbed in this assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'MemberNotNullWhenAttribute' is not stubbed in this assembly 'Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.cs index f323c3cc0f2..d0a76b8f06f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.DependencyInjection.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.DependencyInjection, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory` in `Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultServiceProviderFactory : Microsoft.Extensions.DependencyInjection.IServiceProviderFactory { public Microsoft.Extensions.DependencyInjection.IServiceCollection CreateBuilder(Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -15,7 +15,6 @@ namespace Microsoft public DefaultServiceProviderFactory(Microsoft.Extensions.DependencyInjection.ServiceProviderOptions options) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions` in `Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServiceCollectionContainerBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -23,7 +22,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.ServiceProvider BuildServiceProvider(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, bool validateScopes) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceProvider` in `Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceProvider : System.IAsyncDisposable, System.IDisposable, System.IServiceProvider { public void Dispose() => throw null; @@ -31,7 +29,6 @@ namespace Microsoft public object GetService(System.Type serviceType) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceProviderOptions` in `Microsoft.Extensions.DependencyInjection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ServiceProviderOptions { public ServiceProviderOptions() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.cs index 849f0c761f7..36b8d407872 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,14 +9,12 @@ namespace Microsoft { namespace HealthChecks { - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckContext { public HealthCheckContext() => throw null; public Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckRegistration Registration { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckRegistration` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckRegistration { public System.Func Factory { get => throw null; set => throw null; } @@ -29,7 +28,6 @@ namespace Microsoft public System.TimeSpan Timeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct HealthCheckResult { public System.Collections.Generic.IReadOnlyDictionary Data { get => throw null; } @@ -43,7 +41,6 @@ namespace Microsoft public static Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult Unhealthy(string description = default(string), System.Exception exception = default(System.Exception), System.Collections.Generic.IReadOnlyDictionary data = default(System.Collections.Generic.IReadOnlyDictionary)) => throw null; } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthReport` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthReport { public System.Collections.Generic.IReadOnlyDictionary Entries { get => throw null; } @@ -53,7 +50,6 @@ namespace Microsoft public System.TimeSpan TotalDuration { get => throw null; } } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthReportEntry` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct HealthReportEntry { public System.Collections.Generic.IReadOnlyDictionary Data { get => throw null; } @@ -67,7 +63,6 @@ namespace Microsoft public System.Collections.Generic.IEnumerable Tags { get => throw null; } } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum HealthStatus : int { Degraded = 1, @@ -75,13 +70,11 @@ namespace Microsoft Unhealthy = 0, } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHealthCheck { System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheckPublisher` in `Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHealthCheckPublisher { System.Threading.Tasks.Task PublishAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthReport report, System.Threading.CancellationToken cancellationToken); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.cs index 82cc6e67f1f..7b0dead748d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Diagnostics.HealthChecks.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Diagnostics.HealthChecks, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,11 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.HealthCheckServiceCollectionExtensions` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HealthCheckServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddHealthChecks(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.HealthChecksBuilderAddCheckExtensions` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HealthChecksBuilderAddCheckExtensions { public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCheck(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string name, Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck instance, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus, System.Collections.Generic.IEnumerable tags) => throw null; @@ -25,7 +24,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddTypeActivatedCheck(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string name, params object[] args) where T : class, Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.HealthChecksBuilderDelegateExtensions` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HealthChecksBuilderDelegateExtensions { public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAsyncCheck(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string name, System.Func> check, System.Collections.Generic.IEnumerable tags) => throw null; @@ -38,7 +36,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCheck(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string name, System.Func check, System.Collections.Generic.IEnumerable tags = default(System.Collections.Generic.IEnumerable), System.TimeSpan? timeout = default(System.TimeSpan?)) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHealthChecksBuilder { Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder Add(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckRegistration registration); @@ -50,7 +47,6 @@ namespace Microsoft { namespace HealthChecks { - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckPublisherOptions` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckPublisherOptions { public System.TimeSpan Delay { get => throw null; set => throw null; } @@ -60,7 +56,6 @@ namespace Microsoft public System.TimeSpan Timeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckService` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HealthCheckService { public System.Threading.Tasks.Task CheckHealthAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -68,7 +63,6 @@ namespace Microsoft protected HealthCheckService() => throw null; } - // Generated from `Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckServiceOptions` in `Microsoft.Extensions.Diagnostics.HealthChecks, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HealthCheckServiceOptions { public HealthCheckServiceOptions() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Features.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Features.cs index 4d257c86a71..69563ef43fc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Features.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Features.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Features, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Features { - // Generated from `Microsoft.AspNetCore.Http.Features.FeatureCollection` in `Microsoft.Extensions.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FeatureCollection : Microsoft.AspNetCore.Http.Features.IFeatureCollection, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public FeatureCollection() => throw null; @@ -23,7 +23,12 @@ namespace Microsoft public void Set(TFeature instance) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.FeatureReference<>` in `Microsoft.Extensions.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public static class FeatureCollectionExtensions + { + public static object GetRequiredFeature(this Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection, System.Type key) => throw null; + public static TFeature GetRequiredFeature(this Microsoft.AspNetCore.Http.Features.IFeatureCollection featureCollection) => throw null; + } + public struct FeatureReference { public static Microsoft.AspNetCore.Http.Features.FeatureReference Default; @@ -32,7 +37,6 @@ namespace Microsoft public T Update(Microsoft.AspNetCore.Http.Features.IFeatureCollection features, T feature) => throw null; } - // Generated from `Microsoft.AspNetCore.Http.Features.FeatureReferences<>` in `Microsoft.Extensions.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FeatureReferences { public TCache Cache; @@ -46,7 +50,6 @@ namespace Microsoft public int Revision { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Http.Features.IFeatureCollection` in `Microsoft.Extensions.Features, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFeatureCollection : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { TFeature Get(); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Abstractions.cs index fda24f3b741..f09d2e0fc08 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.FileProviders.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,13 +7,11 @@ namespace Microsoft { namespace FileProviders { - // Generated from `Microsoft.Extensions.FileProviders.IDirectoryContents` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IDirectoryContents : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { bool Exists { get; } } - // Generated from `Microsoft.Extensions.FileProviders.IFileInfo` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFileInfo { System.IO.Stream CreateReadStream(); @@ -24,7 +23,6 @@ namespace Microsoft string PhysicalPath { get; } } - // Generated from `Microsoft.Extensions.FileProviders.IFileProvider` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IFileProvider { Microsoft.Extensions.FileProviders.IDirectoryContents GetDirectoryContents(string subpath); @@ -32,7 +30,6 @@ namespace Microsoft Microsoft.Extensions.Primitives.IChangeToken Watch(string filter); } - // Generated from `Microsoft.Extensions.FileProviders.NotFoundDirectoryContents` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NotFoundDirectoryContents : Microsoft.Extensions.FileProviders.IDirectoryContents, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public bool Exists { get => throw null; } @@ -42,7 +39,6 @@ namespace Microsoft public static Microsoft.Extensions.FileProviders.NotFoundDirectoryContents Singleton { get => throw null; } } - // Generated from `Microsoft.Extensions.FileProviders.NotFoundFileInfo` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NotFoundFileInfo : Microsoft.Extensions.FileProviders.IFileInfo { public System.IO.Stream CreateReadStream() => throw null; @@ -55,7 +51,6 @@ namespace Microsoft public string PhysicalPath { get => throw null; } } - // Generated from `Microsoft.Extensions.FileProviders.NullChangeToken` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullChangeToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } @@ -64,7 +59,6 @@ namespace Microsoft public static Microsoft.Extensions.FileProviders.NullChangeToken Singleton { get => throw null; } } - // Generated from `Microsoft.Extensions.FileProviders.NullFileProvider` in `Microsoft.Extensions.FileProviders.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullFileProvider : Microsoft.Extensions.FileProviders.IFileProvider { public Microsoft.Extensions.FileProviders.IDirectoryContents GetDirectoryContents(string subpath) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Composite.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Composite.cs index bfd688aeb90..de2b0bdd3fd 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Composite.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Composite.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.FileProviders.Composite, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace FileProviders { - // Generated from `Microsoft.Extensions.FileProviders.CompositeFileProvider` in `Microsoft.Extensions.FileProviders.Composite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeFileProvider : Microsoft.Extensions.FileProviders.IFileProvider { public CompositeFileProvider(System.Collections.Generic.IEnumerable fileProviders) => throw null; @@ -19,7 +19,6 @@ namespace Microsoft namespace Composite { - // Generated from `Microsoft.Extensions.FileProviders.Composite.CompositeDirectoryContents` in `Microsoft.Extensions.FileProviders.Composite, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeDirectoryContents : Microsoft.Extensions.FileProviders.IDirectoryContents, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public CompositeDirectoryContents(System.Collections.Generic.IList fileProviders, string subpath) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Embedded.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Embedded.cs index 45bc49754ea..98158803de5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Embedded.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Embedded.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.FileProviders.Embedded, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace FileProviders { - // Generated from `Microsoft.Extensions.FileProviders.EmbeddedFileProvider` in `Microsoft.Extensions.FileProviders.Embedded, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EmbeddedFileProvider : Microsoft.Extensions.FileProviders.IFileProvider { public EmbeddedFileProvider(System.Reflection.Assembly assembly) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.IChangeToken Watch(string pattern) => throw null; } - // Generated from `Microsoft.Extensions.FileProviders.ManifestEmbeddedFileProvider` in `Microsoft.Extensions.FileProviders.Embedded, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ManifestEmbeddedFileProvider : Microsoft.Extensions.FileProviders.IFileProvider { public System.Reflection.Assembly Assembly { get => throw null; } @@ -31,7 +30,6 @@ namespace Microsoft namespace Embedded { - // Generated from `Microsoft.Extensions.FileProviders.Embedded.EmbeddedResourceFileInfo` in `Microsoft.Extensions.FileProviders.Embedded, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EmbeddedResourceFileInfo : Microsoft.Extensions.FileProviders.IFileInfo { public System.IO.Stream CreateReadStream() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Physical.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Physical.cs index 5e0496a7efe..557246dd9f4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Physical.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileProviders.Physical.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.FileProviders.Physical, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace FileProviders { - // Generated from `Microsoft.Extensions.FileProviders.PhysicalFileProvider` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalFileProvider : Microsoft.Extensions.FileProviders.IFileProvider, System.IDisposable { public void Dispose() => throw null; @@ -24,7 +24,6 @@ namespace Microsoft namespace Internal { - // Generated from `Microsoft.Extensions.FileProviders.Internal.PhysicalDirectoryContents` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalDirectoryContents : Microsoft.Extensions.FileProviders.IDirectoryContents, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public bool Exists { get => throw null; } @@ -37,7 +36,6 @@ namespace Microsoft } namespace Physical { - // Generated from `Microsoft.Extensions.FileProviders.Physical.ExclusionFilters` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum ExclusionFilters : int { @@ -48,7 +46,6 @@ namespace Microsoft System = 4, } - // Generated from `Microsoft.Extensions.FileProviders.Physical.PhysicalDirectoryInfo` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalDirectoryInfo : Microsoft.Extensions.FileProviders.IFileInfo { public System.IO.Stream CreateReadStream() => throw null; @@ -61,7 +58,6 @@ namespace Microsoft public string PhysicalPath { get => throw null; } } - // Generated from `Microsoft.Extensions.FileProviders.Physical.PhysicalFileInfo` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalFileInfo : Microsoft.Extensions.FileProviders.IFileInfo { public System.IO.Stream CreateReadStream() => throw null; @@ -74,7 +70,6 @@ namespace Microsoft public string PhysicalPath { get => throw null; } } - // Generated from `Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhysicalFilesWatcher : System.IDisposable { public Microsoft.Extensions.Primitives.IChangeToken CreateFileChangeToken(string filter) => throw null; @@ -85,7 +80,6 @@ namespace Microsoft // ERR: Stub generator didn't handle member: ~PhysicalFilesWatcher } - // Generated from `Microsoft.Extensions.FileProviders.Physical.PollingFileChangeToken` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PollingFileChangeToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } @@ -94,7 +88,6 @@ namespace Microsoft public System.IDisposable RegisterChangeCallback(System.Action callback, object state) => throw null; } - // Generated from `Microsoft.Extensions.FileProviders.Physical.PollingWildCardChangeToken` in `Microsoft.Extensions.FileProviders.Physical, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PollingWildCardChangeToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileSystemGlobbing.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileSystemGlobbing.cs index 7e30563d837..17b83af8040 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileSystemGlobbing.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.FileSystemGlobbing.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.FileSystemGlobbing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace FileSystemGlobbing { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.FilePatternMatch` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FilePatternMatch : System.IEquatable { public bool Equals(Microsoft.Extensions.FileSystemGlobbing.FilePatternMatch other) => throw null; @@ -18,7 +18,6 @@ namespace Microsoft public string Stem { get => throw null; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.InMemoryDirectoryInfo` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class InMemoryDirectoryInfo : Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase { public override System.Collections.Generic.IEnumerable EnumerateFileSystemInfos() => throw null; @@ -30,7 +29,6 @@ namespace Microsoft public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase ParentDirectory { get => throw null; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Matcher` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Matcher { public virtual Microsoft.Extensions.FileSystemGlobbing.Matcher AddExclude(string pattern) => throw null; @@ -40,7 +38,6 @@ namespace Microsoft public Matcher(System.StringComparison comparisonType) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.MatcherExtensions` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class MatcherExtensions { public static void AddExcludePatterns(this Microsoft.Extensions.FileSystemGlobbing.Matcher matcher, params System.Collections.Generic.IEnumerable[] excludePatternsGroups) => throw null; @@ -52,7 +49,6 @@ namespace Microsoft public static Microsoft.Extensions.FileSystemGlobbing.PatternMatchingResult Match(this Microsoft.Extensions.FileSystemGlobbing.Matcher matcher, string rootDir, string file) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.PatternMatchingResult` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternMatchingResult { public System.Collections.Generic.IEnumerable Files { get => throw null; set => throw null; } @@ -63,7 +59,6 @@ namespace Microsoft namespace Abstractions { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class DirectoryInfoBase : Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileSystemInfoBase { protected DirectoryInfoBase() => throw null; @@ -72,7 +67,6 @@ namespace Microsoft public abstract Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase GetFile(string path); } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoWrapper` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DirectoryInfoWrapper : Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase { public DirectoryInfoWrapper(System.IO.DirectoryInfo directoryInfo) => throw null; @@ -84,13 +78,11 @@ namespace Microsoft public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase ParentDirectory { get => throw null; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FileInfoBase : Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileSystemInfoBase { protected FileInfoBase() => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoWrapper` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class FileInfoWrapper : Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase { public FileInfoWrapper(System.IO.FileInfo fileInfo) => throw null; @@ -99,7 +91,6 @@ namespace Microsoft public override Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase ParentDirectory { get => throw null; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileSystemInfoBase` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class FileSystemInfoBase { protected FileSystemInfoBase() => throw null; @@ -111,27 +102,23 @@ namespace Microsoft } namespace Internal { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.ILinearPattern` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILinearPattern : Microsoft.Extensions.FileSystemGlobbing.Internal.IPattern { System.Collections.Generic.IList Segments { get; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPathSegment { bool CanProduceStem { get; } bool Match(string value); } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.IPattern` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPattern { Microsoft.Extensions.FileSystemGlobbing.Internal.IPatternContext CreatePatternContextForExclude(); Microsoft.Extensions.FileSystemGlobbing.Internal.IPatternContext CreatePatternContextForInclude(); } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.IPatternContext` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPatternContext { void Declare(System.Action onDeclare); @@ -141,7 +128,6 @@ namespace Microsoft Microsoft.Extensions.FileSystemGlobbing.Internal.PatternTestResult Test(Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase file); } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.IRaggedPattern` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRaggedPattern : Microsoft.Extensions.FileSystemGlobbing.Internal.IPattern { System.Collections.Generic.IList> Contains { get; } @@ -150,14 +136,12 @@ namespace Microsoft System.Collections.Generic.IList StartsWith { get; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.MatcherContext` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MatcherContext { public Microsoft.Extensions.FileSystemGlobbing.PatternMatchingResult Execute() => throw null; public MatcherContext(System.Collections.Generic.IEnumerable includePatterns, System.Collections.Generic.IEnumerable excludePatterns, Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase directoryInfo, System.StringComparison comparison) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternTestResult` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct PatternTestResult { public static Microsoft.Extensions.FileSystemGlobbing.Internal.PatternTestResult Failed; @@ -169,7 +153,6 @@ namespace Microsoft namespace PathSegments { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments.CurrentPathSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CurrentPathSegment : Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment { public bool CanProduceStem { get => throw null; } @@ -177,7 +160,6 @@ namespace Microsoft public bool Match(string value) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments.LiteralPathSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LiteralPathSegment : Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment { public bool CanProduceStem { get => throw null; } @@ -188,7 +170,6 @@ namespace Microsoft public string Value { get => throw null; } } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments.ParentPathSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ParentPathSegment : Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment { public bool CanProduceStem { get => throw null; } @@ -196,7 +177,6 @@ namespace Microsoft public ParentPathSegment() => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments.RecursiveWildcardSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RecursiveWildcardSegment : Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment { public bool CanProduceStem { get => throw null; } @@ -204,7 +184,6 @@ namespace Microsoft public RecursiveWildcardSegment() => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PathSegments.WildcardPathSegment` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WildcardPathSegment : Microsoft.Extensions.FileSystemGlobbing.Internal.IPathSegment { public string BeginsWith { get => throw null; } @@ -219,8 +198,7 @@ namespace Microsoft } namespace PatternContexts { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContext<>` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public abstract class PatternContext : Microsoft.Extensions.FileSystemGlobbing.Internal.IPatternContext + public abstract class PatternContext : Microsoft.Extensions.FileSystemGlobbing.Internal.IPatternContext where TFrame : struct { public virtual void Declare(System.Action declare) => throw null; protected TFrame Frame; @@ -233,10 +211,8 @@ namespace Microsoft public abstract Microsoft.Extensions.FileSystemGlobbing.Internal.PatternTestResult Test(Microsoft.Extensions.FileSystemGlobbing.Abstractions.FileInfoBase file); } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinear` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PatternContextLinear : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContext { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinear+FrameData` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FrameData { // Stub generator skipped constructor @@ -257,14 +233,12 @@ namespace Microsoft protected bool TestMatchingSegment(string value) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinearExclude` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternContextLinearExclude : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinear { public PatternContextLinearExclude(Microsoft.Extensions.FileSystemGlobbing.Internal.ILinearPattern pattern) : base(default(Microsoft.Extensions.FileSystemGlobbing.Internal.ILinearPattern)) => throw null; public override bool Test(Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase directory) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinearInclude` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternContextLinearInclude : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextLinear { public override void Declare(System.Action onDeclare) => throw null; @@ -272,10 +246,8 @@ namespace Microsoft public override bool Test(Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase directory) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRagged` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PatternContextRagged : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContext { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRagged+FrameData` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct FrameData { public int BacktrackAvailable; @@ -302,14 +274,12 @@ namespace Microsoft protected bool TestMatchingSegment(string value) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRaggedExclude` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternContextRaggedExclude : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRagged { public PatternContextRaggedExclude(Microsoft.Extensions.FileSystemGlobbing.Internal.IRaggedPattern pattern) : base(default(Microsoft.Extensions.FileSystemGlobbing.Internal.IRaggedPattern)) => throw null; public override bool Test(Microsoft.Extensions.FileSystemGlobbing.Abstractions.DirectoryInfoBase directory) => throw null; } - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRaggedInclude` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternContextRaggedInclude : Microsoft.Extensions.FileSystemGlobbing.Internal.PatternContexts.PatternContextRagged { public override void Declare(System.Action onDeclare) => throw null; @@ -320,7 +290,6 @@ namespace Microsoft } namespace Patterns { - // Generated from `Microsoft.Extensions.FileSystemGlobbing.Internal.Patterns.PatternBuilder` in `Microsoft.Extensions.FileSystemGlobbing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PatternBuilder { public Microsoft.Extensions.FileSystemGlobbing.Internal.IPattern Build(string pattern) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.Abstractions.cs index 046a467725d..47adebded54 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Hosting.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.ServiceCollectionHostedServiceExtensions` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ServiceCollectionHostedServiceExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHostedService(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where THostedService : class, Microsoft.Extensions.Hosting.IHostedService => throw null; @@ -16,7 +16,6 @@ namespace Microsoft } namespace Hosting { - // Generated from `Microsoft.Extensions.Hosting.BackgroundService` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class BackgroundService : Microsoft.Extensions.Hosting.IHostedService, System.IDisposable { protected BackgroundService() => throw null; @@ -27,7 +26,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.EnvironmentName` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EnvironmentName { public static string Development; @@ -35,7 +33,6 @@ namespace Microsoft public static string Staging; } - // Generated from `Microsoft.Extensions.Hosting.Environments` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Environments { public static string Development; @@ -43,7 +40,13 @@ namespace Microsoft public static string Staging; } - // Generated from `Microsoft.Extensions.Hosting.HostBuilderContext` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HostAbortedException : System.Exception + { + public HostAbortedException() => throw null; + public HostAbortedException(string message) => throw null; + public HostAbortedException(string message, System.Exception innerException) => throw null; + } + public class HostBuilderContext { public Microsoft.Extensions.Configuration.IConfiguration Configuration { get => throw null; set => throw null; } @@ -52,7 +55,6 @@ namespace Microsoft public System.Collections.Generic.IDictionary Properties { get => throw null; } } - // Generated from `Microsoft.Extensions.Hosting.HostDefaults` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostDefaults { public static string ApplicationKey; @@ -60,7 +62,6 @@ namespace Microsoft public static string EnvironmentKey; } - // Generated from `Microsoft.Extensions.Hosting.HostEnvironmentEnvExtensions` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostEnvironmentEnvExtensions { public static bool IsDevelopment(this Microsoft.Extensions.Hosting.IHostEnvironment hostEnvironment) => throw null; @@ -69,14 +70,12 @@ namespace Microsoft public static bool IsStaging(this Microsoft.Extensions.Hosting.IHostEnvironment hostEnvironment) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.HostingAbstractionsHostBuilderExtensions` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostingAbstractionsHostBuilderExtensions { public static Microsoft.Extensions.Hosting.IHost Start(this Microsoft.Extensions.Hosting.IHostBuilder hostBuilder) => throw null; public static System.Threading.Tasks.Task StartAsync(this Microsoft.Extensions.Hosting.IHostBuilder hostBuilder, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostingAbstractionsHostExtensions { public static void Run(this Microsoft.Extensions.Hosting.IHost host) => throw null; @@ -87,7 +86,6 @@ namespace Microsoft public static System.Threading.Tasks.Task WaitForShutdownAsync(this Microsoft.Extensions.Hosting.IHost host, System.Threading.CancellationToken token = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.HostingEnvironmentExtensions` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostingEnvironmentExtensions { public static bool IsDevelopment(this Microsoft.Extensions.Hosting.IHostingEnvironment hostingEnvironment) => throw null; @@ -96,7 +94,6 @@ namespace Microsoft public static bool IsStaging(this Microsoft.Extensions.Hosting.IHostingEnvironment hostingEnvironment) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.IApplicationLifetime` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IApplicationLifetime { System.Threading.CancellationToken ApplicationStarted { get; } @@ -105,7 +102,6 @@ namespace Microsoft void StopApplication(); } - // Generated from `Microsoft.Extensions.Hosting.IHost` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHost : System.IDisposable { System.IServiceProvider Services { get; } @@ -113,7 +109,6 @@ namespace Microsoft System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.Extensions.Hosting.IHostApplicationLifetime` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostApplicationLifetime { System.Threading.CancellationToken ApplicationStarted { get; } @@ -122,7 +117,6 @@ namespace Microsoft void StopApplication(); } - // Generated from `Microsoft.Extensions.Hosting.IHostBuilder` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostBuilder { Microsoft.Extensions.Hosting.IHost Build(); @@ -135,7 +129,6 @@ namespace Microsoft Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory); } - // Generated from `Microsoft.Extensions.Hosting.IHostEnvironment` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostEnvironment { string ApplicationName { get; set; } @@ -144,21 +137,18 @@ namespace Microsoft string EnvironmentName { get; set; } } - // Generated from `Microsoft.Extensions.Hosting.IHostLifetime` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostLifetime { System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken); System.Threading.Tasks.Task WaitForStartAsync(System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.Extensions.Hosting.IHostedService` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostedService { System.Threading.Tasks.Task StartAsync(System.Threading.CancellationToken cancellationToken); System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.Extensions.Hosting.IHostingEnvironment` in `Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHostingEnvironment { string ApplicationName { get; set; } @@ -170,16 +160,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.cs index 8dc9909fe94..8e078972865 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Hosting.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Hosting, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.OptionsBuilderExtensions` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsBuilderExtensions { public static Microsoft.Extensions.Options.OptionsBuilder ValidateOnStart(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder) where TOptions : class => throw null; @@ -15,28 +15,50 @@ namespace Microsoft } namespace Hosting { - // Generated from `Microsoft.Extensions.Hosting.BackgroundServiceExceptionBehavior` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum BackgroundServiceExceptionBehavior : int { Ignore = 1, StopHost = 0, } - // Generated from `Microsoft.Extensions.Hosting.ConsoleLifetimeOptions` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsoleLifetimeOptions { public ConsoleLifetimeOptions() => throw null; public bool SuppressStatusMessages { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Hosting.Host` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Host { + public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder() => throw null; + public static Microsoft.Extensions.Hosting.HostApplicationBuilder CreateApplicationBuilder(string[] args) => throw null; public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder() => throw null; public static Microsoft.Extensions.Hosting.IHostBuilder CreateDefaultBuilder(string[] args) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.HostBuilder` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public class HostApplicationBuilder + { + public Microsoft.Extensions.Hosting.IHost Build() => throw null; + public Microsoft.Extensions.Configuration.ConfigurationManager Configuration { get => throw null; } + public void ConfigureContainer(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory, System.Action configure = default(System.Action)) => throw null; + public Microsoft.Extensions.Hosting.IHostEnvironment Environment { get => throw null; } + public HostApplicationBuilder() => throw null; + public HostApplicationBuilder(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings settings) => throw null; + public HostApplicationBuilder(string[] args) => throw null; + public Microsoft.Extensions.Logging.ILoggingBuilder Logging { get => throw null; } + public Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get => throw null; } + } + + public class HostApplicationBuilderSettings + { + public string ApplicationName { get => throw null; set => throw null; } + public string[] Args { get => throw null; set => throw null; } + public Microsoft.Extensions.Configuration.ConfigurationManager Configuration { get => throw null; set => throw null; } + public string ContentRootPath { get => throw null; set => throw null; } + public bool DisableDefaults { get => throw null; set => throw null; } + public string EnvironmentName { get => throw null; set => throw null; } + public HostApplicationBuilderSettings() => throw null; + } + public class HostBuilder : Microsoft.Extensions.Hosting.IHostBuilder { public Microsoft.Extensions.Hosting.IHost Build() => throw null; @@ -50,7 +72,6 @@ namespace Microsoft public Microsoft.Extensions.Hosting.IHostBuilder UseServiceProviderFactory(Microsoft.Extensions.DependencyInjection.IServiceProviderFactory factory) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.HostOptions` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostOptions { public Microsoft.Extensions.Hosting.BackgroundServiceExceptionBehavior BackgroundServiceExceptionBehavior { get => throw null; set => throw null; } @@ -58,7 +79,6 @@ namespace Microsoft public System.TimeSpan ShutdownTimeout { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Hosting.HostingHostBuilderExtensions` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HostingHostBuilderExtensions { public static Microsoft.Extensions.Hosting.IHostBuilder ConfigureAppConfiguration(this Microsoft.Extensions.Hosting.IHostBuilder hostBuilder, System.Action configureDelegate) => throw null; @@ -81,7 +101,6 @@ namespace Microsoft namespace Internal { - // Generated from `Microsoft.Extensions.Hosting.Internal.ApplicationLifetime` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ApplicationLifetime : Microsoft.Extensions.Hosting.IApplicationLifetime, Microsoft.Extensions.Hosting.IHostApplicationLifetime { public ApplicationLifetime(Microsoft.Extensions.Logging.ILogger logger) => throw null; @@ -93,7 +112,6 @@ namespace Microsoft public void StopApplication() => throw null; } - // Generated from `Microsoft.Extensions.Hosting.Internal.ConsoleLifetime` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsoleLifetime : Microsoft.Extensions.Hosting.IHostLifetime, System.IDisposable { public ConsoleLifetime(Microsoft.Extensions.Options.IOptions options, Microsoft.Extensions.Hosting.IHostEnvironment environment, Microsoft.Extensions.Hosting.IHostApplicationLifetime applicationLifetime, Microsoft.Extensions.Options.IOptions hostOptions) => throw null; @@ -103,7 +121,6 @@ namespace Microsoft public System.Threading.Tasks.Task WaitForStartAsync(System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.Extensions.Hosting.Internal.HostingEnvironment` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HostingEnvironment : Microsoft.Extensions.Hosting.IHostEnvironment, Microsoft.Extensions.Hosting.IHostingEnvironment { public string ApplicationName { get => throw null; set => throw null; } @@ -117,34 +134,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } - namespace Runtime - { - namespace Versioning - { - /* Duplicate type 'OSPlatformAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'SupportedOSPlatformAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'SupportedOSPlatformGuardAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'TargetPlatformAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'UnsupportedOSPlatformAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'UnsupportedOSPlatformGuardAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Http.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Http.cs index 1129a90710b..64f9e39c787 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Http.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Http.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Http, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpClientBuilderExtensions { public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder AddHttpMessageHandler(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.Func configureHandler) => throw null; @@ -27,7 +27,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder SetHandlerLifetime(this Microsoft.Extensions.DependencyInjection.IHttpClientBuilder builder, System.TimeSpan handlerLifetime) => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.HttpClientFactoryServiceCollectionExtensions` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpClientFactoryServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddHttpClient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -52,7 +51,6 @@ namespace Microsoft public static Microsoft.Extensions.DependencyInjection.IHttpClientBuilder AddHttpClient(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, string name, System.Action configureClient) where TClient : class => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.IHttpClientBuilder` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpClientBuilder { string Name { get; } @@ -62,7 +60,6 @@ namespace Microsoft } namespace Http { - // Generated from `Microsoft.Extensions.Http.HttpClientFactoryOptions` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HttpClientFactoryOptions { public System.TimeSpan HandlerLifetime { get => throw null; set => throw null; } @@ -73,7 +70,6 @@ namespace Microsoft public bool SuppressHandlerScope { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Http.HttpMessageHandlerBuilder` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class HttpMessageHandlerBuilder { public abstract System.Collections.Generic.IList AdditionalHandlers { get; } @@ -85,13 +81,11 @@ namespace Microsoft public virtual System.IServiceProvider Services { get => throw null; } } - // Generated from `Microsoft.Extensions.Http.IHttpMessageHandlerBuilderFilter` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpMessageHandlerBuilderFilter { System.Action Configure(System.Action next); } - // Generated from `Microsoft.Extensions.Http.ITypedHttpClientFactory<>` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ITypedHttpClientFactory { TClient CreateClient(System.Net.Http.HttpClient httpClient); @@ -99,7 +93,6 @@ namespace Microsoft namespace Logging { - // Generated from `Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggingHttpMessageHandler : System.Net.Http.DelegatingHandler { public LoggingHttpMessageHandler(Microsoft.Extensions.Logging.ILogger logger) => throw null; @@ -107,7 +100,6 @@ namespace Microsoft protected internal override System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggingScopeHttpMessageHandler : System.Net.Http.DelegatingHandler { public LoggingScopeHttpMessageHandler(Microsoft.Extensions.Logging.ILogger logger) => throw null; @@ -121,39 +113,25 @@ namespace Microsoft } namespace System { - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } namespace Net { namespace Http { - // Generated from `System.Net.Http.HttpClientFactoryExtensions` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpClientFactoryExtensions { public static System.Net.Http.HttpClient CreateClient(this System.Net.Http.IHttpClientFactory factory) => throw null; } - // Generated from `System.Net.Http.HttpMessageHandlerFactoryExtensions` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HttpMessageHandlerFactoryExtensions { public static System.Net.Http.HttpMessageHandler CreateHandler(this System.Net.Http.IHttpMessageHandlerFactory factory) => throw null; } - // Generated from `System.Net.Http.IHttpClientFactory` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpClientFactory { System.Net.Http.HttpClient CreateClient(string name); } - // Generated from `System.Net.Http.IHttpMessageHandlerFactory` in `Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IHttpMessageHandlerFactory { System.Net.Http.HttpMessageHandler CreateHandler(string name); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Core.cs index ae9a9d1d87e..f4ad09fbca6 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Core.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Identity.Core, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Identity { - // Generated from `Microsoft.AspNetCore.Identity.AuthenticatorTokenProvider<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class AuthenticatorTokenProvider : Microsoft.AspNetCore.Identity.IUserTwoFactorTokenProvider where TUser : class { public AuthenticatorTokenProvider() => throw null; @@ -15,7 +15,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidateAsync(string purpose, string token, Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.ClaimsIdentityOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ClaimsIdentityOptions { public ClaimsIdentityOptions() => throw null; @@ -26,7 +25,6 @@ namespace Microsoft public string UserNameClaimType { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.DefaultPersonalDataProtector` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultPersonalDataProtector : Microsoft.AspNetCore.Identity.IPersonalDataProtector { public DefaultPersonalDataProtector(Microsoft.AspNetCore.Identity.ILookupProtectorKeyRing keyRing, Microsoft.AspNetCore.Identity.ILookupProtector protector) => throw null; @@ -34,14 +32,12 @@ namespace Microsoft public virtual string Unprotect(string data) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.DefaultUserConfirmation<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultUserConfirmation : Microsoft.AspNetCore.Identity.IUserConfirmation where TUser : class { public DefaultUserConfirmation() => throw null; public virtual System.Threading.Tasks.Task IsConfirmedAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.EmailTokenProvider<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EmailTokenProvider : Microsoft.AspNetCore.Identity.TotpSecurityStampBasedTokenProvider where TUser : class { public override System.Threading.Tasks.Task CanGenerateTwoFactorTokenAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; @@ -49,21 +45,18 @@ namespace Microsoft public override System.Threading.Tasks.Task GetUserModifierAsync(string purpose, Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.ILookupNormalizer` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILookupNormalizer { string NormalizeEmail(string email); string NormalizeName(string name); } - // Generated from `Microsoft.AspNetCore.Identity.ILookupProtector` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILookupProtector { string Protect(string keyId, string data); string Unprotect(string keyId, string data); } - // Generated from `Microsoft.AspNetCore.Identity.ILookupProtectorKeyRing` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILookupProtectorKeyRing { string CurrentKeyId { get; } @@ -71,44 +64,37 @@ namespace Microsoft string this[string keyId] { get; } } - // Generated from `Microsoft.AspNetCore.Identity.IPasswordHasher<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPasswordHasher where TUser : class { string HashPassword(TUser user, string password); Microsoft.AspNetCore.Identity.PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword); } - // Generated from `Microsoft.AspNetCore.Identity.IPasswordValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPasswordValidator where TUser : class { System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user, string password); } - // Generated from `Microsoft.AspNetCore.Identity.IPersonalDataProtector` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPersonalDataProtector { string Protect(string data); string Unprotect(string data); } - // Generated from `Microsoft.AspNetCore.Identity.IProtectedUserStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IProtectedUserStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { } - // Generated from `Microsoft.AspNetCore.Identity.IQueryableRoleStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IQueryableRoleStore : Microsoft.AspNetCore.Identity.IRoleStore, System.IDisposable where TRole : class { System.Linq.IQueryable Roles { get; } } - // Generated from `Microsoft.AspNetCore.Identity.IQueryableUserStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IQueryableUserStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Linq.IQueryable Users { get; } } - // Generated from `Microsoft.AspNetCore.Identity.IRoleClaimStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRoleClaimStore : Microsoft.AspNetCore.Identity.IRoleStore, System.IDisposable where TRole : class { System.Threading.Tasks.Task AddClaimAsync(TRole role, System.Security.Claims.Claim claim, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -116,7 +102,6 @@ namespace Microsoft System.Threading.Tasks.Task RemoveClaimAsync(TRole role, System.Security.Claims.Claim claim, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Identity.IRoleStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRoleStore : System.IDisposable where TRole : class { System.Threading.Tasks.Task CreateAsync(TRole role, System.Threading.CancellationToken cancellationToken); @@ -131,13 +116,11 @@ namespace Microsoft System.Threading.Tasks.Task UpdateAsync(TRole role, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IRoleValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IRoleValidator where TRole : class { System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Identity.RoleManager manager, TRole role); } - // Generated from `Microsoft.AspNetCore.Identity.IUserAuthenticationTokenStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserAuthenticationTokenStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetTokenAsync(TUser user, string loginProvider, string name, System.Threading.CancellationToken cancellationToken); @@ -145,14 +128,12 @@ namespace Microsoft System.Threading.Tasks.Task SetTokenAsync(TUser user, string loginProvider, string name, string value, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserAuthenticatorKeyStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserAuthenticatorKeyStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetAuthenticatorKeyAsync(TUser user, System.Threading.CancellationToken cancellationToken); System.Threading.Tasks.Task SetAuthenticatorKeyAsync(TUser user, string key, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserClaimStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserClaimStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task AddClaimsAsync(TUser user, System.Collections.Generic.IEnumerable claims, System.Threading.CancellationToken cancellationToken); @@ -162,19 +143,16 @@ namespace Microsoft System.Threading.Tasks.Task ReplaceClaimAsync(TUser user, System.Security.Claims.Claim claim, System.Security.Claims.Claim newClaim, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserClaimsPrincipalFactory where TUser : class { System.Threading.Tasks.Task CreateAsync(TUser user); } - // Generated from `Microsoft.AspNetCore.Identity.IUserConfirmation<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserConfirmation where TUser : class { System.Threading.Tasks.Task IsConfirmedAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user); } - // Generated from `Microsoft.AspNetCore.Identity.IUserEmailStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserEmailStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task FindByEmailAsync(string normalizedEmail, System.Threading.CancellationToken cancellationToken); @@ -186,7 +164,6 @@ namespace Microsoft System.Threading.Tasks.Task SetNormalizedEmailAsync(TUser user, string normalizedEmail, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserLockoutStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserLockoutStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetAccessFailedCountAsync(TUser user, System.Threading.CancellationToken cancellationToken); @@ -198,7 +175,6 @@ namespace Microsoft System.Threading.Tasks.Task SetLockoutEndDateAsync(TUser user, System.DateTimeOffset? lockoutEnd, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserLoginStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserLoginStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task AddLoginAsync(TUser user, Microsoft.AspNetCore.Identity.UserLoginInfo login, System.Threading.CancellationToken cancellationToken); @@ -207,7 +183,6 @@ namespace Microsoft System.Threading.Tasks.Task RemoveLoginAsync(TUser user, string loginProvider, string providerKey, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserPasswordStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserPasswordStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetPasswordHashAsync(TUser user, System.Threading.CancellationToken cancellationToken); @@ -215,7 +190,6 @@ namespace Microsoft System.Threading.Tasks.Task SetPasswordHashAsync(TUser user, string passwordHash, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserPhoneNumberStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserPhoneNumberStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetPhoneNumberAsync(TUser user, System.Threading.CancellationToken cancellationToken); @@ -224,7 +198,6 @@ namespace Microsoft System.Threading.Tasks.Task SetPhoneNumberConfirmedAsync(TUser user, bool confirmed, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserRoleStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserRoleStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task AddToRoleAsync(TUser user, string roleName, System.Threading.CancellationToken cancellationToken); @@ -234,14 +207,12 @@ namespace Microsoft System.Threading.Tasks.Task RemoveFromRoleAsync(TUser user, string roleName, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserSecurityStampStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserSecurityStampStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetSecurityStampAsync(TUser user, System.Threading.CancellationToken cancellationToken); System.Threading.Tasks.Task SetSecurityStampAsync(TUser user, string stamp, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserStore : System.IDisposable where TUser : class { System.Threading.Tasks.Task CreateAsync(TUser user, System.Threading.CancellationToken cancellationToken); @@ -256,7 +227,6 @@ namespace Microsoft System.Threading.Tasks.Task UpdateAsync(TUser user, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserTwoFactorRecoveryCodeStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserTwoFactorRecoveryCodeStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task CountCodesAsync(TUser user, System.Threading.CancellationToken cancellationToken); @@ -264,14 +234,12 @@ namespace Microsoft System.Threading.Tasks.Task ReplaceCodesAsync(TUser user, System.Collections.Generic.IEnumerable recoveryCodes, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserTwoFactorStore<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserTwoFactorStore : Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TUser : class { System.Threading.Tasks.Task GetTwoFactorEnabledAsync(TUser user, System.Threading.CancellationToken cancellationToken); System.Threading.Tasks.Task SetTwoFactorEnabledAsync(TUser user, bool enabled, System.Threading.CancellationToken cancellationToken); } - // Generated from `Microsoft.AspNetCore.Identity.IUserTwoFactorTokenProvider<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserTwoFactorTokenProvider where TUser : class { System.Threading.Tasks.Task CanGenerateTwoFactorTokenAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user); @@ -279,13 +247,11 @@ namespace Microsoft System.Threading.Tasks.Task ValidateAsync(string purpose, string token, Microsoft.AspNetCore.Identity.UserManager manager, TUser user); } - // Generated from `Microsoft.AspNetCore.Identity.IUserValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IUserValidator where TUser : class { System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user); } - // Generated from `Microsoft.AspNetCore.Identity.IdentityBuilder` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityBuilder { public virtual Microsoft.AspNetCore.Identity.IdentityBuilder AddClaimsPrincipalFactory() where TFactory : class => throw null; @@ -309,7 +275,6 @@ namespace Microsoft public System.Type UserType { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityError` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityError { public string Code { get => throw null; set => throw null; } @@ -317,7 +282,6 @@ namespace Microsoft public IdentityError() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityErrorDescriber` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityErrorDescriber { public virtual Microsoft.AspNetCore.Identity.IdentityError ConcurrencyFailure() => throw null; @@ -345,7 +309,6 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Identity.IdentityError UserNotInRole(string role) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityOptions { public Microsoft.AspNetCore.Identity.ClaimsIdentityOptions ClaimsIdentity { get => throw null; set => throw null; } @@ -358,7 +321,6 @@ namespace Microsoft public Microsoft.AspNetCore.Identity.UserOptions User { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityResult` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityResult { public System.Collections.Generic.IEnumerable Errors { get => throw null; } @@ -369,7 +331,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.LockoutOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LockoutOptions { public bool AllowedForNewUsers { get => throw null; set => throw null; } @@ -378,7 +339,6 @@ namespace Microsoft public int MaxFailedAccessAttempts { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.PasswordHasher<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PasswordHasher : Microsoft.AspNetCore.Identity.IPasswordHasher where TUser : class { public virtual string HashPassword(TUser user, string password) => throw null; @@ -386,14 +346,12 @@ namespace Microsoft public virtual Microsoft.AspNetCore.Identity.PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.PasswordHasherCompatibilityMode` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum PasswordHasherCompatibilityMode : int { IdentityV2 = 0, IdentityV3 = 1, } - // Generated from `Microsoft.AspNetCore.Identity.PasswordHasherOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PasswordHasherOptions { public Microsoft.AspNetCore.Identity.PasswordHasherCompatibilityMode CompatibilityMode { get => throw null; set => throw null; } @@ -401,7 +359,6 @@ namespace Microsoft public PasswordHasherOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.PasswordOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PasswordOptions { public PasswordOptions() => throw null; @@ -413,7 +370,6 @@ namespace Microsoft public int RequiredUniqueChars { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.PasswordValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PasswordValidator : Microsoft.AspNetCore.Identity.IPasswordValidator where TUser : class { public Microsoft.AspNetCore.Identity.IdentityErrorDescriber Describer { get => throw null; } @@ -425,7 +381,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user, string password) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.PasswordVerificationResult` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum PasswordVerificationResult : int { Failed = 0, @@ -433,13 +388,11 @@ namespace Microsoft SuccessRehashNeeded = 2, } - // Generated from `Microsoft.AspNetCore.Identity.PersonalDataAttribute` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PersonalDataAttribute : System.Attribute { public PersonalDataAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.PhoneNumberTokenProvider<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PhoneNumberTokenProvider : Microsoft.AspNetCore.Identity.TotpSecurityStampBasedTokenProvider where TUser : class { public override System.Threading.Tasks.Task CanGenerateTwoFactorTokenAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; @@ -447,13 +400,11 @@ namespace Microsoft public PhoneNumberTokenProvider() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.ProtectedPersonalDataAttribute` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProtectedPersonalDataAttribute : Microsoft.AspNetCore.Identity.PersonalDataAttribute { public ProtectedPersonalDataAttribute() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.RoleManager<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoleManager : System.IDisposable where TRole : class { public virtual System.Threading.Tasks.Task AddClaimAsync(TRole role, System.Security.Claims.Claim claim) => throw null; @@ -487,14 +438,12 @@ namespace Microsoft protected virtual System.Threading.Tasks.Task ValidateRoleAsync(TRole role) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.RoleValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RoleValidator : Microsoft.AspNetCore.Identity.IRoleValidator where TRole : class { public RoleValidator(Microsoft.AspNetCore.Identity.IdentityErrorDescriber errors = default(Microsoft.AspNetCore.Identity.IdentityErrorDescriber)) => throw null; public virtual System.Threading.Tasks.Task ValidateAsync(Microsoft.AspNetCore.Identity.RoleManager manager, TRole role) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.SignInOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SignInOptions { public bool RequireConfirmedAccount { get => throw null; set => throw null; } @@ -503,7 +452,6 @@ namespace Microsoft public SignInOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.SignInResult` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SignInResult { public static Microsoft.AspNetCore.Identity.SignInResult Failed { get => throw null; } @@ -519,7 +467,6 @@ namespace Microsoft public static Microsoft.AspNetCore.Identity.SignInResult TwoFactorRequired { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.StoreOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StoreOptions { public int MaxLengthForKeys { get => throw null; set => throw null; } @@ -527,7 +474,6 @@ namespace Microsoft public StoreOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.TokenOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TokenOptions { public string AuthenticatorIssuer { get => throw null; set => throw null; } @@ -544,7 +490,6 @@ namespace Microsoft public TokenOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.TokenProviderDescriptor` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TokenProviderDescriptor { public object ProviderInstance { get => throw null; set => throw null; } @@ -552,7 +497,6 @@ namespace Microsoft public TokenProviderDescriptor(System.Type type) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.TotpSecurityStampBasedTokenProvider<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class TotpSecurityStampBasedTokenProvider : Microsoft.AspNetCore.Identity.IUserTwoFactorTokenProvider where TUser : class { public abstract System.Threading.Tasks.Task CanGenerateTwoFactorTokenAsync(Microsoft.AspNetCore.Identity.UserManager manager, TUser user); @@ -562,7 +506,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task ValidateAsync(string purpose, string token, Microsoft.AspNetCore.Identity.UserManager manager, TUser user) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UpperInvariantLookupNormalizer` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UpperInvariantLookupNormalizer : Microsoft.AspNetCore.Identity.ILookupNormalizer { public string NormalizeEmail(string email) => throw null; @@ -570,7 +513,6 @@ namespace Microsoft public UpperInvariantLookupNormalizer() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory<,>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserClaimsPrincipalFactory : Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory where TRole : class where TUser : class { protected override System.Threading.Tasks.Task GenerateClaimsAsync(TUser user) => throw null; @@ -578,7 +520,6 @@ namespace Microsoft public UserClaimsPrincipalFactory(Microsoft.AspNetCore.Identity.UserManager userManager, Microsoft.AspNetCore.Identity.RoleManager roleManager, Microsoft.Extensions.Options.IOptions options) : base(default(Microsoft.AspNetCore.Identity.UserManager), default(Microsoft.Extensions.Options.IOptions)) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserClaimsPrincipalFactory<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserClaimsPrincipalFactory : Microsoft.AspNetCore.Identity.IUserClaimsPrincipalFactory where TUser : class { public virtual System.Threading.Tasks.Task CreateAsync(TUser user) => throw null; @@ -588,7 +529,6 @@ namespace Microsoft public Microsoft.AspNetCore.Identity.UserManager UserManager { get => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.UserLoginInfo` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserLoginInfo { public string LoginProvider { get => throw null; set => throw null; } @@ -597,7 +537,6 @@ namespace Microsoft public UserLoginInfo(string loginProvider, string providerKey, string displayName) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserManager<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserManager : System.IDisposable where TUser : class { public virtual System.Threading.Tasks.Task AccessFailedAsync(TUser user) => throw null; @@ -723,7 +662,6 @@ namespace Microsoft public virtual System.Threading.Tasks.Task VerifyUserTokenAsync(TUser user, string tokenProvider, string purpose, string token) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserOptions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserOptions { public string AllowedUserNameCharacters { get => throw null; set => throw null; } @@ -731,7 +669,6 @@ namespace Microsoft public UserOptions() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserValidator<>` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UserValidator : Microsoft.AspNetCore.Identity.IUserValidator where TUser : class { public Microsoft.AspNetCore.Identity.IdentityErrorDescriber Describer { get => throw null; } @@ -745,7 +682,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.IdentityServiceCollectionExtensions` in `Microsoft.AspNetCore.Identity, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class IdentityServiceCollectionExtensions { public static Microsoft.AspNetCore.Identity.IdentityBuilder AddIdentityCore(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TUser : class => throw null; @@ -761,7 +697,6 @@ namespace System { namespace Claims { - // Generated from `System.Security.Claims.PrincipalExtensions` in `Microsoft.Extensions.Identity.Core, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class PrincipalExtensions { public static string FindFirstValue(this System.Security.Claims.ClaimsPrincipal principal, string claimType) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Stores.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Stores.cs index e6208d9b957..9784752a233 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Stores.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Identity.Stores.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Identity.Stores, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,14 +7,12 @@ namespace Microsoft { namespace Identity { - // Generated from `Microsoft.AspNetCore.Identity.IdentityRole` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityRole : Microsoft.AspNetCore.Identity.IdentityRole { public IdentityRole() => throw null; public IdentityRole(string roleName) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityRole<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityRole where TKey : System.IEquatable { public virtual string ConcurrencyStamp { get => throw null; set => throw null; } @@ -25,7 +24,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityRoleClaim<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityRoleClaim where TKey : System.IEquatable { public virtual string ClaimType { get => throw null; set => throw null; } @@ -37,14 +35,12 @@ namespace Microsoft public virtual System.Security.Claims.Claim ToClaim() => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUser` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUser : Microsoft.AspNetCore.Identity.IdentityUser { public IdentityUser() => throw null; public IdentityUser(string userName) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUser<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUser where TKey : System.IEquatable { public virtual int AccessFailedCount { get => throw null; set => throw null; } @@ -67,7 +63,6 @@ namespace Microsoft public virtual string UserName { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUserClaim<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUserClaim where TKey : System.IEquatable { public virtual string ClaimType { get => throw null; set => throw null; } @@ -79,7 +74,6 @@ namespace Microsoft public virtual TKey UserId { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUserLogin<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUserLogin where TKey : System.IEquatable { public IdentityUserLogin() => throw null; @@ -89,7 +83,6 @@ namespace Microsoft public virtual TKey UserId { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUserRole<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUserRole where TKey : System.IEquatable { public IdentityUserRole() => throw null; @@ -97,7 +90,6 @@ namespace Microsoft public virtual TKey UserId { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.IdentityUserToken<>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class IdentityUserToken where TKey : System.IEquatable { public IdentityUserToken() => throw null; @@ -107,7 +99,6 @@ namespace Microsoft public virtual string Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.AspNetCore.Identity.RoleStoreBase<,,,>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class RoleStoreBase : Microsoft.AspNetCore.Identity.IQueryableRoleStore, Microsoft.AspNetCore.Identity.IRoleClaimStore, Microsoft.AspNetCore.Identity.IRoleStore, System.IDisposable where TKey : System.IEquatable where TRole : Microsoft.AspNetCore.Identity.IdentityRole where TRoleClaim : Microsoft.AspNetCore.Identity.IdentityRoleClaim, new() where TUserRole : Microsoft.AspNetCore.Identity.IdentityUserRole, new() { public abstract System.Threading.Tasks.Task AddClaimAsync(TRole role, System.Security.Claims.Claim claim, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -133,7 +124,6 @@ namespace Microsoft public abstract System.Threading.Tasks.Task UpdateAsync(TRole role, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.AspNetCore.Identity.UserStoreBase<,,,,,,,>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class UserStoreBase : Microsoft.AspNetCore.Identity.UserStoreBase, Microsoft.AspNetCore.Identity.IUserRoleStore, Microsoft.AspNetCore.Identity.IUserStore, System.IDisposable where TKey : System.IEquatable where TRole : Microsoft.AspNetCore.Identity.IdentityRole where TRoleClaim : Microsoft.AspNetCore.Identity.IdentityRoleClaim, new() where TUser : Microsoft.AspNetCore.Identity.IdentityUser where TUserClaim : Microsoft.AspNetCore.Identity.IdentityUserClaim, new() where TUserLogin : Microsoft.AspNetCore.Identity.IdentityUserLogin, new() where TUserRole : Microsoft.AspNetCore.Identity.IdentityUserRole, new() where TUserToken : Microsoft.AspNetCore.Identity.IdentityUserToken, new() { public abstract System.Threading.Tasks.Task AddToRoleAsync(TUser user, string normalizedRoleName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); @@ -147,7 +137,6 @@ namespace Microsoft public UserStoreBase(Microsoft.AspNetCore.Identity.IdentityErrorDescriber describer) : base(default(Microsoft.AspNetCore.Identity.IdentityErrorDescriber)) => throw null; } - // Generated from `Microsoft.AspNetCore.Identity.UserStoreBase<,,,,>` in `Microsoft.Extensions.Identity.Stores, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class UserStoreBase : Microsoft.AspNetCore.Identity.IQueryableUserStore, Microsoft.AspNetCore.Identity.IUserAuthenticationTokenStore, Microsoft.AspNetCore.Identity.IUserAuthenticatorKeyStore, Microsoft.AspNetCore.Identity.IUserClaimStore, Microsoft.AspNetCore.Identity.IUserEmailStore, Microsoft.AspNetCore.Identity.IUserLockoutStore, Microsoft.AspNetCore.Identity.IUserLoginStore, Microsoft.AspNetCore.Identity.IUserPasswordStore, Microsoft.AspNetCore.Identity.IUserPhoneNumberStore, Microsoft.AspNetCore.Identity.IUserSecurityStampStore, Microsoft.AspNetCore.Identity.IUserStore, Microsoft.AspNetCore.Identity.IUserTwoFactorRecoveryCodeStore, Microsoft.AspNetCore.Identity.IUserTwoFactorStore, System.IDisposable where TKey : System.IEquatable where TUser : Microsoft.AspNetCore.Identity.IdentityUser where TUserClaim : Microsoft.AspNetCore.Identity.IdentityUserClaim, new() where TUserLogin : Microsoft.AspNetCore.Identity.IdentityUserLogin, new() where TUserToken : Microsoft.AspNetCore.Identity.IdentityUserToken, new() { public abstract System.Threading.Tasks.Task AddClaimsAsync(TUser user, System.Collections.Generic.IEnumerable claims, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.Abstractions.cs index 4b1dd8b8ace..c64b40cfc9a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Localization.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Localization { - // Generated from `Microsoft.Extensions.Localization.IStringLocalizer` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStringLocalizer { System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures); @@ -14,19 +14,16 @@ namespace Microsoft Microsoft.Extensions.Localization.LocalizedString this[string name] { get; } } - // Generated from `Microsoft.Extensions.Localization.IStringLocalizer<>` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStringLocalizer : Microsoft.Extensions.Localization.IStringLocalizer { } - // Generated from `Microsoft.Extensions.Localization.IStringLocalizerFactory` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IStringLocalizerFactory { Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource); Microsoft.Extensions.Localization.IStringLocalizer Create(string baseName, string location); } - // Generated from `Microsoft.Extensions.Localization.LocalizedString` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocalizedString { public LocalizedString(string name, string value) => throw null; @@ -40,7 +37,6 @@ namespace Microsoft public static implicit operator string(Microsoft.Extensions.Localization.LocalizedString localizedString) => throw null; } - // Generated from `Microsoft.Extensions.Localization.StringLocalizer<>` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringLocalizer : Microsoft.Extensions.Localization.IStringLocalizer, Microsoft.Extensions.Localization.IStringLocalizer { public System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures) => throw null; @@ -49,7 +45,6 @@ namespace Microsoft public StringLocalizer(Microsoft.Extensions.Localization.IStringLocalizerFactory factory) => throw null; } - // Generated from `Microsoft.Extensions.Localization.StringLocalizerExtensions` in `Microsoft.Extensions.Localization.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class StringLocalizerExtensions { public static System.Collections.Generic.IEnumerable GetAllStrings(this Microsoft.Extensions.Localization.IStringLocalizer stringLocalizer) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.cs index ee1d6caabdc..b1134a1f3ec 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Localization.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Localization, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.LocalizationServiceCollectionExtensions` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LocalizationServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddLocalization(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -16,27 +16,23 @@ namespace Microsoft } namespace Localization { - // Generated from `Microsoft.Extensions.Localization.IResourceNamesCache` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IResourceNamesCache { System.Collections.Generic.IList GetOrAdd(string name, System.Func> valueFactory); } - // Generated from `Microsoft.Extensions.Localization.LocalizationOptions` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LocalizationOptions { public LocalizationOptions() => throw null; public string ResourcesPath { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Localization.ResourceLocationAttribute` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceLocationAttribute : System.Attribute { public string ResourceLocation { get => throw null; } public ResourceLocationAttribute(string resourceLocation) => throw null; } - // Generated from `Microsoft.Extensions.Localization.ResourceManagerStringLocalizer` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceManagerStringLocalizer : Microsoft.Extensions.Localization.IStringLocalizer { public virtual System.Collections.Generic.IEnumerable GetAllStrings(bool includeParentCultures) => throw null; @@ -47,7 +43,6 @@ namespace Microsoft public ResourceManagerStringLocalizer(System.Resources.ResourceManager resourceManager, System.Reflection.Assembly resourceAssembly, string baseName, Microsoft.Extensions.Localization.IResourceNamesCache resourceNamesCache, Microsoft.Extensions.Logging.ILogger logger) => throw null; } - // Generated from `Microsoft.Extensions.Localization.ResourceManagerStringLocalizerFactory` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceManagerStringLocalizerFactory : Microsoft.Extensions.Localization.IStringLocalizerFactory { public Microsoft.Extensions.Localization.IStringLocalizer Create(System.Type resourceSource) => throw null; @@ -62,14 +57,12 @@ namespace Microsoft public ResourceManagerStringLocalizerFactory(Microsoft.Extensions.Options.IOptions localizationOptions, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) => throw null; } - // Generated from `Microsoft.Extensions.Localization.ResourceNamesCache` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ResourceNamesCache : Microsoft.Extensions.Localization.IResourceNamesCache { public System.Collections.Generic.IList GetOrAdd(string name, System.Func> valueFactory) => throw null; public ResourceNamesCache() => throw null; } - // Generated from `Microsoft.Extensions.Localization.RootNamespaceAttribute` in `Microsoft.Extensions.Localization, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RootNamespaceAttribute : System.Attribute { public string RootNamespace { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Abstractions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Abstractions.cs index f2d68ea9e17..5797688f98a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Abstractions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Abstractions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.Abstractions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,8 +7,7 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.EventId` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` - public struct EventId + public struct EventId : System.IEquatable { public static bool operator !=(Microsoft.Extensions.Logging.EventId left, Microsoft.Extensions.Logging.EventId right) => throw null; public static bool operator ==(Microsoft.Extensions.Logging.EventId left, Microsoft.Extensions.Logging.EventId right) => throw null; @@ -22,14 +22,12 @@ namespace Microsoft public static implicit operator Microsoft.Extensions.Logging.EventId(int i) => throw null; } - // Generated from `Microsoft.Extensions.Logging.IExternalScopeProvider` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IExternalScopeProvider { void ForEachScope(System.Action callback, TState state); System.IDisposable Push(object state); } - // Generated from `Microsoft.Extensions.Logging.ILogger` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILogger { System.IDisposable BeginScope(TState state); @@ -37,38 +35,32 @@ namespace Microsoft void Log(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, System.Exception exception, System.Func formatter); } - // Generated from `Microsoft.Extensions.Logging.ILogger<>` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILogger : Microsoft.Extensions.Logging.ILogger { } - // Generated from `Microsoft.Extensions.Logging.ILoggerFactory` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILoggerFactory : System.IDisposable { void AddProvider(Microsoft.Extensions.Logging.ILoggerProvider provider); Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName); } - // Generated from `Microsoft.Extensions.Logging.ILoggerProvider` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILoggerProvider : System.IDisposable { Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName); } - // Generated from `Microsoft.Extensions.Logging.ISupportExternalScope` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ISupportExternalScope { void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider); } - // Generated from `Microsoft.Extensions.Logging.LogDefineOptions` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LogDefineOptions { public LogDefineOptions() => throw null; public bool SkipEnabledCheck { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Logging.LogLevel` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum LogLevel : int { Critical = 5, @@ -80,7 +72,6 @@ namespace Microsoft Warning = 3, } - // Generated from `Microsoft.Extensions.Logging.Logger<>` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class Logger : Microsoft.Extensions.Logging.ILogger, Microsoft.Extensions.Logging.ILogger { System.IDisposable Microsoft.Extensions.Logging.ILogger.BeginScope(TState state) => throw null; @@ -89,7 +80,6 @@ namespace Microsoft public Logger(Microsoft.Extensions.Logging.ILoggerFactory factory) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerExtensions` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggerExtensions { public static System.IDisposable BeginScope(this Microsoft.Extensions.Logging.ILogger logger, string messageFormat, params object[] args) => throw null; @@ -123,7 +113,6 @@ namespace Microsoft public static void LogWarning(this Microsoft.Extensions.Logging.ILogger logger, string message, params object[] args) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerExternalScopeProvider` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerExternalScopeProvider : Microsoft.Extensions.Logging.IExternalScopeProvider { public void ForEachScope(System.Action callback, TState state) => throw null; @@ -131,14 +120,12 @@ namespace Microsoft public System.IDisposable Push(object state) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerFactoryExtensions` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggerFactoryExtensions { public static Microsoft.Extensions.Logging.ILogger CreateLogger(this Microsoft.Extensions.Logging.ILoggerFactory factory, System.Type type) => throw null; public static Microsoft.Extensions.Logging.ILogger CreateLogger(this Microsoft.Extensions.Logging.ILoggerFactory factory) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerMessage` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggerMessage { public static System.Action Define(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, string formatString) => throw null; @@ -164,7 +151,6 @@ namespace Microsoft public static System.Func DefineScope(string formatString) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerMessageAttribute` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerMessageAttribute : System.Attribute { public int EventId { get => throw null; set => throw null; } @@ -178,7 +164,6 @@ namespace Microsoft namespace Abstractions { - // Generated from `Microsoft.Extensions.Logging.Abstractions.LogEntry<>` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct LogEntry { public string Category { get => throw null; } @@ -191,7 +176,6 @@ namespace Microsoft public TState State { get => throw null; } } - // Generated from `Microsoft.Extensions.Logging.Abstractions.NullLogger` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullLogger : Microsoft.Extensions.Logging.ILogger { public System.IDisposable BeginScope(TState state) => throw null; @@ -200,7 +184,6 @@ namespace Microsoft public void Log(Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, System.Exception exception, System.Func formatter) => throw null; } - // Generated from `Microsoft.Extensions.Logging.Abstractions.NullLogger<>` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullLogger : Microsoft.Extensions.Logging.ILogger, Microsoft.Extensions.Logging.ILogger { public System.IDisposable BeginScope(TState state) => throw null; @@ -210,7 +193,6 @@ namespace Microsoft public NullLogger() => throw null; } - // Generated from `Microsoft.Extensions.Logging.Abstractions.NullLoggerFactory` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullLoggerFactory : Microsoft.Extensions.Logging.ILoggerFactory, System.IDisposable { public void AddProvider(Microsoft.Extensions.Logging.ILoggerProvider provider) => throw null; @@ -220,7 +202,6 @@ namespace Microsoft public NullLoggerFactory() => throw null; } - // Generated from `Microsoft.Extensions.Logging.Abstractions.NullLoggerProvider` in `Microsoft.Extensions.Logging.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NullLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, System.IDisposable { public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Configuration.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Configuration.cs index f787be48cd3..0d098e3e4d3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Configuration.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Configuration.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.Configuration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.LoggingBuilderExtensions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class LoggingBuilderExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddConfiguration(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Configuration.IConfiguration configuration) => throw null; @@ -14,31 +14,26 @@ namespace Microsoft namespace Configuration { - // Generated from `Microsoft.Extensions.Logging.Configuration.ILoggerProviderConfiguration<>` in `Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILoggerProviderConfiguration { Microsoft.Extensions.Configuration.IConfiguration Configuration { get; } } - // Generated from `Microsoft.Extensions.Logging.Configuration.ILoggerProviderConfigurationFactory` in `Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILoggerProviderConfigurationFactory { Microsoft.Extensions.Configuration.IConfiguration GetConfiguration(System.Type providerType); } - // Generated from `Microsoft.Extensions.Logging.Configuration.LoggerProviderOptions` in `Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggerProviderOptions { public static void RegisterProviderOptions(Microsoft.Extensions.DependencyInjection.IServiceCollection services) where TOptions : class => throw null; } - // Generated from `Microsoft.Extensions.Logging.Configuration.LoggerProviderOptionsChangeTokenSource<,>` in `Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerProviderOptionsChangeTokenSource : Microsoft.Extensions.Options.ConfigurationChangeTokenSource { public LoggerProviderOptionsChangeTokenSource(Microsoft.Extensions.Logging.Configuration.ILoggerProviderConfiguration providerConfiguration) : base(default(Microsoft.Extensions.Configuration.IConfiguration)) => throw null; } - // Generated from `Microsoft.Extensions.Logging.Configuration.LoggingBuilderConfigurationExtensions` in `Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggingBuilderConfigurationExtensions { public static void AddConfiguration(this Microsoft.Extensions.Logging.ILoggingBuilder builder) => throw null; @@ -48,18 +43,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'RequiresUnreferencedCodeAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Console.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Console.cs index 91af05c07d5..ad283d7b3ad 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Console.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Console.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.Console, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.ConsoleLoggerExtensions` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConsoleLoggerExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddConsole(this Microsoft.Extensions.Logging.ILoggingBuilder builder) => throw null; @@ -23,7 +23,6 @@ namespace Microsoft namespace Console { - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleFormatter` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ConsoleFormatter { protected ConsoleFormatter(string name) => throw null; @@ -31,7 +30,6 @@ namespace Microsoft public abstract void Write(Microsoft.Extensions.Logging.Abstractions.LogEntry logEntry, Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider, System.IO.TextWriter textWriter); } - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleFormatterNames` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ConsoleFormatterNames { public const string Json = default; @@ -39,7 +37,6 @@ namespace Microsoft public const string Systemd = default; } - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsoleFormatterOptions { public ConsoleFormatterOptions() => throw null; @@ -48,14 +45,12 @@ namespace Microsoft public bool UseUtcTimestamp { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleLoggerFormat` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum ConsoleLoggerFormat : int { Default = 0, Systemd = 1, } - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleLoggerOptions` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsoleLoggerOptions { public ConsoleLoggerOptions() => throw null; @@ -64,11 +59,12 @@ namespace Microsoft public string FormatterName { get => throw null; set => throw null; } public bool IncludeScopes { get => throw null; set => throw null; } public Microsoft.Extensions.Logging.LogLevel LogToStandardErrorThreshold { get => throw null; set => throw null; } + public int MaxQueueLength { get => throw null; set => throw null; } + public Microsoft.Extensions.Logging.Console.ConsoleLoggerQueueFullMode QueueFullMode { get => throw null; set => throw null; } public string TimestampFormat { get => throw null; set => throw null; } public bool UseUtcTimestamp { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Logging.Console.ConsoleLoggerProvider` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConsoleLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, Microsoft.Extensions.Logging.ISupportExternalScope, System.IDisposable { public ConsoleLoggerProvider(Microsoft.Extensions.Options.IOptionsMonitor options) => throw null; @@ -78,14 +74,18 @@ namespace Microsoft public void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider) => throw null; } - // Generated from `Microsoft.Extensions.Logging.Console.JsonConsoleFormatterOptions` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` + public enum ConsoleLoggerQueueFullMode : int + { + DropWrite = 1, + Wait = 0, + } + public class JsonConsoleFormatterOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { public JsonConsoleFormatterOptions() => throw null; public System.Text.Json.JsonWriterOptions JsonWriterOptions { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.Logging.Console.LoggerColorBehavior` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum LoggerColorBehavior : int { Default = 0, @@ -93,7 +93,6 @@ namespace Microsoft Enabled = 1, } - // Generated from `Microsoft.Extensions.Logging.Console.SimpleConsoleFormatterOptions` in `Microsoft.Extensions.Logging.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SimpleConsoleFormatterOptions : Microsoft.Extensions.Logging.Console.ConsoleFormatterOptions { public Microsoft.Extensions.Logging.Console.LoggerColorBehavior ColorBehavior { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Debug.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Debug.cs index 62ee5e82901..4aa3b8a9fb5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Debug.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.Debug.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.Debug, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.DebugLoggerFactoryExtensions` in `Microsoft.Extensions.Logging.Debug, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DebugLoggerFactoryExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddDebug(this Microsoft.Extensions.Logging.ILoggingBuilder builder) => throw null; @@ -14,7 +14,6 @@ namespace Microsoft namespace Debug { - // Generated from `Microsoft.Extensions.Logging.Debug.DebugLoggerProvider` in `Microsoft.Extensions.Logging.Debug, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DebugLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, System.IDisposable { public Microsoft.Extensions.Logging.ILogger CreateLogger(string name) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventLog.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventLog.cs index fdd0828fb02..dc103021eb8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventLog.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventLog.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.EventLog, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.EventLoggerFactoryExtensions` in `Microsoft.Extensions.Logging.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EventLoggerFactoryExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventLog(this Microsoft.Extensions.Logging.ILoggingBuilder builder) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft namespace EventLog { - // Generated from `Microsoft.Extensions.Logging.EventLog.EventLogLoggerProvider` in `Microsoft.Extensions.Logging.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventLogLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, Microsoft.Extensions.Logging.ISupportExternalScope, System.IDisposable { public Microsoft.Extensions.Logging.ILogger CreateLogger(string name) => throw null; @@ -27,7 +26,6 @@ namespace Microsoft public void SetScopeProvider(Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider) => throw null; } - // Generated from `Microsoft.Extensions.Logging.EventLog.EventLogSettings` in `Microsoft.Extensions.Logging.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventLogSettings { public EventLogSettings() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventSource.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventSource.cs index d9fb94eac95..8d4e1fb1f5f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventSource.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.EventSource.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.EventSource, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.EventSourceLoggerFactoryExtensions` in `Microsoft.Extensions.Logging.EventSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EventSourceLoggerFactoryExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddEventSourceLogger(this Microsoft.Extensions.Logging.ILoggingBuilder builder) => throw null; @@ -14,7 +14,6 @@ namespace Microsoft namespace EventSource { - // Generated from `Microsoft.Extensions.Logging.EventSource.EventSourceLoggerProvider` in `Microsoft.Extensions.Logging.EventSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EventSourceLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, System.IDisposable { public Microsoft.Extensions.Logging.ILogger CreateLogger(string categoryName) => throw null; @@ -22,10 +21,8 @@ namespace Microsoft public EventSourceLoggerProvider(Microsoft.Extensions.Logging.EventSource.LoggingEventSource eventSource) => throw null; } - // Generated from `Microsoft.Extensions.Logging.EventSource.LoggingEventSource` in `Microsoft.Extensions.Logging.EventSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggingEventSource : System.Diagnostics.Tracing.EventSource { - // Generated from `Microsoft.Extensions.Logging.EventSource.LoggingEventSource+Keywords` in `Microsoft.Extensions.Logging.EventSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Keywords { public const System.Diagnostics.Tracing.EventKeywords FormattedMessage = default; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.TraceSource.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.TraceSource.cs index dd9a6315114..a28778aad6d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.TraceSource.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.TraceSource.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging.TraceSource, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Logging { - // Generated from `Microsoft.Extensions.Logging.TraceSourceFactoryExtensions` in `Microsoft.Extensions.Logging.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class TraceSourceFactoryExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddTraceSource(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Diagnostics.SourceSwitch sourceSwitch) => throw null; @@ -17,7 +17,6 @@ namespace Microsoft namespace TraceSource { - // Generated from `Microsoft.Extensions.Logging.TraceSource.TraceSourceLoggerProvider` in `Microsoft.Extensions.Logging.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class TraceSourceLoggerProvider : Microsoft.Extensions.Logging.ILoggerProvider, System.IDisposable { public Microsoft.Extensions.Logging.ILogger CreateLogger(string name) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.cs index 14b5405680d..0cc448912d1 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Logging.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Logging, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.LoggingServiceCollectionExtensions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class LoggingServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddLogging(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft } namespace Logging { - // Generated from `Microsoft.Extensions.Logging.ActivityTrackingOptions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` [System.Flags] public enum ActivityTrackingOptions : int { @@ -30,7 +29,6 @@ namespace Microsoft TraceState = 8, } - // Generated from `Microsoft.Extensions.Logging.FilterLoggingBuilderExtensions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class FilterLoggingBuilderExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddFilter(this Microsoft.Extensions.Logging.ILoggingBuilder builder, System.Func levelFilter) => throw null; @@ -53,13 +51,11 @@ namespace Microsoft public static Microsoft.Extensions.Logging.LoggerFilterOptions AddFilter(this Microsoft.Extensions.Logging.LoggerFilterOptions builder, string category, Microsoft.Extensions.Logging.LogLevel level) where T : Microsoft.Extensions.Logging.ILoggerProvider => throw null; } - // Generated from `Microsoft.Extensions.Logging.ILoggingBuilder` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface ILoggingBuilder { Microsoft.Extensions.DependencyInjection.IServiceCollection Services { get; } } - // Generated from `Microsoft.Extensions.Logging.LoggerFactory` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerFactory : Microsoft.Extensions.Logging.ILoggerFactory, System.IDisposable { public void AddProvider(Microsoft.Extensions.Logging.ILoggerProvider provider) => throw null; @@ -70,18 +66,17 @@ namespace Microsoft public LoggerFactory() => throw null; public LoggerFactory(System.Collections.Generic.IEnumerable providers) => throw null; public LoggerFactory(System.Collections.Generic.IEnumerable providers, Microsoft.Extensions.Options.IOptionsMonitor filterOption) => throw null; - public LoggerFactory(System.Collections.Generic.IEnumerable providers, Microsoft.Extensions.Options.IOptionsMonitor filterOption, Microsoft.Extensions.Options.IOptions options = default(Microsoft.Extensions.Options.IOptions)) => throw null; + public LoggerFactory(System.Collections.Generic.IEnumerable providers, Microsoft.Extensions.Options.IOptionsMonitor filterOption, Microsoft.Extensions.Options.IOptions options) => throw null; + public LoggerFactory(System.Collections.Generic.IEnumerable providers, Microsoft.Extensions.Options.IOptionsMonitor filterOption, Microsoft.Extensions.Options.IOptions options = default(Microsoft.Extensions.Options.IOptions), Microsoft.Extensions.Logging.IExternalScopeProvider scopeProvider = default(Microsoft.Extensions.Logging.IExternalScopeProvider)) => throw null; public LoggerFactory(System.Collections.Generic.IEnumerable providers, Microsoft.Extensions.Logging.LoggerFilterOptions filterOptions) => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerFactoryOptions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerFactoryOptions { public Microsoft.Extensions.Logging.ActivityTrackingOptions ActivityTrackingOptions { get => throw null; set => throw null; } public LoggerFactoryOptions() => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggerFilterOptions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerFilterOptions { public bool CaptureScopes { get => throw null; set => throw null; } @@ -90,7 +85,6 @@ namespace Microsoft public System.Collections.Generic.IList Rules { get => throw null; } } - // Generated from `Microsoft.Extensions.Logging.LoggerFilterRule` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LoggerFilterRule { public string CategoryName { get => throw null; } @@ -101,7 +95,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.Extensions.Logging.LoggingBuilderExtensions` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static partial class LoggingBuilderExtensions { public static Microsoft.Extensions.Logging.ILoggingBuilder AddProvider(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Logging.ILoggerProvider provider) => throw null; @@ -110,7 +103,6 @@ namespace Microsoft public static Microsoft.Extensions.Logging.ILoggingBuilder SetMinimumLevel(this Microsoft.Extensions.Logging.ILoggingBuilder builder, Microsoft.Extensions.Logging.LogLevel level) => throw null; } - // Generated from `Microsoft.Extensions.Logging.ProviderAliasAttribute` in `Microsoft.Extensions.Logging, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ProviderAliasAttribute : System.Attribute { public string Alias { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.ObjectPool.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.ObjectPool.cs index 073ff3ccfcd..b6e98e8213a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.ObjectPool.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.ObjectPool.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.ObjectPool, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace ObjectPool { - // Generated from `Microsoft.Extensions.ObjectPool.DefaultObjectPool<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultObjectPool : Microsoft.Extensions.ObjectPool.ObjectPool where T : class { public DefaultObjectPool(Microsoft.Extensions.ObjectPool.IPooledObjectPolicy policy) => throw null; @@ -15,7 +15,6 @@ namespace Microsoft public override void Return(T obj) => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.DefaultObjectPoolProvider` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultObjectPoolProvider : Microsoft.Extensions.ObjectPool.ObjectPoolProvider { public override Microsoft.Extensions.ObjectPool.ObjectPool Create(Microsoft.Extensions.ObjectPool.IPooledObjectPolicy policy) where T : class => throw null; @@ -23,7 +22,6 @@ namespace Microsoft public int MaximumRetained { get => throw null; set => throw null; } } - // Generated from `Microsoft.Extensions.ObjectPool.DefaultPooledObjectPolicy<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DefaultPooledObjectPolicy : Microsoft.Extensions.ObjectPool.PooledObjectPolicy where T : class, new() { public override T Create() => throw null; @@ -31,14 +29,12 @@ namespace Microsoft public override bool Return(T obj) => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.IPooledObjectPolicy<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPooledObjectPolicy { T Create(); bool Return(T obj); } - // Generated from `Microsoft.Extensions.ObjectPool.LeakTrackingObjectPool<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LeakTrackingObjectPool : Microsoft.Extensions.ObjectPool.ObjectPool where T : class { public override T Get() => throw null; @@ -46,20 +42,17 @@ namespace Microsoft public override void Return(T obj) => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.LeakTrackingObjectPoolProvider` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class LeakTrackingObjectPoolProvider : Microsoft.Extensions.ObjectPool.ObjectPoolProvider { public override Microsoft.Extensions.ObjectPool.ObjectPool Create(Microsoft.Extensions.ObjectPool.IPooledObjectPolicy policy) where T : class => throw null; public LeakTrackingObjectPoolProvider(Microsoft.Extensions.ObjectPool.ObjectPoolProvider inner) => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.ObjectPool` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ObjectPool { public static Microsoft.Extensions.ObjectPool.ObjectPool Create(Microsoft.Extensions.ObjectPool.IPooledObjectPolicy policy = default(Microsoft.Extensions.ObjectPool.IPooledObjectPolicy)) where T : class, new() => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.ObjectPool<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ObjectPool where T : class { public abstract T Get(); @@ -67,7 +60,6 @@ namespace Microsoft public abstract void Return(T obj); } - // Generated from `Microsoft.Extensions.ObjectPool.ObjectPoolProvider` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class ObjectPoolProvider { public Microsoft.Extensions.ObjectPool.ObjectPool Create() where T : class, new() => throw null; @@ -75,14 +67,12 @@ namespace Microsoft protected ObjectPoolProvider() => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.ObjectPoolProviderExtensions` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ObjectPoolProviderExtensions { public static Microsoft.Extensions.ObjectPool.ObjectPool CreateStringBuilderPool(this Microsoft.Extensions.ObjectPool.ObjectPoolProvider provider) => throw null; public static Microsoft.Extensions.ObjectPool.ObjectPool CreateStringBuilderPool(this Microsoft.Extensions.ObjectPool.ObjectPoolProvider provider, int initialCapacity, int maximumRetainedCapacity) => throw null; } - // Generated from `Microsoft.Extensions.ObjectPool.PooledObjectPolicy<>` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class PooledObjectPolicy : Microsoft.Extensions.ObjectPool.IPooledObjectPolicy { public abstract T Create(); @@ -90,7 +80,6 @@ namespace Microsoft public abstract bool Return(T obj); } - // Generated from `Microsoft.Extensions.ObjectPool.StringBuilderPooledObjectPolicy` in `Microsoft.Extensions.ObjectPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringBuilderPooledObjectPolicy : Microsoft.Extensions.ObjectPool.PooledObjectPolicy { public override System.Text.StringBuilder Create() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.ConfigurationExtensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.ConfigurationExtensions.cs index a6b39c41759..7131c76b988 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.ConfigurationExtensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.ConfigurationExtensions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Options.ConfigurationExtensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.OptionsBuilderConfigurationExtensions` in `Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsBuilderConfigurationExtensions { public static Microsoft.Extensions.Options.OptionsBuilder Bind(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class => throw null; @@ -14,7 +14,6 @@ namespace Microsoft public static Microsoft.Extensions.Options.OptionsBuilder BindConfiguration(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder, string configSectionPath, System.Action configureBinder = default(System.Action)) where TOptions : class => throw null; } - // Generated from `Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions` in `Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsConfigurationServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection Configure(this Microsoft.Extensions.DependencyInjection.IServiceCollection services, Microsoft.Extensions.Configuration.IConfiguration config) where TOptions : class => throw null; @@ -26,7 +25,6 @@ namespace Microsoft } namespace Options { - // Generated from `Microsoft.Extensions.Options.ConfigurationChangeTokenSource<>` in `Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigurationChangeTokenSource : Microsoft.Extensions.Options.IOptionsChangeTokenSource { public ConfigurationChangeTokenSource(Microsoft.Extensions.Configuration.IConfiguration config) => throw null; @@ -35,13 +33,11 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureFromConfigurationOptions<>` in `Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureFromConfigurationOptions : Microsoft.Extensions.Options.ConfigureOptions where TOptions : class { public ConfigureFromConfigurationOptions(Microsoft.Extensions.Configuration.IConfiguration config) : base(default(System.Action)) => throw null; } - // Generated from `Microsoft.Extensions.Options.NamedConfigureFromConfigurationOptions<>` in `Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NamedConfigureFromConfigurationOptions : Microsoft.Extensions.Options.ConfigureNamedOptions where TOptions : class { public NamedConfigureFromConfigurationOptions(string name, Microsoft.Extensions.Configuration.IConfiguration config) : base(default(string), default(System.Action)) => throw null; @@ -51,18 +47,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'RequiresUnreferencedCodeAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.DataAnnotations.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.DataAnnotations.cs index 7ac61567360..1e256aac9fd 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.DataAnnotations.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.DataAnnotations.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Options.DataAnnotations, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.OptionsBuilderDataAnnotationsExtensions` in `Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsBuilderDataAnnotationsExtensions { public static Microsoft.Extensions.Options.OptionsBuilder ValidateDataAnnotations(this Microsoft.Extensions.Options.OptionsBuilder optionsBuilder) where TOptions : class => throw null; @@ -15,7 +15,6 @@ namespace Microsoft } namespace Options { - // Generated from `Microsoft.Extensions.Options.DataAnnotationValidateOptions<>` in `Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DataAnnotationValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public DataAnnotationValidateOptions(string name) => throw null; @@ -26,18 +25,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'RequiresUnreferencedCodeAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.cs index 88cc420093b..b77b3e65468 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Options.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Options, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.OptionsServiceCollectionExtensions` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddOptions(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -26,7 +26,6 @@ namespace Microsoft } namespace Options { - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<,,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -41,7 +40,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -55,7 +53,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -68,7 +65,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TDep1 : class where TDep2 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -80,7 +76,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TDep : class where TOptions : class { public System.Action Action { get => throw null; } @@ -91,7 +86,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureNamedOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureNamedOptions, Microsoft.Extensions.Options.IConfigureOptions where TOptions : class { public System.Action Action { get => throw null; } @@ -101,7 +95,6 @@ namespace Microsoft public string Name { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ConfigureOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ConfigureOptions : Microsoft.Extensions.Options.IConfigureOptions where TOptions : class { public System.Action Action { get => throw null; } @@ -109,38 +102,32 @@ namespace Microsoft public ConfigureOptions(System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.IConfigureNamedOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigureNamedOptions : Microsoft.Extensions.Options.IConfigureOptions where TOptions : class { void Configure(string name, TOptions options); } - // Generated from `Microsoft.Extensions.Options.IConfigureOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IConfigureOptions where TOptions : class { void Configure(TOptions options); } - // Generated from `Microsoft.Extensions.Options.IOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptions where TOptions : class { TOptions Value { get; } } - // Generated from `Microsoft.Extensions.Options.IOptionsChangeTokenSource<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptionsChangeTokenSource { Microsoft.Extensions.Primitives.IChangeToken GetChangeToken(); string Name { get; } } - // Generated from `Microsoft.Extensions.Options.IOptionsFactory<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptionsFactory where TOptions : class { TOptions Create(string name); } - // Generated from `Microsoft.Extensions.Options.IOptionsMonitor<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptionsMonitor { TOptions CurrentValue { get; } @@ -148,7 +135,6 @@ namespace Microsoft System.IDisposable OnChange(System.Action listener); } - // Generated from `Microsoft.Extensions.Options.IOptionsMonitorCache<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptionsMonitorCache where TOptions : class { void Clear(); @@ -157,32 +143,27 @@ namespace Microsoft bool TryRemove(string name); } - // Generated from `Microsoft.Extensions.Options.IOptionsSnapshot<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IOptionsSnapshot : Microsoft.Extensions.Options.IOptions where TOptions : class { TOptions Get(string name); } - // Generated from `Microsoft.Extensions.Options.IPostConfigureOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IPostConfigureOptions where TOptions : class { void PostConfigure(string name, TOptions options); } - // Generated from `Microsoft.Extensions.Options.IValidateOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IValidateOptions where TOptions : class { Microsoft.Extensions.Options.ValidateOptionsResult Validate(string name, TOptions options); } - // Generated from `Microsoft.Extensions.Options.Options` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Options { public static Microsoft.Extensions.Options.IOptions Create(TOptions options) where TOptions : class => throw null; public static string DefaultName; } - // Generated from `Microsoft.Extensions.Options.OptionsBuilder<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsBuilder where TOptions : class { public virtual Microsoft.Extensions.Options.OptionsBuilder Configure(System.Action configureOptions) => throw null; @@ -214,7 +195,6 @@ namespace Microsoft public virtual Microsoft.Extensions.Options.OptionsBuilder Validate(System.Func validation, string failureMessage) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsCache<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsCache : Microsoft.Extensions.Options.IOptionsMonitorCache where TOptions : class { public void Clear() => throw null; @@ -224,7 +204,6 @@ namespace Microsoft public virtual bool TryRemove(string name) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsFactory<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsFactory : Microsoft.Extensions.Options.IOptionsFactory where TOptions : class { public TOptions Create(string name) => throw null; @@ -233,7 +212,6 @@ namespace Microsoft public OptionsFactory(System.Collections.Generic.IEnumerable> setups, System.Collections.Generic.IEnumerable> postConfigures, System.Collections.Generic.IEnumerable> validations) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsManager<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsManager : Microsoft.Extensions.Options.IOptions, Microsoft.Extensions.Options.IOptionsSnapshot where TOptions : class { public virtual TOptions Get(string name) => throw null; @@ -241,7 +219,6 @@ namespace Microsoft public TOptions Value { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.OptionsMonitor<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsMonitor : Microsoft.Extensions.Options.IOptionsMonitor, System.IDisposable where TOptions : class { public TOptions CurrentValue { get => throw null; } @@ -251,13 +228,11 @@ namespace Microsoft public OptionsMonitor(Microsoft.Extensions.Options.IOptionsFactory factory, System.Collections.Generic.IEnumerable> sources, Microsoft.Extensions.Options.IOptionsMonitorCache cache) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsMonitorExtensions` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class OptionsMonitorExtensions { public static System.IDisposable OnChange(this Microsoft.Extensions.Options.IOptionsMonitor monitor, System.Action listener) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsValidationException` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsValidationException : System.Exception { public System.Collections.Generic.IEnumerable Failures { get => throw null; } @@ -267,14 +242,12 @@ namespace Microsoft public OptionsValidationException(string optionsName, System.Type optionsType, System.Collections.Generic.IEnumerable failureMessages) => throw null; } - // Generated from `Microsoft.Extensions.Options.OptionsWrapper<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class OptionsWrapper : Microsoft.Extensions.Options.IOptions where TOptions : class { public OptionsWrapper(TOptions options) => throw null; public TOptions Value { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<,,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TDep5 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -289,7 +262,6 @@ namespace Microsoft public PostConfigureOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, TDep5 dependency5, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TDep4 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -303,7 +275,6 @@ namespace Microsoft public PostConfigureOptions(string name, TDep1 dependency1, TDep2 dependency2, TDep3 dependency3, TDep4 dependency4, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TDep1 : class where TDep2 : class where TDep3 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -316,7 +287,6 @@ namespace Microsoft public PostConfigureOptions(string name, TDep1 dependency, TDep2 dependency2, TDep3 dependency3, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TDep1 : class where TDep2 : class where TOptions : class { public System.Action Action { get => throw null; } @@ -328,7 +298,6 @@ namespace Microsoft public PostConfigureOptions(string name, TDep1 dependency, TDep2 dependency2, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TDep : class where TOptions : class { public System.Action Action { get => throw null; } @@ -339,7 +308,6 @@ namespace Microsoft public PostConfigureOptions(string name, TDep dependency, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.PostConfigureOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class PostConfigureOptions : Microsoft.Extensions.Options.IPostConfigureOptions where TOptions : class { public System.Action Action { get => throw null; } @@ -348,7 +316,6 @@ namespace Microsoft public PostConfigureOptions(string name, System.Action action) => throw null; } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<,,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public TDep1 Dependency1 { get => throw null; } @@ -363,7 +330,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<,,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public TDep1 Dependency1 { get => throw null; } @@ -377,7 +343,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<,,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public TDep1 Dependency1 { get => throw null; } @@ -390,7 +355,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<,,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public TDep1 Dependency1 { get => throw null; } @@ -402,7 +366,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<,>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public TDep Dependency { get => throw null; } @@ -413,7 +376,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptions<>` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptions : Microsoft.Extensions.Options.IValidateOptions where TOptions : class { public string FailureMessage { get => throw null; } @@ -423,7 +385,6 @@ namespace Microsoft public System.Func Validation { get => throw null; } } - // Generated from `Microsoft.Extensions.Options.ValidateOptionsResult` in `Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ValidateOptionsResult { public static Microsoft.Extensions.Options.ValidateOptionsResult Fail(System.Collections.Generic.IEnumerable failures) => throw null; @@ -441,16 +402,3 @@ namespace Microsoft } } } -namespace System -{ - namespace Diagnostics - { - namespace CodeAnalysis - { - /* Duplicate type 'DynamicallyAccessedMemberTypes' is not stubbed in this assembly 'Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - /* Duplicate type 'DynamicallyAccessedMembersAttribute' is not stubbed in this assembly 'Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. */ - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Primitives.cs index eb4385c2764..c79f01782ee 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.Primitives.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace Primitives { - // Generated from `Microsoft.Extensions.Primitives.CancellationChangeToken` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CancellationChangeToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } @@ -15,14 +15,12 @@ namespace Microsoft public System.IDisposable RegisterChangeCallback(System.Action callback, object state) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.ChangeToken` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ChangeToken { public static System.IDisposable OnChange(System.Func changeTokenProducer, System.Action changeTokenConsumer) => throw null; public static System.IDisposable OnChange(System.Func changeTokenProducer, System.Action changeTokenConsumer, TState state) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.CompositeChangeToken` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CompositeChangeToken : Microsoft.Extensions.Primitives.IChangeToken { public bool ActiveChangeCallbacks { get => throw null; } @@ -32,13 +30,11 @@ namespace Microsoft public System.IDisposable RegisterChangeCallback(System.Action callback, object state) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.Extensions` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class Extensions { public static System.Text.StringBuilder Append(this System.Text.StringBuilder builder, Microsoft.Extensions.Primitives.StringSegment segment) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.IChangeToken` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IChangeToken { bool ActiveChangeCallbacks { get; } @@ -46,7 +42,6 @@ namespace Microsoft System.IDisposable RegisterChangeCallback(System.Action callback, object state); } - // Generated from `Microsoft.Extensions.Primitives.StringSegment` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct StringSegment : System.IEquatable, System.IEquatable { public static bool operator !=(Microsoft.Extensions.Primitives.StringSegment left, Microsoft.Extensions.Primitives.StringSegment right) => throw null; @@ -97,7 +92,6 @@ namespace Microsoft public static implicit operator Microsoft.Extensions.Primitives.StringSegment(string value) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.StringSegmentComparer` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringSegmentComparer : System.Collections.Generic.IComparer, System.Collections.Generic.IEqualityComparer { public int Compare(Microsoft.Extensions.Primitives.StringSegment x, Microsoft.Extensions.Primitives.StringSegment y) => throw null; @@ -107,10 +101,8 @@ namespace Microsoft public static Microsoft.Extensions.Primitives.StringSegmentComparer OrdinalIgnoreCase { get => throw null; } } - // Generated from `Microsoft.Extensions.Primitives.StringTokenizer` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct StringTokenizer : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - // Generated from `Microsoft.Extensions.Primitives.StringTokenizer+Enumerator` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public Microsoft.Extensions.Primitives.StringSegment Current { get => throw null; } @@ -131,10 +123,8 @@ namespace Microsoft public StringTokenizer(string value, System.Char[] separators) => throw null; } - // Generated from `Microsoft.Extensions.Primitives.StringValues` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct StringValues : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable, System.IEquatable, System.IEquatable, System.IEquatable { - // Generated from `Microsoft.Extensions.Primitives.StringValues+Enumerator` in `Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public string Current { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.WebEncoders.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.WebEncoders.cs index bc8e332b8f7..c276b598b64 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.WebEncoders.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Extensions.WebEncoders.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Extensions.WebEncoders, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace DependencyInjection { - // Generated from `Microsoft.Extensions.DependencyInjection.EncoderServiceCollectionExtensions` in `Microsoft.Extensions.WebEncoders, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class EncoderServiceCollectionExtensions { public static Microsoft.Extensions.DependencyInjection.IServiceCollection AddWebEncoders(this Microsoft.Extensions.DependencyInjection.IServiceCollection services) => throw null; @@ -16,7 +16,6 @@ namespace Microsoft } namespace WebEncoders { - // Generated from `Microsoft.Extensions.WebEncoders.WebEncoderOptions` in `Microsoft.Extensions.WebEncoders, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class WebEncoderOptions { public System.Text.Encodings.Web.TextEncoderSettings TextEncoderSettings { get => throw null; set => throw null; } @@ -25,7 +24,6 @@ namespace Microsoft namespace Testing { - // Generated from `Microsoft.Extensions.WebEncoders.Testing.HtmlTestEncoder` in `Microsoft.Extensions.WebEncoders, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class HtmlTestEncoder : System.Text.Encodings.Web.HtmlEncoder { public override void Encode(System.IO.TextWriter output, System.Char[] value, int startIndex, int characterCount) => throw null; @@ -38,7 +36,6 @@ namespace Microsoft public override bool WillEncode(int unicodeScalar) => throw null; } - // Generated from `Microsoft.Extensions.WebEncoders.Testing.JavaScriptTestEncoder` in `Microsoft.Extensions.WebEncoders, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JavaScriptTestEncoder : System.Text.Encodings.Web.JavaScriptEncoder { public override void Encode(System.IO.TextWriter output, System.Char[] value, int startIndex, int characterCount) => throw null; @@ -51,7 +48,6 @@ namespace Microsoft public override bool WillEncode(int unicodeScalar) => throw null; } - // Generated from `Microsoft.Extensions.WebEncoders.Testing.UrlTestEncoder` in `Microsoft.Extensions.WebEncoders, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class UrlTestEncoder : System.Text.Encodings.Web.UrlEncoder { public override void Encode(System.IO.TextWriter output, System.Char[] value, int startIndex, int characterCount) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.JSInterop.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.JSInterop.cs index 3f052a6a8db..9dfd9f3db1a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.JSInterop.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.JSInterop.cs @@ -1,23 +1,21 @@ // This file contains auto-generated code. +// Generated from `Microsoft.JSInterop, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { namespace JSInterop { - // Generated from `Microsoft.JSInterop.DotNetObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DotNetObjectReference { public static Microsoft.JSInterop.DotNetObjectReference Create(TValue value) where TValue : class => throw null; } - // Generated from `Microsoft.JSInterop.DotNetObjectReference<>` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DotNetObjectReference : System.IDisposable where TValue : class { public void Dispose() => throw null; public TValue Value { get => throw null; } } - // Generated from `Microsoft.JSInterop.DotNetStreamReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class DotNetStreamReference : System.IDisposable { public void Dispose() => throw null; @@ -26,40 +24,34 @@ namespace Microsoft public System.IO.Stream Stream { get => throw null; } } - // Generated from `Microsoft.JSInterop.IJSInProcessObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSInProcessObjectReference : Microsoft.JSInterop.IJSObjectReference, System.IAsyncDisposable, System.IDisposable { TValue Invoke(string identifier, params object[] args); } - // Generated from `Microsoft.JSInterop.IJSInProcessRuntime` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSInProcessRuntime : Microsoft.JSInterop.IJSRuntime { TResult Invoke(string identifier, params object[] args); } - // Generated from `Microsoft.JSInterop.IJSObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSObjectReference : System.IAsyncDisposable { System.Threading.Tasks.ValueTask InvokeAsync(string identifier, System.Threading.CancellationToken cancellationToken, object[] args); System.Threading.Tasks.ValueTask InvokeAsync(string identifier, object[] args); } - // Generated from `Microsoft.JSInterop.IJSRuntime` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSRuntime { System.Threading.Tasks.ValueTask InvokeAsync(string identifier, System.Threading.CancellationToken cancellationToken, object[] args); System.Threading.Tasks.ValueTask InvokeAsync(string identifier, object[] args); } - // Generated from `Microsoft.JSInterop.IJSStreamReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSStreamReference : System.IAsyncDisposable { System.Int64 Length { get; } System.Threading.Tasks.ValueTask OpenReadStreamAsync(System.Int64 maxAllowedSize = default(System.Int64), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `Microsoft.JSInterop.IJSUnmarshalledObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSUnmarshalledObjectReference : Microsoft.JSInterop.IJSInProcessObjectReference, Microsoft.JSInterop.IJSObjectReference, System.IAsyncDisposable, System.IDisposable { TResult InvokeUnmarshalled(string identifier, T0 arg0, T1 arg1, T2 arg2); @@ -68,7 +60,6 @@ namespace Microsoft TResult InvokeUnmarshalled(string identifier); } - // Generated from `Microsoft.JSInterop.IJSUnmarshalledRuntime` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSUnmarshalledRuntime { TResult InvokeUnmarshalled(string identifier, T0 arg0, T1 arg1, T2 arg2); @@ -77,7 +68,6 @@ namespace Microsoft TResult InvokeUnmarshalled(string identifier); } - // Generated from `Microsoft.JSInterop.JSCallResultType` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum JSCallResultType : int { Default = 0, @@ -86,26 +76,22 @@ namespace Microsoft JSVoidResult = 3, } - // Generated from `Microsoft.JSInterop.JSDisconnectedException` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSDisconnectedException : System.Exception { public JSDisconnectedException(string message) => throw null; } - // Generated from `Microsoft.JSInterop.JSException` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSException : System.Exception { public JSException(string message) => throw null; public JSException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.JSInterop.JSInProcessObjectReferenceExtensions` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSInProcessObjectReferenceExtensions { public static void InvokeVoid(this Microsoft.JSInterop.IJSInProcessObjectReference jsObjectReference, string identifier, params object[] args) => throw null; } - // Generated from `Microsoft.JSInterop.JSInProcessRuntime` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class JSInProcessRuntime : Microsoft.JSInterop.JSRuntime, Microsoft.JSInterop.IJSInProcessRuntime, Microsoft.JSInterop.IJSRuntime { public TValue Invoke(string identifier, params object[] args) => throw null; @@ -114,13 +100,11 @@ namespace Microsoft protected JSInProcessRuntime() => throw null; } - // Generated from `Microsoft.JSInterop.JSInProcessRuntimeExtensions` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSInProcessRuntimeExtensions { public static void InvokeVoid(this Microsoft.JSInterop.IJSInProcessRuntime jsRuntime, string identifier, params object[] args) => throw null; } - // Generated from `Microsoft.JSInterop.JSInvokableAttribute` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSInvokableAttribute : System.Attribute { public string Identifier { get => throw null; } @@ -128,7 +112,6 @@ namespace Microsoft public JSInvokableAttribute(string identifier) => throw null; } - // Generated from `Microsoft.JSInterop.JSObjectReferenceExtensions` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSObjectReferenceExtensions { public static System.Threading.Tasks.ValueTask InvokeAsync(this Microsoft.JSInterop.IJSObjectReference jsObjectReference, string identifier, System.Threading.CancellationToken cancellationToken, params object[] args) => throw null; @@ -139,7 +122,6 @@ namespace Microsoft public static System.Threading.Tasks.ValueTask InvokeVoidAsync(this Microsoft.JSInterop.IJSObjectReference jsObjectReference, string identifier, params object[] args) => throw null; } - // Generated from `Microsoft.JSInterop.JSRuntime` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public abstract class JSRuntime : Microsoft.JSInterop.IJSRuntime, System.IDisposable { protected virtual void BeginInvokeJS(System.Int64 taskId, string identifier, string argsJson) => throw null; @@ -157,7 +139,6 @@ namespace Microsoft protected internal virtual System.Threading.Tasks.Task TransmitStreamAsync(System.Int64 streamId, Microsoft.JSInterop.DotNetStreamReference dotNetStreamReference) => throw null; } - // Generated from `Microsoft.JSInterop.JSRuntimeExtensions` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSRuntimeExtensions { public static System.Threading.Tasks.ValueTask InvokeAsync(this Microsoft.JSInterop.IJSRuntime jsRuntime, string identifier, System.Threading.CancellationToken cancellationToken, params object[] args) => throw null; @@ -170,7 +151,6 @@ namespace Microsoft namespace Implementation { - // Generated from `Microsoft.JSInterop.Implementation.JSInProcessObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSInProcessObjectReference : Microsoft.JSInterop.Implementation.JSObjectReference, Microsoft.JSInterop.IJSInProcessObjectReference, Microsoft.JSInterop.IJSObjectReference, System.IAsyncDisposable, System.IDisposable { public void Dispose() => throw null; @@ -178,7 +158,6 @@ namespace Microsoft protected internal JSInProcessObjectReference(Microsoft.JSInterop.JSInProcessRuntime jsRuntime, System.Int64 id) : base(default(Microsoft.JSInterop.JSRuntime), default(System.Int64)) => throw null; } - // Generated from `Microsoft.JSInterop.Implementation.JSObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSObjectReference : Microsoft.JSInterop.IJSObjectReference, System.IAsyncDisposable { public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; @@ -189,14 +168,12 @@ namespace Microsoft protected void ThrowIfDisposed() => throw null; } - // Generated from `Microsoft.JSInterop.Implementation.JSObjectReferenceJsonWorker` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class JSObjectReferenceJsonWorker { public static System.Int64 ReadJSObjectReferenceIdentifier(ref System.Text.Json.Utf8JsonReader reader) => throw null; public static void WriteJSObjectReference(System.Text.Json.Utf8JsonWriter writer, Microsoft.JSInterop.Implementation.JSObjectReference objectReference) => throw null; } - // Generated from `Microsoft.JSInterop.Implementation.JSStreamReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class JSStreamReference : Microsoft.JSInterop.Implementation.JSObjectReference, Microsoft.JSInterop.IJSStreamReference, System.IAsyncDisposable { internal JSStreamReference(Microsoft.JSInterop.JSRuntime jsRuntime, System.Int64 id, System.Int64 totalLength) : base(default(Microsoft.JSInterop.JSRuntime), default(System.Int64)) => throw null; @@ -207,7 +184,6 @@ namespace Microsoft } namespace Infrastructure { - // Generated from `Microsoft.JSInterop.Infrastructure.DotNetDispatcher` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class DotNetDispatcher { public static void BeginInvokeDotNet(Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) => throw null; @@ -216,7 +192,6 @@ namespace Microsoft public static void ReceiveByteArray(Microsoft.JSInterop.JSRuntime jsRuntime, int id, System.Byte[] data) => throw null; } - // Generated from `Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct DotNetInvocationInfo { public string AssemblyName { get => throw null; } @@ -227,7 +202,6 @@ namespace Microsoft public string MethodIdentifier { get => throw null; } } - // Generated from `Microsoft.JSInterop.Infrastructure.DotNetInvocationResult` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public struct DotNetInvocationResult { // Stub generator skipped constructor @@ -237,12 +211,10 @@ namespace Microsoft public bool Success { get => throw null; } } - // Generated from `Microsoft.JSInterop.Infrastructure.IDotNetObjectReference` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` internal interface IDotNetObjectReference : System.IDisposable { } - // Generated from `Microsoft.JSInterop.Infrastructure.IJSVoidResult` in `Microsoft.JSInterop, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public interface IJSVoidResult { } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Net.Http.Headers.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Net.Http.Headers.cs index 4ea5349a8a5..313c38fbba1 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Net.Http.Headers.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/Microsoft.Net.Http.Headers.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Net.Http.Headers, Version=7.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60`. namespace Microsoft { @@ -8,7 +9,6 @@ namespace Microsoft { namespace Headers { - // Generated from `Microsoft.Net.Http.Headers.CacheControlHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CacheControlHeaderValue { public CacheControlHeaderValue() => throw null; @@ -47,7 +47,6 @@ namespace Microsoft public static bool TryParse(Microsoft.Extensions.Primitives.StringSegment input, out Microsoft.Net.Http.Headers.CacheControlHeaderValue parsedValue) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.ContentDispositionHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ContentDispositionHeaderValue { public ContentDispositionHeaderValue(Microsoft.Extensions.Primitives.StringSegment dispositionType) => throw null; @@ -69,14 +68,12 @@ namespace Microsoft public static bool TryParse(Microsoft.Extensions.Primitives.StringSegment input, out Microsoft.Net.Http.Headers.ContentDispositionHeaderValue parsedValue) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.ContentDispositionHeaderValueIdentityExtensions` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class ContentDispositionHeaderValueIdentityExtensions { public static bool IsFileDisposition(this Microsoft.Net.Http.Headers.ContentDispositionHeaderValue header) => throw null; public static bool IsFormDisposition(this Microsoft.Net.Http.Headers.ContentDispositionHeaderValue header) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.ContentRangeHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class ContentRangeHeaderValue { public ContentRangeHeaderValue(System.Int64 length) => throw null; @@ -95,7 +92,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Unit { get => throw null; set => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.CookieHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class CookieHeaderValue { public CookieHeaderValue(Microsoft.Extensions.Primitives.StringSegment name) => throw null; @@ -113,7 +109,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.EntityTagHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class EntityTagHeaderValue { public static Microsoft.Net.Http.Headers.EntityTagHeaderValue Any { get => throw null; } @@ -133,7 +128,6 @@ namespace Microsoft public static bool TryParseStrictList(System.Collections.Generic.IList inputs, out System.Collections.Generic.IList parsedValues) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.HeaderNames` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HeaderNames { public static string Accept; @@ -234,14 +228,12 @@ namespace Microsoft public static string XXSSProtection; } - // Generated from `Microsoft.Net.Http.Headers.HeaderQuality` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HeaderQuality { public const double Match = default; public const double NoMatch = default; } - // Generated from `Microsoft.Net.Http.Headers.HeaderUtilities` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public static class HeaderUtilities { public static bool ContainsCacheDirective(Microsoft.Extensions.Primitives.StringValues cacheControlDirectives, string targetDirectives) => throw null; @@ -258,7 +250,6 @@ namespace Microsoft public static Microsoft.Extensions.Primitives.StringSegment UnescapeAsQuotedString(Microsoft.Extensions.Primitives.StringSegment input) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.MediaTypeHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MediaTypeHeaderValue { public Microsoft.Extensions.Primitives.StringSegment Boundary { get => throw null; set => throw null; } @@ -293,14 +284,12 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Type { get => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.MediaTypeHeaderValueComparer` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class MediaTypeHeaderValueComparer : System.Collections.Generic.IComparer { public int Compare(Microsoft.Net.Http.Headers.MediaTypeHeaderValue mediaType1, Microsoft.Net.Http.Headers.MediaTypeHeaderValue mediaType2) => throw null; public static Microsoft.Net.Http.Headers.MediaTypeHeaderValueComparer QualityComparer { get => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.NameValueHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class NameValueHeaderValue { public Microsoft.Net.Http.Headers.NameValueHeaderValue Copy() => throw null; @@ -324,7 +313,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.RangeConditionHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RangeConditionHeaderValue { public Microsoft.Net.Http.Headers.EntityTagHeaderValue EntityTag { get => throw null; } @@ -339,7 +327,6 @@ namespace Microsoft public static bool TryParse(Microsoft.Extensions.Primitives.StringSegment input, out Microsoft.Net.Http.Headers.RangeConditionHeaderValue parsedValue) => throw null; } - // Generated from `Microsoft.Net.Http.Headers.RangeHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RangeHeaderValue { public override bool Equals(object obj) => throw null; @@ -353,7 +340,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Unit { get => throw null; set => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.RangeItemHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class RangeItemHeaderValue { public override bool Equals(object obj) => throw null; @@ -364,7 +350,6 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.Net.Http.Headers.SameSiteMode` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public enum SameSiteMode : int { Lax = 1, @@ -373,7 +358,6 @@ namespace Microsoft Unspecified = -1, } - // Generated from `Microsoft.Net.Http.Headers.SetCookieHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class SetCookieHeaderValue { public void AppendToStringBuilder(System.Text.StringBuilder builder) => throw null; @@ -400,7 +384,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Value { get => throw null; set => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.StringWithQualityHeaderValue` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringWithQualityHeaderValue { public override bool Equals(object obj) => throw null; @@ -418,7 +401,6 @@ namespace Microsoft public Microsoft.Extensions.Primitives.StringSegment Value { get => throw null; } } - // Generated from `Microsoft.Net.Http.Headers.StringWithQualityHeaderValueComparer` in `Microsoft.Net.Http.Headers, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60` public class StringWithQualityHeaderValueComparer : System.Collections.Generic.IComparer { public int Compare(Microsoft.Net.Http.Headers.StringWithQualityHeaderValue stringWithQuality1, Microsoft.Net.Http.Headers.StringWithQualityHeaderValue stringWithQuality2) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Diagnostics.EventLog.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Diagnostics.EventLog.cs index 18c944f39dd..95b5a1e0111 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Diagnostics.EventLog.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Diagnostics.EventLog.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.EventLog, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.EntryWrittenEventArgs` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EntryWrittenEventArgs : System.EventArgs { public System.Diagnostics.EventLogEntry Entry { get => throw null; } @@ -12,10 +12,8 @@ namespace System public EntryWrittenEventArgs(System.Diagnostics.EventLogEntry entry) => throw null; } - // Generated from `System.Diagnostics.EntryWrittenEventHandler` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void EntryWrittenEventHandler(object sender, System.Diagnostics.EntryWrittenEventArgs e); - // Generated from `System.Diagnostics.EventInstance` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventInstance { public int CategoryId { get => throw null; set => throw null; } @@ -25,7 +23,6 @@ namespace System public System.Int64 InstanceId { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.EventLog` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLog : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize { public void BeginInit() => throw null; @@ -80,7 +77,6 @@ namespace System public static void WriteEvent(string source, System.Diagnostics.EventInstance instance, params object[] values) => throw null; } - // Generated from `System.Diagnostics.EventLogEntry` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogEntry : System.ComponentModel.Component, System.Runtime.Serialization.ISerializable { public string Category { get => throw null; } @@ -101,7 +97,6 @@ namespace System public string UserName { get => throw null; } } - // Generated from `System.Diagnostics.EventLogEntryCollection` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogEntryCollection : System.Collections.ICollection, System.Collections.IEnumerable { void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; @@ -113,7 +108,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Diagnostics.EventLogEntryType` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum EventLogEntryType : int { Error = 1, @@ -123,7 +117,6 @@ namespace System Warning = 2, } - // Generated from `System.Diagnostics.EventLogTraceListener` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogTraceListener : System.Diagnostics.TraceListener { public override void Close() => throw null; @@ -141,7 +134,6 @@ namespace System public override void WriteLine(string message) => throw null; } - // Generated from `System.Diagnostics.EventSourceCreationData` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventSourceCreationData { public int CategoryCount { get => throw null; set => throw null; } @@ -154,7 +146,6 @@ namespace System public string Source { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.OverflowAction` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum OverflowAction : int { DoNotOverwrite = -1, @@ -166,12 +157,12 @@ namespace System { namespace Reader { - // Generated from `System.Diagnostics.Eventing.Reader.EventBookmark` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventBookmark { + public string BookmarkXml { get => throw null; } + public EventBookmark(string bookmarkXml) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventKeyword` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventKeyword { public string DisplayName { get => throw null; } @@ -179,7 +170,6 @@ namespace System public System.Int64 Value { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLevel` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLevel { public string DisplayName { get => throw null; } @@ -187,7 +177,6 @@ namespace System public int Value { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogConfiguration` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogConfiguration : System.IDisposable { public void Dispose() => throw null; @@ -215,7 +204,6 @@ namespace System public string SecurityDescriptor { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogException` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogException : System.Exception { public EventLogException() => throw null; @@ -227,7 +215,6 @@ namespace System public override string Message { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogInformation` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogInformation { public int? Attributes { get => throw null; } @@ -240,7 +227,6 @@ namespace System public System.Int64? RecordCount { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogInvalidDataException` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogInvalidDataException : System.Diagnostics.Eventing.Reader.EventLogException { public EventLogInvalidDataException() => throw null; @@ -249,7 +235,6 @@ namespace System public EventLogInvalidDataException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogIsolation` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum EventLogIsolation : int { Application = 0, @@ -257,7 +242,6 @@ namespace System System = 1, } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogLink` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogLink { public string DisplayName { get => throw null; } @@ -265,7 +249,6 @@ namespace System public string LogName { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogMode` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum EventLogMode : int { AutoBackup = 1, @@ -273,7 +256,6 @@ namespace System Retain = 2, } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogNotFoundException` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogNotFoundException : System.Diagnostics.Eventing.Reader.EventLogException { public EventLogNotFoundException() => throw null; @@ -282,7 +264,6 @@ namespace System public EventLogNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogPropertySelector` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogPropertySelector : System.IDisposable { public void Dispose() => throw null; @@ -290,7 +271,6 @@ namespace System public EventLogPropertySelector(System.Collections.Generic.IEnumerable propertyQueries) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogProviderDisabledException` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogProviderDisabledException : System.Diagnostics.Eventing.Reader.EventLogException { public EventLogProviderDisabledException() => throw null; @@ -299,7 +279,6 @@ namespace System public EventLogProviderDisabledException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogQuery` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogQuery { public EventLogQuery(string path, System.Diagnostics.Eventing.Reader.PathType pathType) => throw null; @@ -309,7 +288,6 @@ namespace System public bool TolerateQueryErrors { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogReader` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogReader : System.IDisposable { public int BatchSize { get => throw null; set => throw null; } @@ -328,7 +306,6 @@ namespace System public void Seek(System.IO.SeekOrigin origin, System.Int64 offset) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogReadingException` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogReadingException : System.Diagnostics.Eventing.Reader.EventLogException { public EventLogReadingException() => throw null; @@ -337,7 +314,6 @@ namespace System public EventLogReadingException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogRecord` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogRecord : System.Diagnostics.Eventing.Reader.EventRecord { public override System.Guid? ActivityId { get => throw null; } @@ -373,7 +349,6 @@ namespace System public override System.Byte? Version { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogSession` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogSession : System.IDisposable { public void CancelCurrentOperations() => throw null; @@ -394,14 +369,12 @@ namespace System public static System.Diagnostics.Eventing.Reader.EventLogSession GlobalSession { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogStatus` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogStatus { public string LogName { get => throw null; } public int StatusCode { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogType` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum EventLogType : int { Administrative = 0, @@ -410,7 +383,6 @@ namespace System Operational = 1, } - // Generated from `System.Diagnostics.Eventing.Reader.EventLogWatcher` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventLogWatcher : System.IDisposable { public void Dispose() => throw null; @@ -423,7 +395,6 @@ namespace System public event System.EventHandler EventRecordWritten; } - // Generated from `System.Diagnostics.Eventing.Reader.EventMetadata` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventMetadata { public string Description { get => throw null; } @@ -437,7 +408,6 @@ namespace System public System.Byte Version { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventOpcode` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventOpcode { public string DisplayName { get => throw null; } @@ -445,13 +415,11 @@ namespace System public int Value { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventProperty` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventProperty { public object Value { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventRecord` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class EventRecord : System.IDisposable { public abstract System.Guid? ActivityId { get; } @@ -486,14 +454,12 @@ namespace System public abstract System.Byte? Version { get; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventRecordWrittenEventArgs` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventRecordWrittenEventArgs : System.EventArgs { public System.Exception EventException { get => throw null; } public System.Diagnostics.Eventing.Reader.EventRecord EventRecord { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.EventTask` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EventTask { public string DisplayName { get => throw null; } @@ -502,14 +468,12 @@ namespace System public int Value { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.PathType` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum PathType : int { FilePath = 2, LogName = 1, } - // Generated from `System.Diagnostics.Eventing.Reader.ProviderMetadata` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ProviderMetadata : System.IDisposable { public string DisplayName { get => throw null; } @@ -531,7 +495,6 @@ namespace System public System.Collections.Generic.IList Tasks { get => throw null; } } - // Generated from `System.Diagnostics.Eventing.Reader.SessionAuthentication` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum SessionAuthentication : int { Default = 0, @@ -540,7 +503,6 @@ namespace System Ntlm = 3, } - // Generated from `System.Diagnostics.Eventing.Reader.StandardEventKeywords` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum StandardEventKeywords : long { @@ -556,7 +518,6 @@ namespace System WdiDiagnostic = 1125899906842624, } - // Generated from `System.Diagnostics.Eventing.Reader.StandardEventLevel` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum StandardEventLevel : int { Critical = 1, @@ -567,7 +528,6 @@ namespace System Warning = 3, } - // Generated from `System.Diagnostics.Eventing.Reader.StandardEventOpcode` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum StandardEventOpcode : int { DataCollectionStart = 3, @@ -583,7 +543,6 @@ namespace System Suspend = 8, } - // Generated from `System.Diagnostics.Eventing.Reader.StandardEventTask` in `System.Diagnostics.EventLog, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum StandardEventTask : int { None = 0, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.IO.Pipelines.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.IO.Pipelines.cs index b6ac93159af..9bba4b098f2 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.IO.Pipelines.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.IO.Pipelines.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Pipelines, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Pipelines { - // Generated from `System.IO.Pipelines.FlushResult` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct FlushResult { // Stub generator skipped constructor @@ -15,14 +15,12 @@ namespace System public bool IsCompleted { get => throw null; } } - // Generated from `System.IO.Pipelines.IDuplexPipe` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IDuplexPipe { System.IO.Pipelines.PipeReader Input { get; } System.IO.Pipelines.PipeWriter Output { get; } } - // Generated from `System.IO.Pipelines.Pipe` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Pipe { public Pipe() => throw null; @@ -32,7 +30,6 @@ namespace System public System.IO.Pipelines.PipeWriter Writer { get => throw null; } } - // Generated from `System.IO.Pipelines.PipeOptions` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class PipeOptions { public static System.IO.Pipelines.PipeOptions Default { get => throw null; } @@ -46,7 +43,6 @@ namespace System public System.IO.Pipelines.PipeScheduler WriterScheduler { get => throw null; } } - // Generated from `System.IO.Pipelines.PipeReader` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class PipeReader { public abstract void AdvanceTo(System.SequencePosition consumed); @@ -67,7 +63,6 @@ namespace System public abstract bool TryRead(out System.IO.Pipelines.ReadResult result); } - // Generated from `System.IO.Pipelines.PipeScheduler` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class PipeScheduler { public static System.IO.Pipelines.PipeScheduler Inline { get => throw null; } @@ -76,7 +71,6 @@ namespace System public static System.IO.Pipelines.PipeScheduler ThreadPool { get => throw null; } } - // Generated from `System.IO.Pipelines.PipeWriter` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class PipeWriter : System.Buffers.IBufferWriter { public abstract void Advance(int bytes); @@ -96,7 +90,6 @@ namespace System public virtual System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.IO.Pipelines.ReadResult` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ReadResult { public System.Buffers.ReadOnlySequence Buffer { get => throw null; } @@ -106,13 +99,11 @@ namespace System public ReadResult(System.Buffers.ReadOnlySequence buffer, bool isCanceled, bool isCompleted) => throw null; } - // Generated from `System.IO.Pipelines.StreamPipeExtensions` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class StreamPipeExtensions { public static System.Threading.Tasks.Task CopyToAsync(this System.IO.Stream source, System.IO.Pipelines.PipeWriter destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.IO.Pipelines.StreamPipeReaderOptions` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class StreamPipeReaderOptions { public int BufferSize { get => throw null; } @@ -124,7 +115,6 @@ namespace System public bool UseZeroByteReads { get => throw null; } } - // Generated from `System.IO.Pipelines.StreamPipeWriterOptions` in `System.IO.Pipelines, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class StreamPipeWriterOptions { public bool LeaveOpen { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Security.Cryptography.Xml.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Security.Cryptography.Xml.cs index d8e56df70fb..b47994b9b08 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Security.Cryptography.Xml.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Security.Cryptography.Xml.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Security.Cryptography.Xml, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -8,7 +9,6 @@ namespace System { namespace Xml { - // Generated from `System.Security.Cryptography.Xml.CipherData` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class CipherData { public CipherData() => throw null; @@ -20,7 +20,6 @@ namespace System public void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.CipherReference` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class CipherReference : System.Security.Cryptography.Xml.EncryptedReference { public CipherReference() => throw null; @@ -30,7 +29,6 @@ namespace System public override void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.DSAKeyValue` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DSAKeyValue : System.Security.Cryptography.Xml.KeyInfoClause { public DSAKeyValue() => throw null; @@ -40,7 +38,6 @@ namespace System public override void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.DataObject` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DataObject { public System.Xml.XmlNodeList Data { get => throw null; set => throw null; } @@ -53,7 +50,6 @@ namespace System public string MimeType { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.DataReference` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DataReference : System.Security.Cryptography.Xml.EncryptedReference { public DataReference() => throw null; @@ -61,7 +57,6 @@ namespace System public DataReference(string uri, System.Security.Cryptography.Xml.TransformChain transformChain) => throw null; } - // Generated from `System.Security.Cryptography.Xml.EncryptedData` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptedData : System.Security.Cryptography.Xml.EncryptedType { public EncryptedData() => throw null; @@ -69,7 +64,6 @@ namespace System public override void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.EncryptedKey` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptedKey : System.Security.Cryptography.Xml.EncryptedType { public void AddReference(System.Security.Cryptography.Xml.DataReference dataReference) => throw null; @@ -82,7 +76,6 @@ namespace System public System.Security.Cryptography.Xml.ReferenceList ReferenceList { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.EncryptedReference` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class EncryptedReference { public void AddTransform(System.Security.Cryptography.Xml.Transform transform) => throw null; @@ -97,7 +90,6 @@ namespace System public string Uri { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.EncryptedType` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class EncryptedType { public void AddProperty(System.Security.Cryptography.Xml.EncryptionProperty ep) => throw null; @@ -114,7 +106,6 @@ namespace System public virtual string Type { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.EncryptedXml` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptedXml { public void AddKeyNameMapping(string keyName, object keyObject) => throw null; @@ -164,7 +155,6 @@ namespace System public const string XmlEncTripleDESUrl = default; } - // Generated from `System.Security.Cryptography.Xml.EncryptionMethod` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptionMethod { public EncryptionMethod() => throw null; @@ -175,7 +165,6 @@ namespace System public void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.EncryptionProperty` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptionProperty { public EncryptionProperty() => throw null; @@ -187,7 +176,6 @@ namespace System public string Target { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.EncryptionPropertyCollection` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class EncryptionPropertyCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public int Add(System.Security.Cryptography.Xml.EncryptionProperty value) => throw null; @@ -217,13 +205,11 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.IRelDecryptor` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IRelDecryptor { System.IO.Stream Decrypt(System.Security.Cryptography.Xml.EncryptionMethod encryptionMethod, System.Security.Cryptography.Xml.KeyInfo keyInfo, System.IO.Stream toDecrypt); } - // Generated from `System.Security.Cryptography.Xml.KeyInfo` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfo : System.Collections.IEnumerable { public void AddClause(System.Security.Cryptography.Xml.KeyInfoClause clause) => throw null; @@ -236,7 +222,6 @@ namespace System public void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.KeyInfoClause` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class KeyInfoClause { public abstract System.Xml.XmlElement GetXml(); @@ -244,7 +229,6 @@ namespace System public abstract void LoadXml(System.Xml.XmlElement element); } - // Generated from `System.Security.Cryptography.Xml.KeyInfoEncryptedKey` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfoEncryptedKey : System.Security.Cryptography.Xml.KeyInfoClause { public System.Security.Cryptography.Xml.EncryptedKey EncryptedKey { get => throw null; set => throw null; } @@ -254,7 +238,6 @@ namespace System public override void LoadXml(System.Xml.XmlElement value) => throw null; } - // Generated from `System.Security.Cryptography.Xml.KeyInfoName` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfoName : System.Security.Cryptography.Xml.KeyInfoClause { public override System.Xml.XmlElement GetXml() => throw null; @@ -264,7 +247,6 @@ namespace System public string Value { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.KeyInfoNode` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfoNode : System.Security.Cryptography.Xml.KeyInfoClause { public override System.Xml.XmlElement GetXml() => throw null; @@ -274,7 +256,6 @@ namespace System public System.Xml.XmlElement Value { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.KeyInfoRetrievalMethod` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfoRetrievalMethod : System.Security.Cryptography.Xml.KeyInfoClause { public override System.Xml.XmlElement GetXml() => throw null; @@ -286,7 +267,6 @@ namespace System public string Uri { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.KeyInfoX509Data` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyInfoX509Data : System.Security.Cryptography.Xml.KeyInfoClause { public void AddCertificate(System.Security.Cryptography.X509Certificates.X509Certificate certificate) => throw null; @@ -307,7 +287,6 @@ namespace System public System.Collections.ArrayList SubjectNames { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.KeyReference` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class KeyReference : System.Security.Cryptography.Xml.EncryptedReference { public KeyReference() => throw null; @@ -315,7 +294,6 @@ namespace System public KeyReference(string uri, System.Security.Cryptography.Xml.TransformChain transformChain) => throw null; } - // Generated from `System.Security.Cryptography.Xml.RSAKeyValue` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class RSAKeyValue : System.Security.Cryptography.Xml.KeyInfoClause { public override System.Xml.XmlElement GetXml() => throw null; @@ -325,7 +303,6 @@ namespace System public RSAKeyValue(System.Security.Cryptography.RSA key) => throw null; } - // Generated from `System.Security.Cryptography.Xml.Reference` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Reference { public void AddTransform(System.Security.Cryptography.Xml.Transform transform) => throw null; @@ -342,7 +319,6 @@ namespace System public string Uri { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.ReferenceList` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ReferenceList : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public int Add(object value) => throw null; @@ -366,7 +342,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.Signature` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Signature { public void AddObject(System.Security.Cryptography.Xml.DataObject dataObject) => throw null; @@ -380,7 +355,6 @@ namespace System public System.Security.Cryptography.Xml.SignedInfo SignedInfo { get => throw null; set => throw null; } } - // Generated from `System.Security.Cryptography.Xml.SignedInfo` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SignedInfo : System.Collections.ICollection, System.Collections.IEnumerable { public void AddReference(System.Security.Cryptography.Xml.Reference reference) => throw null; @@ -401,7 +375,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Security.Cryptography.Xml.SignedXml` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SignedXml { public void AddObject(System.Security.Cryptography.Xml.DataObject dataObject) => throw null; @@ -460,7 +433,6 @@ namespace System protected string m_strSigningKeyName; } - // Generated from `System.Security.Cryptography.Xml.Transform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Transform { public string Algorithm { get => throw null; set => throw null; } @@ -479,7 +451,6 @@ namespace System protected Transform() => throw null; } - // Generated from `System.Security.Cryptography.Xml.TransformChain` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransformChain { public void Add(System.Security.Cryptography.Xml.Transform transform) => throw null; @@ -489,7 +460,6 @@ namespace System public TransformChain() => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDecryptionTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDecryptionTransform : System.Security.Cryptography.Xml.Transform { public void AddExceptUri(string uri) => throw null; @@ -505,7 +475,6 @@ namespace System public XmlDecryptionTransform() => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigBase64Transform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigBase64Transform : System.Security.Cryptography.Xml.Transform { protected override System.Xml.XmlNodeList GetInnerXml() => throw null; @@ -518,7 +487,6 @@ namespace System public XmlDsigBase64Transform() => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigC14NTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigC14NTransform : System.Security.Cryptography.Xml.Transform { public override System.Byte[] GetDigestedOutput(System.Security.Cryptography.HashAlgorithm hash) => throw null; @@ -533,13 +501,11 @@ namespace System public XmlDsigC14NTransform(bool includeComments) => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigC14NWithCommentsTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigC14NWithCommentsTransform : System.Security.Cryptography.Xml.XmlDsigC14NTransform { public XmlDsigC14NWithCommentsTransform() => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigEnvelopedSignatureTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigEnvelopedSignatureTransform : System.Security.Cryptography.Xml.Transform { protected override System.Xml.XmlNodeList GetInnerXml() => throw null; @@ -553,7 +519,6 @@ namespace System public XmlDsigEnvelopedSignatureTransform(bool includeComments) => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigExcC14NTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigExcC14NTransform : System.Security.Cryptography.Xml.Transform { public override System.Byte[] GetDigestedOutput(System.Security.Cryptography.HashAlgorithm hash) => throw null; @@ -571,14 +536,12 @@ namespace System public XmlDsigExcC14NTransform(string inclusiveNamespacesPrefixList) => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigExcC14NWithCommentsTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigExcC14NWithCommentsTransform : System.Security.Cryptography.Xml.XmlDsigExcC14NTransform { public XmlDsigExcC14NWithCommentsTransform() => throw null; public XmlDsigExcC14NWithCommentsTransform(string inclusiveNamespacesPrefixList) => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigXPathTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigXPathTransform : System.Security.Cryptography.Xml.Transform { protected override System.Xml.XmlNodeList GetInnerXml() => throw null; @@ -591,7 +554,6 @@ namespace System public XmlDsigXPathTransform() => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlDsigXsltTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlDsigXsltTransform : System.Security.Cryptography.Xml.Transform { protected override System.Xml.XmlNodeList GetInnerXml() => throw null; @@ -605,7 +567,6 @@ namespace System public XmlDsigXsltTransform(bool includeComments) => throw null; } - // Generated from `System.Security.Cryptography.Xml.XmlLicenseTransform` in `System.Security.Cryptography.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class XmlLicenseTransform : System.Security.Cryptography.Xml.Transform { public System.Security.Cryptography.Xml.IRelDecryptor Decryptor { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Threading.RateLimiting.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Threading.RateLimiting.cs new file mode 100644 index 00000000000..dfad6d3fa06 --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.AspNetCore.App/System.Threading.RateLimiting.cs @@ -0,0 +1,213 @@ +// This file contains auto-generated code. +// Generated from `System.Threading.RateLimiting, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. + +namespace System +{ + namespace Threading + { + namespace RateLimiting + { + public class ConcurrencyLimiter : System.Threading.RateLimiting.RateLimiter + { + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount) => throw null; + public ConcurrencyLimiter(System.Threading.RateLimiting.ConcurrencyLimiterOptions options) => throw null; + protected override void Dispose(bool disposing) => throw null; + protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public override System.Threading.RateLimiting.RateLimiterStatistics GetStatistics() => throw null; + public override System.TimeSpan? IdleDuration { get => throw null; } + } + + public class ConcurrencyLimiterOptions + { + public ConcurrencyLimiterOptions() => throw null; + public int PermitLimit { get => throw null; set => throw null; } + public int QueueLimit { get => throw null; set => throw null; } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get => throw null; set => throw null; } + } + + public class FixedWindowRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter + { + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount) => throw null; + protected override void Dispose(bool disposing) => throw null; + protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public FixedWindowRateLimiter(System.Threading.RateLimiting.FixedWindowRateLimiterOptions options) => throw null; + public override System.Threading.RateLimiting.RateLimiterStatistics GetStatistics() => throw null; + public override System.TimeSpan? IdleDuration { get => throw null; } + public override bool IsAutoReplenishing { get => throw null; } + public override System.TimeSpan ReplenishmentPeriod { get => throw null; } + public override bool TryReplenish() => throw null; + } + + public class FixedWindowRateLimiterOptions + { + public bool AutoReplenishment { get => throw null; set => throw null; } + public FixedWindowRateLimiterOptions() => throw null; + public int PermitLimit { get => throw null; set => throw null; } + public int QueueLimit { get => throw null; set => throw null; } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get => throw null; set => throw null; } + public System.TimeSpan Window { get => throw null; set => throw null; } + } + + public static class MetadataName + { + public static System.Threading.RateLimiting.MetadataName Create(string name) => throw null; + public static System.Threading.RateLimiting.MetadataName ReasonPhrase { get => throw null; } + public static System.Threading.RateLimiting.MetadataName RetryAfter { get => throw null; } + } + + public class MetadataName : System.IEquatable> + { + public static bool operator !=(System.Threading.RateLimiting.MetadataName left, System.Threading.RateLimiting.MetadataName right) => throw null; + public static bool operator ==(System.Threading.RateLimiting.MetadataName left, System.Threading.RateLimiting.MetadataName right) => throw null; + public bool Equals(System.Threading.RateLimiting.MetadataName other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public MetadataName(string name) => throw null; + public string Name { get => throw null; } + public override string ToString() => throw null; + } + + public static class PartitionedRateLimiter + { + public static System.Threading.RateLimiting.PartitionedRateLimiter Create(System.Func> partitioner, System.Collections.Generic.IEqualityComparer equalityComparer = default(System.Collections.Generic.IEqualityComparer)) => throw null; + public static System.Threading.RateLimiting.PartitionedRateLimiter CreateChained(params System.Threading.RateLimiting.PartitionedRateLimiter[] limiters) => throw null; + } + + public abstract class PartitionedRateLimiter : System.IAsyncDisposable, System.IDisposable + { + public System.Threading.Tasks.ValueTask AcquireAsync(TResource resource, int permitCount = default(int), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected abstract System.Threading.Tasks.ValueTask AcquireAsyncCore(TResource resource, int permitCount, System.Threading.CancellationToken cancellationToken); + public System.Threading.RateLimiting.RateLimitLease AttemptAcquire(TResource resource, int permitCount = default(int)) => throw null; + protected abstract System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(TResource resource, int permitCount); + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + protected virtual System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public abstract System.Threading.RateLimiting.RateLimiterStatistics GetStatistics(TResource resource); + protected PartitionedRateLimiter() => throw null; + public System.Threading.RateLimiting.PartitionedRateLimiter WithTranslatedKey(System.Func keyAdapter, bool leaveOpen) => throw null; + } + + public enum QueueProcessingOrder : int + { + NewestFirst = 1, + OldestFirst = 0, + } + + public abstract class RateLimitLease : System.IDisposable + { + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public virtual System.Collections.Generic.IEnumerable> GetAllMetadata() => throw null; + public abstract bool IsAcquired { get; } + public abstract System.Collections.Generic.IEnumerable MetadataNames { get; } + protected RateLimitLease() => throw null; + public abstract bool TryGetMetadata(string metadataName, out object metadata); + public bool TryGetMetadata(System.Threading.RateLimiting.MetadataName metadataName, out T metadata) => throw null; + } + + public static class RateLimitPartition + { + public static System.Threading.RateLimiting.RateLimitPartition Get(TKey partitionKey, System.Func factory) => throw null; + public static System.Threading.RateLimiting.RateLimitPartition GetConcurrencyLimiter(TKey partitionKey, System.Func factory) => throw null; + public static System.Threading.RateLimiting.RateLimitPartition GetFixedWindowLimiter(TKey partitionKey, System.Func factory) => throw null; + public static System.Threading.RateLimiting.RateLimitPartition GetNoLimiter(TKey partitionKey) => throw null; + public static System.Threading.RateLimiting.RateLimitPartition GetSlidingWindowLimiter(TKey partitionKey, System.Func factory) => throw null; + public static System.Threading.RateLimiting.RateLimitPartition GetTokenBucketLimiter(TKey partitionKey, System.Func factory) => throw null; + } + + public struct RateLimitPartition + { + public System.Func Factory { get => throw null; } + public TKey PartitionKey { get => throw null; } + // Stub generator skipped constructor + public RateLimitPartition(TKey partitionKey, System.Func factory) => throw null; + } + + public abstract class RateLimiter : System.IAsyncDisposable, System.IDisposable + { + public System.Threading.Tasks.ValueTask AcquireAsync(int permitCount = default(int), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected abstract System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken); + public System.Threading.RateLimiting.RateLimitLease AttemptAcquire(int permitCount = default(int)) => throw null; + protected abstract System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount); + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + protected virtual System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public abstract System.Threading.RateLimiting.RateLimiterStatistics GetStatistics(); + public abstract System.TimeSpan? IdleDuration { get; } + protected RateLimiter() => throw null; + } + + public class RateLimiterStatistics + { + public System.Int64 CurrentAvailablePermits { get => throw null; set => throw null; } + public System.Int64 CurrentQueuedCount { get => throw null; set => throw null; } + public RateLimiterStatistics() => throw null; + public System.Int64 TotalFailedLeases { get => throw null; set => throw null; } + public System.Int64 TotalSuccessfulLeases { get => throw null; set => throw null; } + } + + public abstract class ReplenishingRateLimiter : System.Threading.RateLimiting.RateLimiter + { + public abstract bool IsAutoReplenishing { get; } + protected ReplenishingRateLimiter() => throw null; + public abstract System.TimeSpan ReplenishmentPeriod { get; } + public abstract bool TryReplenish(); + } + + public class SlidingWindowRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter + { + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int permitCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int permitCount) => throw null; + protected override void Dispose(bool disposing) => throw null; + protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public override System.Threading.RateLimiting.RateLimiterStatistics GetStatistics() => throw null; + public override System.TimeSpan? IdleDuration { get => throw null; } + public override bool IsAutoReplenishing { get => throw null; } + public override System.TimeSpan ReplenishmentPeriod { get => throw null; } + public SlidingWindowRateLimiter(System.Threading.RateLimiting.SlidingWindowRateLimiterOptions options) => throw null; + public override bool TryReplenish() => throw null; + } + + public class SlidingWindowRateLimiterOptions + { + public bool AutoReplenishment { get => throw null; set => throw null; } + public int PermitLimit { get => throw null; set => throw null; } + public int QueueLimit { get => throw null; set => throw null; } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get => throw null; set => throw null; } + public int SegmentsPerWindow { get => throw null; set => throw null; } + public SlidingWindowRateLimiterOptions() => throw null; + public System.TimeSpan Window { get => throw null; set => throw null; } + } + + public class TokenBucketRateLimiter : System.Threading.RateLimiting.ReplenishingRateLimiter + { + protected override System.Threading.Tasks.ValueTask AcquireAsyncCore(int tokenCount, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Threading.RateLimiting.RateLimitLease AttemptAcquireCore(int tokenCount) => throw null; + protected override void Dispose(bool disposing) => throw null; + protected override System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public override System.Threading.RateLimiting.RateLimiterStatistics GetStatistics() => throw null; + public override System.TimeSpan? IdleDuration { get => throw null; } + public override bool IsAutoReplenishing { get => throw null; } + public override System.TimeSpan ReplenishmentPeriod { get => throw null; } + public TokenBucketRateLimiter(System.Threading.RateLimiting.TokenBucketRateLimiterOptions options) => throw null; + public override bool TryReplenish() => throw null; + } + + public class TokenBucketRateLimiterOptions + { + public bool AutoReplenishment { get => throw null; set => throw null; } + public int QueueLimit { get => throw null; set => throw null; } + public System.Threading.RateLimiting.QueueProcessingOrder QueueProcessingOrder { get => throw null; set => throw null; } + public System.TimeSpan ReplenishmentPeriod { get => throw null; set => throw null; } + public TokenBucketRateLimiterOptions() => throw null; + public int TokenLimit { get => throw null; set => throw null; } + public int TokensPerPeriod { get => throw null; set => throw null; } + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.CSharp.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.CSharp.cs index 641de33695d..659a790c78b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.CSharp.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.CSharp.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `Microsoft.CSharp, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace RuntimeBinder { - // Generated from `Microsoft.CSharp.RuntimeBinder.Binder` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Binder { public static System.Runtime.CompilerServices.CallSiteBinder BinaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Linq.Expressions.ExpressionType operation, System.Type context, System.Collections.Generic.IEnumerable argumentInfo) => throw null; @@ -22,13 +22,11 @@ namespace Microsoft public static System.Runtime.CompilerServices.CallSiteBinder UnaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Linq.Expressions.ExpressionType operation, System.Type context, System.Collections.Generic.IEnumerable argumentInfo) => throw null; } - // Generated from `Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CSharpArgumentInfo { public static Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo Create(Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags flags, string name) => throw null; } - // Generated from `Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CSharpArgumentInfoFlags : int { @@ -41,7 +39,6 @@ namespace Microsoft UseCompileTimeType = 1, } - // Generated from `Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CSharpBinderFlags : int { @@ -57,7 +54,6 @@ namespace Microsoft ValueFromCompoundAssignment = 128, } - // Generated from `Microsoft.CSharp.RuntimeBinder.RuntimeBinderException` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RuntimeBinderException : System.Exception { public RuntimeBinderException() => throw null; @@ -66,7 +62,6 @@ namespace Microsoft public RuntimeBinderException(string message, System.Exception innerException) => throw null; } - // Generated from `Microsoft.CSharp.RuntimeBinder.RuntimeBinderInternalCompilerException` in `Microsoft.CSharp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RuntimeBinderInternalCompilerException : System.Exception { public RuntimeBinderInternalCompilerException() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.VisualBasic.Core.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.VisualBasic.Core.cs index 6082fb69ca1..c5e90da6fcc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.VisualBasic.Core.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.VisualBasic.Core.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `Microsoft.VisualBasic.Core, Version=12.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { namespace VisualBasic { - // Generated from `Microsoft.VisualBasic.AppWinStyle` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AppWinStyle : short { Hide = 0, @@ -15,7 +15,6 @@ namespace Microsoft NormalNoFocus = 4, } - // Generated from `Microsoft.VisualBasic.CallType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CallType : int { Get = 2, @@ -24,7 +23,6 @@ namespace Microsoft Set = 8, } - // Generated from `Microsoft.VisualBasic.Collection` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Collection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { int System.Collections.IList.Add(object value) => throw null; @@ -55,7 +53,6 @@ namespace Microsoft object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `Microsoft.VisualBasic.ComClassAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComClassAttribute : System.Attribute { public string ClassID { get => throw null; } @@ -68,14 +65,12 @@ namespace Microsoft public bool InterfaceShadows { get => throw null; set => throw null; } } - // Generated from `Microsoft.VisualBasic.CompareMethod` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CompareMethod : int { Binary = 0, Text = 1, } - // Generated from `Microsoft.VisualBasic.Constants` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Constants { public const Microsoft.VisualBasic.MsgBoxResult vbAbort = default; @@ -182,7 +177,6 @@ namespace Microsoft public const Microsoft.VisualBasic.MsgBoxStyle vbYesNoCancel = default; } - // Generated from `Microsoft.VisualBasic.ControlChars` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ControlChars { public const System.Char Back = default; @@ -198,7 +192,6 @@ namespace Microsoft public const System.Char VerticalTab = default; } - // Generated from `Microsoft.VisualBasic.Conversion` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Conversion { public static object CTypeDynamic(object Expression, System.Type TargetType) => throw null; @@ -243,7 +236,6 @@ namespace Microsoft public static double Val(string InputStr) => throw null; } - // Generated from `Microsoft.VisualBasic.DateAndTime` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateAndTime { public static System.DateTime DateAdd(Microsoft.VisualBasic.DateInterval Interval, double Number, System.DateTime DateValue) => throw null; @@ -273,7 +265,6 @@ namespace Microsoft public static int Year(System.DateTime DateValue) => throw null; } - // Generated from `Microsoft.VisualBasic.DateFormat` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DateFormat : int { GeneralDate = 0, @@ -283,7 +274,6 @@ namespace Microsoft ShortTime = 4, } - // Generated from `Microsoft.VisualBasic.DateInterval` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DateInterval : int { Day = 4, @@ -298,14 +288,12 @@ namespace Microsoft Year = 0, } - // Generated from `Microsoft.VisualBasic.DueDate` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DueDate : int { BegOfPeriod = 1, EndOfPeriod = 0, } - // Generated from `Microsoft.VisualBasic.ErrObject` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ErrObject { public void Clear() => throw null; @@ -320,7 +308,6 @@ namespace Microsoft public string Source { get => throw null; set => throw null; } } - // Generated from `Microsoft.VisualBasic.FileAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileAttribute : int { @@ -333,7 +320,6 @@ namespace Microsoft Volume = 8, } - // Generated from `Microsoft.VisualBasic.FileSystem` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystem { public static void ChDir(string Path) => throw null; @@ -421,7 +407,6 @@ namespace Microsoft public static void WriteLine(int FileNumber, params object[] Output) => throw null; } - // Generated from `Microsoft.VisualBasic.Financial` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Financial { public static double DDB(double Cost, double Salvage, double Life, double Period, double Factor = default(double)) => throw null; @@ -439,7 +424,6 @@ namespace Microsoft public static double SYD(double Cost, double Salvage, double Life, double Period) => throw null; } - // Generated from `Microsoft.VisualBasic.FirstDayOfWeek` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FirstDayOfWeek : int { Friday = 6, @@ -452,7 +436,6 @@ namespace Microsoft Wednesday = 4, } - // Generated from `Microsoft.VisualBasic.FirstWeekOfYear` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FirstWeekOfYear : int { FirstFourDays = 2, @@ -461,13 +444,11 @@ namespace Microsoft System = 0, } - // Generated from `Microsoft.VisualBasic.HideModuleNameAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HideModuleNameAttribute : System.Attribute { public HideModuleNameAttribute() => throw null; } - // Generated from `Microsoft.VisualBasic.Information` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Information { public static int Erl() => throw null; @@ -489,7 +470,6 @@ namespace Microsoft public static string VbTypeName(string UrtName) => throw null; } - // Generated from `Microsoft.VisualBasic.Interaction` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Interaction { public static void AppActivate(int ProcessId) => throw null; @@ -514,7 +494,6 @@ namespace Microsoft public static object Switch(params object[] VarExpr) => throw null; } - // Generated from `Microsoft.VisualBasic.MsgBoxResult` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MsgBoxResult : int { Abort = 3, @@ -526,7 +505,6 @@ namespace Microsoft Yes = 6, } - // Generated from `Microsoft.VisualBasic.MsgBoxStyle` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MsgBoxStyle : int { @@ -551,7 +529,6 @@ namespace Microsoft YesNoCancel = 3, } - // Generated from `Microsoft.VisualBasic.MyGroupCollectionAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MyGroupCollectionAttribute : System.Attribute { public string CreateMethod { get => throw null; } @@ -561,7 +538,6 @@ namespace Microsoft public string MyGroupName { get => throw null; } } - // Generated from `Microsoft.VisualBasic.OpenAccess` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OpenAccess : int { Default = -1, @@ -570,7 +546,6 @@ namespace Microsoft Write = 2, } - // Generated from `Microsoft.VisualBasic.OpenMode` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OpenMode : int { Append = 8, @@ -580,7 +555,6 @@ namespace Microsoft Random = 4, } - // Generated from `Microsoft.VisualBasic.OpenShare` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OpenShare : int { Default = -1, @@ -590,14 +564,12 @@ namespace Microsoft Shared = 3, } - // Generated from `Microsoft.VisualBasic.SpcInfo` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SpcInfo { public System.Int16 Count; // Stub generator skipped constructor } - // Generated from `Microsoft.VisualBasic.Strings` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Strings { public static int Asc(System.Char String) => throw null; @@ -659,14 +631,12 @@ namespace Microsoft public static string UCase(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.TabInfo` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TabInfo { public System.Int16 Column; // Stub generator skipped constructor } - // Generated from `Microsoft.VisualBasic.TriState` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TriState : int { False = 0, @@ -674,7 +644,6 @@ namespace Microsoft UseDefault = -2, } - // Generated from `Microsoft.VisualBasic.VBFixedArrayAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VBFixedArrayAttribute : System.Attribute { public int[] Bounds { get => throw null; } @@ -683,14 +652,12 @@ namespace Microsoft public VBFixedArrayAttribute(int UpperBound1, int UpperBound2) => throw null; } - // Generated from `Microsoft.VisualBasic.VBFixedStringAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VBFixedStringAttribute : System.Attribute { public int Length { get => throw null; } public VBFixedStringAttribute(int Length) => throw null; } - // Generated from `Microsoft.VisualBasic.VBMath` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VBMath { public static void Randomize() => throw null; @@ -699,7 +666,6 @@ namespace Microsoft public static float Rnd(float Number) => throw null; } - // Generated from `Microsoft.VisualBasic.VariantType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum VariantType : int { Array = 8192, @@ -724,7 +690,6 @@ namespace Microsoft Variant = 12, } - // Generated from `Microsoft.VisualBasic.VbStrConv` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum VbStrConv : int { @@ -743,35 +708,30 @@ namespace Microsoft namespace CompilerServices { - // Generated from `Microsoft.VisualBasic.CompilerServices.BooleanType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BooleanType { public static bool FromObject(object Value) => throw null; public static bool FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.ByteType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ByteType { public static System.Byte FromObject(object Value) => throw null; public static System.Byte FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.CharArrayType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CharArrayType { public static System.Char[] FromObject(object Value) => throw null; public static System.Char[] FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.CharType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CharType { public static System.Char FromObject(object Value) => throw null; public static System.Char FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.Conversions` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Conversions { public static object ChangeType(object Expression, System.Type TargetType) => throw null; @@ -829,7 +789,6 @@ namespace Microsoft public static System.UInt16 ToUShort(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.DateType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateType { public static System.DateTime FromObject(object Value) => throw null; @@ -837,7 +796,6 @@ namespace Microsoft public static System.DateTime FromString(string Value, System.Globalization.CultureInfo culture) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.DecimalType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecimalType { public static System.Decimal FromBoolean(bool Value) => throw null; @@ -848,13 +806,11 @@ namespace Microsoft public static System.Decimal Parse(string Value, System.Globalization.NumberFormatInfo NumberFormat) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.DesignerGeneratedAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerGeneratedAttribute : System.Attribute { public DesignerGeneratedAttribute() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.DoubleType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DoubleType { public static double FromObject(object Value) => throw null; @@ -865,20 +821,17 @@ namespace Microsoft public static double Parse(string Value, System.Globalization.NumberFormatInfo NumberFormat) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.IncompleteInitialization` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IncompleteInitialization : System.Exception { public IncompleteInitialization() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.IntegerType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IntegerType { public static int FromObject(object Value) => throw null; public static int FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.LateBinding` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LateBinding { public static void LateCall(object o, System.Type objType, string name, object[] args, string[] paramnames, bool[] CopyBack) => throw null; @@ -890,21 +843,18 @@ namespace Microsoft public static void LateSetComplex(object o, System.Type objType, string name, object[] args, string[] paramnames, bool OptimisticSet, bool RValueBase) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.LikeOperator` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LikeOperator { public static object LikeObject(object Source, object Pattern, Microsoft.VisualBasic.CompareMethod CompareOption) => throw null; public static bool LikeString(string Source, string Pattern, Microsoft.VisualBasic.CompareMethod CompareOption) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.LongType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LongType { public static System.Int64 FromObject(object Value) => throw null; public static System.Int64 FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.NewLateBinding` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NewLateBinding { public static object FallbackCall(object Instance, string MemberName, object[] Arguments, string[] ArgumentNames, bool IgnoreReturn) => throw null; @@ -927,10 +877,8 @@ namespace Microsoft public static void LateSetComplex(object Instance, System.Type Type, string MemberName, object[] Arguments, string[] ArgumentNames, System.Type[] TypeArguments, bool OptimisticSet, bool RValueBase) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.ObjectFlowControl` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectFlowControl { - // Generated from `Microsoft.VisualBasic.CompilerServices.ObjectFlowControl+ForLoopControl` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ForLoopControl { public static bool ForLoopInitObj(object Counter, object Start, object Limit, object StepValue, ref object LoopForResult, ref object CounterResult) => throw null; @@ -944,7 +892,6 @@ namespace Microsoft public static void CheckForSyncLockOnValueType(object Expression) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.ObjectType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectType { public static object AddObj(object o1, object o2) => throw null; @@ -970,7 +917,6 @@ namespace Microsoft public static object XorObj(object obj1, object obj2) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.Operators` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Operators { public static object AddObject(object Left, object Right) => throw null; @@ -1005,19 +951,16 @@ namespace Microsoft public static object XorObject(object Left, object Right) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OptionCompareAttribute : System.Attribute { public OptionCompareAttribute() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.OptionTextAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OptionTextAttribute : System.Attribute { public OptionTextAttribute() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.ProjectData` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProjectData { public static void ClearProjectError() => throw null; @@ -1027,14 +970,12 @@ namespace Microsoft public static void SetProjectError(System.Exception ex, int lErl) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.ShortType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ShortType { public static System.Int16 FromObject(object Value) => throw null; public static System.Int16 FromString(string Value) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.SingleType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SingleType { public static float FromObject(object Value) => throw null; @@ -1043,20 +984,17 @@ namespace Microsoft public static float FromString(string Value, System.Globalization.NumberFormatInfo NumberFormat) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StandardModuleAttribute : System.Attribute { public StandardModuleAttribute() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.StaticLocalInitFlag` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StaticLocalInitFlag { public System.Int16 State; public StaticLocalInitFlag() => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.StringType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringType { public static string FromBoolean(bool Value) => throw null; @@ -1080,14 +1018,12 @@ namespace Microsoft public static bool StrLikeText(string Source, string Pattern) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.Utils` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Utils { public static System.Array CopyArray(System.Array arySrc, System.Array aryDest) => throw null; public static string GetResourceString(string ResourceKey, params string[] Args) => throw null; } - // Generated from `Microsoft.VisualBasic.CompilerServices.Versioned` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Versioned { public static object CallByName(object Instance, string MethodName, Microsoft.VisualBasic.CallType UseCallType, params object[] Arguments) => throw null; @@ -1100,21 +1036,18 @@ namespace Microsoft } namespace FileIO { - // Generated from `Microsoft.VisualBasic.FileIO.DeleteDirectoryOption` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DeleteDirectoryOption : int { DeleteAllContents = 5, ThrowIfDirectoryNonEmpty = 4, } - // Generated from `Microsoft.VisualBasic.FileIO.FieldType` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FieldType : int { Delimited = 0, FixedWidth = 1, } - // Generated from `Microsoft.VisualBasic.FileIO.FileSystem` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystem { public static string CombinePath(string baseDirectory, string relativePath) => throw null; @@ -1175,7 +1108,6 @@ namespace Microsoft public static void WriteAllText(string file, string text, bool append, System.Text.Encoding encoding) => throw null; } - // Generated from `Microsoft.VisualBasic.FileIO.MalformedLineException` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MalformedLineException : System.Exception { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -1189,21 +1121,18 @@ namespace Microsoft public override string ToString() => throw null; } - // Generated from `Microsoft.VisualBasic.FileIO.RecycleOption` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RecycleOption : int { DeletePermanently = 2, SendToRecycleBin = 3, } - // Generated from `Microsoft.VisualBasic.FileIO.SearchOption` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SearchOption : int { SearchAllSubDirectories = 3, SearchTopLevelOnly = 2, } - // Generated from `Microsoft.VisualBasic.FileIO.SpecialDirectories` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SpecialDirectories { public static string AllUsersApplicationData { get => throw null; } @@ -1218,7 +1147,6 @@ namespace Microsoft public static string Temp { get => throw null; } } - // Generated from `Microsoft.VisualBasic.FileIO.TextFieldParser` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TextFieldParser : System.IDisposable { public void Close() => throw null; @@ -1251,14 +1179,12 @@ namespace Microsoft // ERR: Stub generator didn't handle member: ~TextFieldParser } - // Generated from `Microsoft.VisualBasic.FileIO.UICancelOption` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UICancelOption : int { DoNothing = 2, ThrowException = 3, } - // Generated from `Microsoft.VisualBasic.FileIO.UIOption` in `Microsoft.VisualBasic.Core, Version=11.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UIOption : int { AllDialogs = 3, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Primitives.cs index df4170b8153..5a60e762ef4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Primitives.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Win32.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace ComponentModel { - // Generated from `System.ComponentModel.Win32Exception` in `Microsoft.Win32.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Win32Exception : System.Runtime.InteropServices.ExternalException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Registry.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Registry.cs index f30a2dff24b..97a5c94d86b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Registry.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.Win32.Registry.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `Microsoft.Win32.Registry, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { namespace Win32 { - // Generated from `Microsoft.Win32.Registry` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Registry { public static Microsoft.Win32.RegistryKey ClassesRoot; @@ -18,7 +18,6 @@ namespace Microsoft public static Microsoft.Win32.RegistryKey Users; } - // Generated from `Microsoft.Win32.RegistryHive` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RegistryHive : int { ClassesRoot = -2147483648, @@ -29,7 +28,6 @@ namespace Microsoft Users = -2147483645, } - // Generated from `Microsoft.Win32.RegistryKey` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegistryKey : System.MarshalByRefObject, System.IDisposable { public void Close() => throw null; @@ -77,7 +75,6 @@ namespace Microsoft public Microsoft.Win32.RegistryView View { get => throw null; } } - // Generated from `Microsoft.Win32.RegistryKeyPermissionCheck` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RegistryKeyPermissionCheck : int { Default = 0, @@ -85,7 +82,6 @@ namespace Microsoft ReadWriteSubTree = 2, } - // Generated from `Microsoft.Win32.RegistryOptions` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum RegistryOptions : int { @@ -93,7 +89,6 @@ namespace Microsoft Volatile = 1, } - // Generated from `Microsoft.Win32.RegistryValueKind` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RegistryValueKind : int { Binary = 3, @@ -106,7 +101,6 @@ namespace Microsoft Unknown = 0, } - // Generated from `Microsoft.Win32.RegistryValueOptions` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum RegistryValueOptions : int { @@ -114,7 +108,6 @@ namespace Microsoft None = 0, } - // Generated from `Microsoft.Win32.RegistryView` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RegistryView : int { Default = 0, @@ -124,7 +117,6 @@ namespace Microsoft namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.SafeRegistryHandle` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeRegistryHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { protected override bool ReleaseHandle() => throw null; @@ -141,7 +133,6 @@ namespace System { namespace AccessControl { - // Generated from `System.Security.AccessControl.RegistryAccessRule` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegistryAccessRule : System.Security.AccessControl.AccessRule { public RegistryAccessRule(System.Security.Principal.IdentityReference identity, System.Security.AccessControl.RegistryRights registryRights, System.Security.AccessControl.AccessControlType type) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AccessControlType)) => throw null; @@ -151,7 +142,6 @@ namespace System public System.Security.AccessControl.RegistryRights RegistryRights { get => throw null; } } - // Generated from `System.Security.AccessControl.RegistryAuditRule` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegistryAuditRule : System.Security.AccessControl.AuditRule { public RegistryAuditRule(System.Security.Principal.IdentityReference identity, System.Security.AccessControl.RegistryRights registryRights, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags, System.Security.AccessControl.AuditFlags flags) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AuditFlags)) => throw null; @@ -159,7 +149,6 @@ namespace System public System.Security.AccessControl.RegistryRights RegistryRights { get => throw null; } } - // Generated from `System.Security.AccessControl.RegistryRights` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum RegistryRights : int { @@ -179,7 +168,6 @@ namespace System WriteKey = 131078, } - // Generated from `System.Security.AccessControl.RegistrySecurity` in `Microsoft.Win32.Registry, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegistrySecurity : System.Security.AccessControl.NativeObjectSecurity { public override System.Type AccessRightType { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Concurrent.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Concurrent.cs index 183a876e248..a4552677a27 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Concurrent.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Concurrent.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Collections.Concurrent, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Concurrent { - // Generated from `System.Collections.Concurrent.BlockingCollection<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BlockingCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable, System.IDisposable { public void Add(T item) => throw null; @@ -55,7 +55,6 @@ namespace System public static int TryTakeFromAny(System.Collections.Concurrent.BlockingCollection[] collections, out T item, int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Collections.Concurrent.ConcurrentBag<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrentBag : System.Collections.Concurrent.IProducerConsumerCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { public void Add(T item) => throw null; @@ -76,7 +75,6 @@ namespace System public bool TryTake(out T result) => throw null; } - // Generated from `System.Collections.Concurrent.ConcurrentDictionary<,>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrentDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair keyValuePair) => throw null; @@ -131,7 +129,6 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.Collections.Concurrent.ConcurrentQueue<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrentQueue : System.Collections.Concurrent.IProducerConsumerCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { public void Clear() => throw null; @@ -153,7 +150,6 @@ namespace System bool System.Collections.Concurrent.IProducerConsumerCollection.TryTake(out T item) => throw null; } - // Generated from `System.Collections.Concurrent.ConcurrentStack<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrentStack : System.Collections.Concurrent.IProducerConsumerCollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { public void Clear() => throw null; @@ -179,7 +175,6 @@ namespace System bool System.Collections.Concurrent.IProducerConsumerCollection.TryTake(out T item) => throw null; } - // Generated from `System.Collections.Concurrent.EnumerablePartitionerOptions` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EnumerablePartitionerOptions : int { @@ -187,7 +182,6 @@ namespace System None = 0, } - // Generated from `System.Collections.Concurrent.IProducerConsumerCollection<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IProducerConsumerCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable { void CopyTo(T[] array, int index); @@ -196,7 +190,6 @@ namespace System bool TryTake(out T item); } - // Generated from `System.Collections.Concurrent.OrderablePartitioner<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class OrderablePartitioner : System.Collections.Concurrent.Partitioner { public override System.Collections.Generic.IEnumerable GetDynamicPartitions() => throw null; @@ -209,7 +202,6 @@ namespace System protected OrderablePartitioner(bool keysOrderedInEachPartition, bool keysOrderedAcrossPartitions, bool keysNormalized) => throw null; } - // Generated from `System.Collections.Concurrent.Partitioner` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Partitioner { public static System.Collections.Concurrent.OrderablePartitioner> Create(int fromInclusive, int toExclusive) => throw null; @@ -222,7 +214,6 @@ namespace System public static System.Collections.Concurrent.OrderablePartitioner Create(TSource[] array, bool loadBalance) => throw null; } - // Generated from `System.Collections.Concurrent.Partitioner<>` in `System.Collections.Concurrent, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Partitioner { public virtual System.Collections.Generic.IEnumerable GetDynamicPartitions() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Immutable.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Immutable.cs index 61ca6586565..c8eb72a94e9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Immutable.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Immutable.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Collections.Immutable, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Immutable { - // Generated from `System.Collections.Immutable.IImmutableDictionary<,>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IImmutableDictionary : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { System.Collections.Immutable.IImmutableDictionary Add(TKey key, TValue value); @@ -20,7 +20,6 @@ namespace System bool TryGetKey(TKey equalKey, out TKey actualKey); } - // Generated from `System.Collections.Immutable.IImmutableList<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IImmutableList : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { System.Collections.Immutable.IImmutableList Add(T value); @@ -39,7 +38,6 @@ namespace System System.Collections.Immutable.IImmutableList SetItem(int index, T value); } - // Generated from `System.Collections.Immutable.IImmutableQueue<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IImmutableQueue : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { System.Collections.Immutable.IImmutableQueue Clear(); @@ -49,7 +47,6 @@ namespace System T Peek(); } - // Generated from `System.Collections.Immutable.IImmutableSet<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IImmutableSet : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { System.Collections.Immutable.IImmutableSet Add(T value); @@ -69,7 +66,6 @@ namespace System System.Collections.Immutable.IImmutableSet Union(System.Collections.Generic.IEnumerable other); } - // Generated from `System.Collections.Immutable.IImmutableStack<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IImmutableStack : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { System.Collections.Immutable.IImmutableStack Clear(); @@ -79,7 +75,6 @@ namespace System System.Collections.Immutable.IImmutableStack Push(T value); } - // Generated from `System.Collections.Immutable.ImmutableArray` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableArray { public static int BinarySearch(this System.Collections.Immutable.ImmutableArray array, T value) => throw null; @@ -88,6 +83,8 @@ namespace System public static int BinarySearch(this System.Collections.Immutable.ImmutableArray array, int index, int length, T value, System.Collections.Generic.IComparer comparer) => throw null; public static System.Collections.Immutable.ImmutableArray Create() => throw null; public static System.Collections.Immutable.ImmutableArray Create(System.Collections.Immutable.ImmutableArray items, int start, int length) => throw null; + public static System.Collections.Immutable.ImmutableArray Create(System.ReadOnlySpan items) => throw null; + public static System.Collections.Immutable.ImmutableArray Create(System.Span items) => throw null; public static System.Collections.Immutable.ImmutableArray Create(T item) => throw null; public static System.Collections.Immutable.ImmutableArray Create(T item1, T item2) => throw null; public static System.Collections.Immutable.ImmutableArray Create(T item1, T item2, T item3) => throw null; @@ -101,14 +98,14 @@ namespace System public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, int start, int length, System.Func selector, TArg arg) => throw null; public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, System.Func selector) => throw null; public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, int start, int length, System.Func selector) => throw null; + public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.ReadOnlySpan items) => throw null; + public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Span items) => throw null; public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Collections.Immutable.ImmutableArray.Builder builder) => throw null; public static System.Collections.Immutable.ImmutableArray ToImmutableArray(this System.Collections.Generic.IEnumerable items) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableArray<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImmutableArray : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.Collections.Immutable.IImmutableList, System.IEquatable> { - // Generated from `System.Collections.Immutable.ImmutableArray<>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { public void Add(T item) => throw null; @@ -116,24 +113,32 @@ namespace System public void AddRange(System.Collections.Generic.IEnumerable items) => throw null; public void AddRange(System.Collections.Immutable.ImmutableArray items) => throw null; public void AddRange(System.Collections.Immutable.ImmutableArray items, int length) => throw null; + public void AddRange(System.ReadOnlySpan items) => throw null; public void AddRange(T[] items, int length) => throw null; public void AddRange(params T[] items) => throw null; public void AddRange(System.Collections.Immutable.ImmutableArray.Builder items) where TDerived : T => throw null; public void AddRange(System.Collections.Immutable.ImmutableArray items) where TDerived : T => throw null; + public void AddRange(System.ReadOnlySpan items) where TDerived : T => throw null; public void AddRange(TDerived[] items) where TDerived : T => throw null; public int Capacity { get => throw null; set => throw null; } public void Clear() => throw null; public bool Contains(T item) => throw null; + public void CopyTo(System.Span destination) => throw null; + public void CopyTo(T[] destination) => throw null; public void CopyTo(T[] array, int index) => throw null; + public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) => throw null; public int Count { get => throw null; set => throw null; } public System.Collections.Generic.IEnumerator GetEnumerator() => throw null; System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; public int IndexOf(T item) => throw null; public int IndexOf(T item, int startIndex) => throw null; + public int IndexOf(T item, int startIndex, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public int IndexOf(T item, int startIndex, int count) => throw null; public int IndexOf(T item, int startIndex, int count, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public void Insert(int index, T item) => throw null; + public void InsertRange(int index, System.Collections.Generic.IEnumerable items) => throw null; + public void InsertRange(int index, System.Collections.Immutable.ImmutableArray items) => throw null; bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } public T ItemRef(int index) => throw null; public T this[int index] { get => throw null; set => throw null; } @@ -143,7 +148,14 @@ namespace System public int LastIndexOf(T item, int startIndex, int count, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public System.Collections.Immutable.ImmutableArray MoveToImmutable() => throw null; public bool Remove(T element) => throw null; + public bool Remove(T element, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; + public void RemoveAll(System.Predicate match) => throw null; public void RemoveAt(int index) => throw null; + public void RemoveRange(System.Collections.Generic.IEnumerable items) => throw null; + public void RemoveRange(System.Collections.Generic.IEnumerable items, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; + public void RemoveRange(int index, int length) => throw null; + public void Replace(T oldValue, T newValue) => throw null; + public void Replace(T oldValue, T newValue, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public void Reverse() => throw null; public void Sort() => throw null; public void Sort(System.Comparison comparison) => throw null; @@ -154,7 +166,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableArray<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -174,9 +185,17 @@ namespace System public System.Collections.Immutable.ImmutableArray AddRange(System.Collections.Generic.IEnumerable items) => throw null; System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.AddRange(System.Collections.Generic.IEnumerable items) => throw null; public System.Collections.Immutable.ImmutableArray AddRange(System.Collections.Immutable.ImmutableArray items) => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(System.Collections.Immutable.ImmutableArray items, int length) => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(System.ReadOnlySpan items) => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(T[] items, int length) => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(params T[] items) => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(System.Collections.Immutable.ImmutableArray items) where TDerived : T => throw null; + public System.Collections.Immutable.ImmutableArray AddRange(TDerived[] items) where TDerived : T => throw null; public System.Collections.Immutable.ImmutableArray As() where TOther : class => throw null; public System.ReadOnlyMemory AsMemory() => throw null; public System.ReadOnlySpan AsSpan() => throw null; + public System.ReadOnlySpan AsSpan(System.Range range) => throw null; + public System.ReadOnlySpan AsSpan(int start, int length) => throw null; public System.Collections.Immutable.ImmutableArray CastArray() where TOther : class => throw null; public static System.Collections.Immutable.ImmutableArray CastUp(System.Collections.Immutable.ImmutableArray items) where TDerived : class, T => throw null; public System.Collections.Immutable.ImmutableArray Clear() => throw null; @@ -187,6 +206,7 @@ namespace System public bool Contains(T item) => throw null; bool System.Collections.IList.Contains(object value) => throw null; void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(System.Span destination) => throw null; public void CopyTo(T[] destination) => throw null; public void CopyTo(T[] destination, int destinationIndex) => throw null; public void CopyTo(int sourceIndex, T[] destination, int destinationIndex, int length) => throw null; @@ -216,6 +236,8 @@ namespace System public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.Collections.Generic.IEnumerable items) => throw null; System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.InsertRange(int index, System.Collections.Generic.IEnumerable items) => throw null; public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.Collections.Immutable.ImmutableArray items) => throw null; + public System.Collections.Immutable.ImmutableArray InsertRange(int index, System.ReadOnlySpan items) => throw null; + public System.Collections.Immutable.ImmutableArray InsertRange(int index, T[] items) => throw null; public bool IsDefault { get => throw null; } public bool IsDefaultOrEmpty { get => throw null; } public bool IsEmpty { get => throw null; } @@ -250,6 +272,8 @@ namespace System System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.RemoveRange(System.Collections.Generic.IEnumerable items, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public System.Collections.Immutable.ImmutableArray RemoveRange(System.Collections.Immutable.ImmutableArray items) => throw null; public System.Collections.Immutable.ImmutableArray RemoveRange(System.Collections.Immutable.ImmutableArray items, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; + public System.Collections.Immutable.ImmutableArray RemoveRange(System.ReadOnlySpan items, System.Collections.Generic.IEqualityComparer equalityComparer = default(System.Collections.Generic.IEqualityComparer)) => throw null; + public System.Collections.Immutable.ImmutableArray RemoveRange(T[] items, System.Collections.Generic.IEqualityComparer equalityComparer = default(System.Collections.Generic.IEqualityComparer)) => throw null; public System.Collections.Immutable.ImmutableArray RemoveRange(int index, int length) => throw null; System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.RemoveRange(int index, int count) => throw null; public System.Collections.Immutable.ImmutableArray Replace(T oldValue, T newValue) => throw null; @@ -257,6 +281,7 @@ namespace System System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.Replace(T oldValue, T newValue, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public System.Collections.Immutable.ImmutableArray SetItem(int index, T item) => throw null; System.Collections.Immutable.IImmutableList System.Collections.Immutable.IImmutableList.SetItem(int index, T value) => throw null; + public System.Collections.Immutable.ImmutableArray Slice(int start, int length) => throw null; public System.Collections.Immutable.ImmutableArray Sort() => throw null; public System.Collections.Immutable.ImmutableArray Sort(System.Comparison comparison) => throw null; public System.Collections.Immutable.ImmutableArray Sort(System.Collections.Generic.IComparer comparer) => throw null; @@ -265,7 +290,6 @@ namespace System public System.Collections.Immutable.ImmutableArray.Builder ToBuilder() => throw null; } - // Generated from `System.Collections.Immutable.ImmutableDictionary` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableDictionary { public static bool Contains(this System.Collections.Immutable.IImmutableDictionary map, TKey key, TValue value) => throw null; @@ -291,10 +315,8 @@ namespace System public static System.Collections.Immutable.ImmutableDictionary ToImmutableDictionary(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Collections.Generic.IEqualityComparer keyComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableDictionary<,>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableDictionary { - // Generated from `System.Collections.Immutable.ImmutableDictionary<,>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { public void Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -340,7 +362,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableDictionary<,>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -410,7 +431,6 @@ namespace System public System.Collections.Immutable.ImmutableDictionary WithComparers(System.Collections.Generic.IEqualityComparer keyComparer, System.Collections.Generic.IEqualityComparer valueComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableHashSet` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableHashSet { public static System.Collections.Immutable.ImmutableHashSet Create() => throw null; @@ -428,10 +448,8 @@ namespace System public static System.Collections.Immutable.ImmutableHashSet ToImmutableHashSet(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableHashSet<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableHashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableSet { - // Generated from `System.Collections.Immutable.ImmutableHashSet<>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.IEnumerable { public bool Add(T item) => throw null; @@ -461,7 +479,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableHashSet<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -519,7 +536,6 @@ namespace System public System.Collections.Immutable.ImmutableHashSet WithComparer(System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableInterlocked` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableInterlocked { public static TValue AddOrUpdate(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, System.Func addValueFactory, System.Func updateValueFactory) => throw null; @@ -543,7 +559,6 @@ namespace System public static bool Update(ref T location, System.Func transformer) where T : class => throw null; } - // Generated from `System.Collections.Immutable.ImmutableList` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableList { public static System.Collections.Immutable.ImmutableList Create() => throw null; @@ -566,10 +581,8 @@ namespace System public static System.Collections.Immutable.ImmutableList ToImmutableList(this System.Collections.Generic.IEnumerable source) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableList<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableList { - // Generated from `System.Collections.Immutable.ImmutableList<>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public void Add(T item) => throw null; @@ -623,9 +636,15 @@ namespace System public int LastIndexOf(T item, int startIndex, int count) => throw null; public int LastIndexOf(T item, int startIndex, int count, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public bool Remove(T item) => throw null; + public bool Remove(T item, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; void System.Collections.IList.Remove(object value) => throw null; public int RemoveAll(System.Predicate match) => throw null; public void RemoveAt(int index) => throw null; + public void RemoveRange(System.Collections.Generic.IEnumerable items) => throw null; + public void RemoveRange(System.Collections.Generic.IEnumerable items, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; + public void RemoveRange(int index, int count) => throw null; + public void Replace(T oldValue, T newValue) => throw null; + public void Replace(T oldValue, T newValue, System.Collections.Generic.IEqualityComparer equalityComparer) => throw null; public void Reverse() => throw null; public void Reverse(int index, int count) => throw null; public void Sort() => throw null; @@ -638,7 +657,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableList<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -738,7 +756,6 @@ namespace System public bool TrueForAll(System.Predicate match) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableQueue` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableQueue { public static System.Collections.Immutable.ImmutableQueue Create() => throw null; @@ -748,10 +765,8 @@ namespace System public static System.Collections.Immutable.IImmutableQueue Dequeue(this System.Collections.Immutable.IImmutableQueue queue, out T value) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableQueue<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableQueue : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableQueue { - // Generated from `System.Collections.Immutable.ImmutableQueue<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -776,7 +791,6 @@ namespace System public T PeekRef() => throw null; } - // Generated from `System.Collections.Immutable.ImmutableSortedDictionary` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableSortedDictionary { public static System.Collections.Immutable.ImmutableSortedDictionary Create() => throw null; @@ -797,10 +811,8 @@ namespace System public static System.Collections.Immutable.ImmutableSortedDictionary ToImmutableSortedDictionary(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Func elementSelector, System.Collections.Generic.IComparer keyComparer, System.Collections.Generic.IEqualityComparer valueComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableSortedDictionary<,>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableSortedDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableDictionary { - // Generated from `System.Collections.Immutable.ImmutableSortedDictionary<,>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { public void Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -847,7 +859,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableSortedDictionary<,>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -918,7 +929,6 @@ namespace System public System.Collections.Immutable.ImmutableSortedDictionary WithComparers(System.Collections.Generic.IComparer keyComparer, System.Collections.Generic.IEqualityComparer valueComparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableSortedSet` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableSortedSet { public static System.Collections.Immutable.ImmutableSortedSet Create() => throw null; @@ -936,10 +946,8 @@ namespace System public static System.Collections.Immutable.ImmutableSortedSet ToImmutableSortedSet(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IComparer comparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableSortedSet<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableSortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.Immutable.IImmutableSet { - // Generated from `System.Collections.Immutable.ImmutableSortedSet<>+Builder` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Builder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable { public bool Add(T item) => throw null; @@ -953,6 +961,7 @@ namespace System public System.Collections.Immutable.ImmutableSortedSet.Enumerator GetEnumerator() => throw null; System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public int IndexOf(T item) => throw null; public void IntersectWith(System.Collections.Generic.IEnumerable other) => throw null; public bool IsProperSubsetOf(System.Collections.Generic.IEnumerable other) => throw null; public bool IsProperSupersetOf(System.Collections.Generic.IEnumerable other) => throw null; @@ -977,7 +986,6 @@ namespace System } - // Generated from `System.Collections.Immutable.ImmutableSortedSet<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -1054,7 +1062,6 @@ namespace System public System.Collections.Immutable.ImmutableSortedSet WithComparer(System.Collections.Generic.IComparer comparer) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableStack` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableStack { public static System.Collections.Immutable.ImmutableStack Create() => throw null; @@ -1064,10 +1071,8 @@ namespace System public static System.Collections.Immutable.IImmutableStack Pop(this System.Collections.Immutable.IImmutableStack stack, out T value) => throw null; } - // Generated from `System.Collections.Immutable.ImmutableStack<>` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableStack : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Collections.Immutable.IImmutableStack { - // Generated from `System.Collections.Immutable.ImmutableStack<>+Enumerator` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -1096,7 +1101,6 @@ namespace System } namespace Linq { - // Generated from `System.Linq.ImmutableArrayExtensions` in `System.Collections.Immutable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ImmutableArrayExtensions { public static T Aggregate(this System.Collections.Immutable.ImmutableArray immutableArray, System.Func func) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.NonGeneric.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.NonGeneric.cs index 6311d99099f..cb64504fca4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.NonGeneric.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.NonGeneric.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Collections.NonGeneric, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Collections { - // Generated from `System.Collections.CaseInsensitiveComparer` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CaseInsensitiveComparer : System.Collections.IComparer { public CaseInsensitiveComparer() => throw null; @@ -14,7 +14,6 @@ namespace System public static System.Collections.CaseInsensitiveComparer DefaultInvariant { get => throw null; } } - // Generated from `System.Collections.CaseInsensitiveHashCodeProvider` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CaseInsensitiveHashCodeProvider : System.Collections.IHashCodeProvider { public CaseInsensitiveHashCodeProvider() => throw null; @@ -24,7 +23,6 @@ namespace System public int GetHashCode(object obj) => throw null; } - // Generated from `System.Collections.CollectionBase` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { int System.Collections.IList.Add(object value) => throw null; @@ -58,7 +56,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Collections.DictionaryBase` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DictionaryBase : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { void System.Collections.IDictionary.Add(object key, object value) => throw null; @@ -91,7 +88,6 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.Collections.Queue` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Queue : System.Collections.ICollection, System.Collections.IEnumerable, System.ICloneable { public virtual void Clear() => throw null; @@ -114,7 +110,6 @@ namespace System public virtual void TrimToSize() => throw null; } - // Generated from `System.Collections.ReadOnlyCollectionBase` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ReadOnlyCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable { void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; @@ -126,7 +121,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Collections.SortedList` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortedList : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ICloneable { public virtual void Add(object key, object value) => throw null; @@ -166,7 +160,6 @@ namespace System public virtual System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Collections.Stack` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Stack : System.Collections.ICollection, System.Collections.IEnumerable, System.ICloneable { public virtual void Clear() => throw null; @@ -189,7 +182,6 @@ namespace System namespace Specialized { - // Generated from `System.Collections.Specialized.CollectionsUtil` in `System.Collections.NonGeneric, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CollectionsUtil { public CollectionsUtil() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Specialized.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Specialized.cs index 7f1ebf51687..3a63dff333a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Specialized.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.Specialized.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Collections.Specialized, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,11 +7,9 @@ namespace System { namespace Specialized { - // Generated from `System.Collections.Specialized.BitVector32` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct BitVector32 + public struct BitVector32 : System.IEquatable { - // Generated from `System.Collections.Specialized.BitVector32+Section` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Section + public struct Section : System.IEquatable { public static bool operator !=(System.Collections.Specialized.BitVector32.Section a, System.Collections.Specialized.BitVector32.Section b) => throw null; public static bool operator ==(System.Collections.Specialized.BitVector32.Section a, System.Collections.Specialized.BitVector32.Section b) => throw null; @@ -33,6 +32,7 @@ namespace System public static System.Collections.Specialized.BitVector32.Section CreateSection(System.Int16 maxValue) => throw null; public static System.Collections.Specialized.BitVector32.Section CreateSection(System.Int16 maxValue, System.Collections.Specialized.BitVector32.Section previous) => throw null; public int Data { get => throw null; } + public bool Equals(System.Collections.Specialized.BitVector32 other) => throw null; public override bool Equals(object o) => throw null; public override int GetHashCode() => throw null; public int this[System.Collections.Specialized.BitVector32.Section section] { get => throw null; set => throw null; } @@ -41,7 +41,6 @@ namespace System public static string ToString(System.Collections.Specialized.BitVector32 value) => throw null; } - // Generated from `System.Collections.Specialized.HybridDictionary` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HybridDictionary : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { public void Add(object key, object value) => throw null; @@ -65,7 +64,6 @@ namespace System public System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Collections.Specialized.IOrderedDictionary` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IOrderedDictionary : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { System.Collections.IDictionaryEnumerator GetEnumerator(); @@ -74,7 +72,6 @@ namespace System void RemoveAt(int index); } - // Generated from `System.Collections.Specialized.ListDictionary` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListDictionary : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { public void Add(object key, object value) => throw null; @@ -96,10 +93,8 @@ namespace System public System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Collections.Specialized.NameObjectCollectionBase` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class NameObjectCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.Collections.Specialized.NameObjectCollectionBase+KeysCollection` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KeysCollection : System.Collections.ICollection, System.Collections.IEnumerable { void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; @@ -143,7 +138,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Collections.Specialized.NameValueCollection` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NameValueCollection : System.Collections.Specialized.NameObjectCollectionBase { public void Add(System.Collections.Specialized.NameValueCollection c) => throw null; @@ -173,7 +167,6 @@ namespace System public virtual void Set(string name, string value) => throw null; } - // Generated from `System.Collections.Specialized.OrderedDictionary` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OrderedDictionary : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Collections.Specialized.IOrderedDictionary, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public void Add(object key, object value) => throw null; @@ -205,7 +198,6 @@ namespace System public System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Collections.Specialized.StringCollection` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { int System.Collections.IList.Add(object value) => throw null; @@ -236,7 +228,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Collections.Specialized.StringDictionary` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringDictionary : System.Collections.IEnumerable { public virtual void Add(string key, string value) => throw null; @@ -255,7 +246,6 @@ namespace System public virtual System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Collections.Specialized.StringEnumerator` in `System.Collections.Specialized, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringEnumerator { public string Current { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.cs index 0a19a5ad326..97c54625254 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Collections.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Collections, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Collections { - // Generated from `System.Collections.BitArray` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BitArray : System.Collections.ICollection, System.Collections.IEnumerable, System.ICloneable { public System.Collections.BitArray And(System.Collections.BitArray value) => throw null; @@ -33,7 +33,6 @@ namespace System public System.Collections.BitArray Xor(System.Collections.BitArray value) => throw null; } - // Generated from `System.Collections.StructuralComparisons` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class StructuralComparisons { public static System.Collections.IComparer StructuralComparer { get => throw null; } @@ -42,16 +41,16 @@ namespace System namespace Generic { - // Generated from `System.Collections.Generic.CollectionExtensions` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CollectionExtensions { + public static System.Collections.ObjectModel.ReadOnlyCollection AsReadOnly(this System.Collections.Generic.IList list) => throw null; + public static System.Collections.ObjectModel.ReadOnlyDictionary AsReadOnly(this System.Collections.Generic.IDictionary dictionary) => throw null; public static TValue GetValueOrDefault(this System.Collections.Generic.IReadOnlyDictionary dictionary, TKey key) => throw null; public static TValue GetValueOrDefault(this System.Collections.Generic.IReadOnlyDictionary dictionary, TKey key, TValue defaultValue) => throw null; public static bool Remove(this System.Collections.Generic.IDictionary dictionary, TKey key, out TValue value) => throw null; public static bool TryAdd(this System.Collections.Generic.IDictionary dictionary, TKey key, TValue value) => throw null; } - // Generated from `System.Collections.Generic.Comparer<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Comparer : System.Collections.Generic.IComparer, System.Collections.IComparer { public abstract int Compare(T x, T y); @@ -61,10 +60,8 @@ namespace System public static System.Collections.Generic.Comparer Default { get => throw null; } } - // Generated from `System.Collections.Generic.Dictionary<,>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Dictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.Collections.Generic.Dictionary<,>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IDictionaryEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -79,10 +76,8 @@ namespace System } - // Generated from `System.Collections.Generic.Dictionary<,>+KeyCollection` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KeyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.Dictionary<,>+KeyCollection+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public TKey Current { get => throw null; } @@ -111,10 +106,8 @@ namespace System } - // Generated from `System.Collections.Generic.Dictionary<,>+ValueCollection` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValueCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.Dictionary<,>+ValueCollection+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public TValue Current { get => throw null; } @@ -196,7 +189,6 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.Collections.Generic.EqualityComparer<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EqualityComparer : System.Collections.Generic.IEqualityComparer, System.Collections.IEqualityComparer { public static System.Collections.Generic.EqualityComparer Default { get => throw null; } @@ -207,10 +199,8 @@ namespace System int System.Collections.IEqualityComparer.GetHashCode(object obj) => throw null; } - // Generated from `System.Collections.Generic.HashSet<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HashSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.ISet, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.Collections.Generic.HashSet<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -262,10 +252,8 @@ namespace System public void UnionWith(System.Collections.Generic.IEnumerable other) => throw null; } - // Generated from `System.Collections.Generic.LinkedList<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LinkedList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.Collections.Generic.LinkedList<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public T Current { get => throw null; } @@ -314,7 +302,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Collections.Generic.LinkedListNode<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LinkedListNode { public LinkedListNode(T value) => throw null; @@ -325,10 +312,8 @@ namespace System public T ValueRef { get => throw null; } } - // Generated from `System.Collections.Generic.List<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class List : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { - // Generated from `System.Collections.Generic.List<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -409,13 +394,10 @@ namespace System public bool TrueForAll(System.Predicate match) => throw null; } - // Generated from `System.Collections.Generic.PriorityQueue<,>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PriorityQueue { - // Generated from `System.Collections.Generic.PriorityQueue<,>+UnorderedItemsCollection` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnorderedItemsCollection : System.Collections.Generic.IEnumerable<(TElement, TPriority)>, System.Collections.Generic.IReadOnlyCollection<(TElement, TPriority)>, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.PriorityQueue<,>+UnorderedItemsCollection+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator<(TElement, TPriority)>, System.Collections.IEnumerator, System.IDisposable { public (TElement, TPriority) Current { get => throw null; } @@ -460,10 +442,8 @@ namespace System public System.Collections.Generic.PriorityQueue.UnorderedItemsCollection UnorderedItems { get => throw null; } } - // Generated from `System.Collections.Generic.Queue<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Queue : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.Queue<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -498,7 +478,6 @@ namespace System public bool TryPeek(out T result) => throw null; } - // Generated from `System.Collections.Generic.ReferenceEqualityComparer` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReferenceEqualityComparer : System.Collections.Generic.IEqualityComparer, System.Collections.IEqualityComparer { public bool Equals(object x, object y) => throw null; @@ -506,10 +485,8 @@ namespace System public static System.Collections.Generic.ReferenceEqualityComparer Instance { get => throw null; } } - // Generated from `System.Collections.Generic.SortedDictionary<,>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortedDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.SortedDictionary<,>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IDictionaryEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -524,10 +501,8 @@ namespace System } - // Generated from `System.Collections.Generic.SortedDictionary<,>+KeyCollection` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KeyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.SortedDictionary<,>+KeyCollection+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public TKey Current { get => throw null; } @@ -556,10 +531,8 @@ namespace System } - // Generated from `System.Collections.Generic.SortedDictionary<,>+ValueCollection` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValueCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.SortedDictionary<,>+ValueCollection+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public TValue Current { get => throw null; } @@ -629,7 +602,6 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.Collections.Generic.SortedList<,>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortedList : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair keyValuePair) => throw null; @@ -649,6 +621,8 @@ namespace System System.Collections.Generic.IEnumerator> System.Collections.Generic.IEnumerable>.GetEnumerator() => throw null; System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() => throw null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public TKey GetKeyAtIndex(int index) => throw null; + public TValue GetValueAtIndex(int index) => throw null; public int IndexOfKey(TKey key) => throw null; public int IndexOfValue(TValue value) => throw null; bool System.Collections.IDictionary.IsFixedSize { get => throw null; } @@ -665,6 +639,7 @@ namespace System public bool Remove(TKey key) => throw null; void System.Collections.IDictionary.Remove(object key) => throw null; public void RemoveAt(int index) => throw null; + public void SetValueAtIndex(int index, TValue value) => throw null; public SortedList() => throw null; public SortedList(System.Collections.Generic.IComparer comparer) => throw null; public SortedList(System.Collections.Generic.IDictionary dictionary) => throw null; @@ -680,10 +655,8 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.Collections.Generic.SortedSet<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortedSet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlySet, System.Collections.Generic.ISet, System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.Collections.Generic.SortedSet<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public T Current { get => throw null; } @@ -743,10 +716,8 @@ namespace System public void UnionWith(System.Collections.Generic.IEnumerable other) => throw null; } - // Generated from `System.Collections.Generic.Stack<>` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Stack : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { - // Generated from `System.Collections.Generic.Stack<>+Enumerator` in `System.Collections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Annotations.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Annotations.cs index 0f2d0ef2581..e9d1bd902c5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Annotations.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Annotations.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.ComponentModel.Annotations, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace DataAnnotations { - // Generated from `System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProvider` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssociatedMetadataTypeTypeDescriptionProvider : System.ComponentModel.TypeDescriptionProvider { public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type) => throw null; @@ -14,7 +14,6 @@ namespace System public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(System.Type objectType, object instance) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.AssociationAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssociationAttribute : System.Attribute { public AssociationAttribute(string name, string thisKey, string otherKey) => throw null; @@ -26,7 +25,6 @@ namespace System public System.Collections.Generic.IEnumerable ThisKeyMembers { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.CompareAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompareAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public CompareAttribute(string otherProperty) => throw null; @@ -37,20 +35,17 @@ namespace System public override bool RequiresValidationContext { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.ConcurrencyCheckAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrencyCheckAttribute : System.Attribute { public ConcurrencyCheckAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.CreditCardAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CreditCardAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public CreditCardAttribute() : base(default(System.ComponentModel.DataAnnotations.DataType)) => throw null; public override bool IsValid(object value) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.CustomValidationAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CustomValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public CustomValidationAttribute(System.Type validatorType, string method) => throw null; @@ -60,7 +55,6 @@ namespace System public System.Type ValidatorType { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.DataType` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DataType : int { CreditCard = 14, @@ -82,7 +76,6 @@ namespace System Url = 12, } - // Generated from `System.ComponentModel.DataAnnotations.DataTypeAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTypeAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public string CustomDataType { get => throw null; } @@ -94,7 +87,6 @@ namespace System public override bool IsValid(object value) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.DisplayAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DisplayAttribute : System.Attribute { public bool AutoGenerateField { get => throw null; set => throw null; } @@ -117,7 +109,6 @@ namespace System public string ShortName { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.DisplayColumnAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DisplayColumnAttribute : System.Attribute { public string DisplayColumn { get => throw null; } @@ -128,7 +119,6 @@ namespace System public bool SortDescending { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.DisplayFormatAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DisplayFormatAttribute : System.Attribute { public bool ApplyFormatInEditMode { get => throw null; set => throw null; } @@ -141,7 +131,6 @@ namespace System public System.Type NullDisplayTextResourceType { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.EditableAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EditableAttribute : System.Attribute { public bool AllowEdit { get => throw null; } @@ -149,14 +138,12 @@ namespace System public EditableAttribute(bool allowEdit) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.EmailAddressAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EmailAddressAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public EmailAddressAttribute() : base(default(System.ComponentModel.DataAnnotations.DataType)) => throw null; public override bool IsValid(object value) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.EnumDataTypeAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumDataTypeAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public EnumDataTypeAttribute(System.Type enumType) : base(default(System.ComponentModel.DataAnnotations.DataType)) => throw null; @@ -164,7 +151,6 @@ namespace System public override bool IsValid(object value) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.FileExtensionsAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileExtensionsAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public string Extensions { get => throw null; set => throw null; } @@ -173,7 +159,6 @@ namespace System public override bool IsValid(object value) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.FilterUIHintAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FilterUIHintAttribute : System.Attribute { public System.Collections.Generic.IDictionary ControlParameters { get => throw null; } @@ -186,19 +171,16 @@ namespace System public string PresentationLayer { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.IValidatableObject` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IValidatableObject { System.Collections.Generic.IEnumerable Validate(System.ComponentModel.DataAnnotations.ValidationContext validationContext); } - // Generated from `System.ComponentModel.DataAnnotations.KeyAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KeyAttribute : System.Attribute { public KeyAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.MaxLengthAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MaxLengthAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public override string FormatErrorMessage(string name) => throw null; @@ -208,14 +190,12 @@ namespace System public MaxLengthAttribute(int length) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.MetadataTypeAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataTypeAttribute : System.Attribute { public System.Type MetadataClassType { get => throw null; } public MetadataTypeAttribute(System.Type metadataClassType) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.MinLengthAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MinLengthAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public override string FormatErrorMessage(string name) => throw null; @@ -224,14 +204,12 @@ namespace System public MinLengthAttribute(int length) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.PhoneAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PhoneAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public override bool IsValid(object value) => throw null; public PhoneAttribute() : base(default(System.ComponentModel.DataAnnotations.DataType)) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.RangeAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RangeAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public bool ConvertValueInInvariantCulture { get => throw null; set => throw null; } @@ -246,17 +224,16 @@ namespace System public RangeAttribute(int minimum, int maximum) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.RegularExpressionAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegularExpressionAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public override string FormatErrorMessage(string name) => throw null; public override bool IsValid(object value) => throw null; + public System.TimeSpan MatchTimeout { get => throw null; } public int MatchTimeoutInMilliseconds { get => throw null; set => throw null; } public string Pattern { get => throw null; } public RegularExpressionAttribute(string pattern) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.RequiredAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RequiredAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public bool AllowEmptyStrings { get => throw null; set => throw null; } @@ -264,14 +241,12 @@ namespace System public RequiredAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.ScaffoldColumnAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ScaffoldColumnAttribute : System.Attribute { public bool Scaffold { get => throw null; } public ScaffoldColumnAttribute(bool scaffold) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.StringLengthAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringLengthAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute { public override string FormatErrorMessage(string name) => throw null; @@ -281,13 +256,11 @@ namespace System public StringLengthAttribute(int maximumLength) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.TimestampAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TimestampAttribute : System.Attribute { public TimestampAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.UIHintAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UIHintAttribute : System.Attribute { public System.Collections.Generic.IDictionary ControlParameters { get => throw null; } @@ -300,14 +273,12 @@ namespace System public UIHintAttribute(string uiHint, string presentationLayer, params object[] controlParameters) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.UrlAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UrlAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute { public override bool IsValid(object value) => throw null; public UrlAttribute() : base(default(System.ComponentModel.DataAnnotations.DataType)) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.ValidationAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ValidationAttribute : System.Attribute { public string ErrorMessage { get => throw null; set => throw null; } @@ -326,7 +297,6 @@ namespace System protected ValidationAttribute(string errorMessage) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.ValidationContext` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValidationContext : System.IServiceProvider { public string DisplayName { get => throw null; set => throw null; } @@ -341,7 +311,6 @@ namespace System public ValidationContext(object instance, System.IServiceProvider serviceProvider, System.Collections.Generic.IDictionary items) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.ValidationException` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValidationException : System.Exception { public System.ComponentModel.DataAnnotations.ValidationAttribute ValidationAttribute { get => throw null; } @@ -355,7 +324,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.ValidationResult` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValidationResult { public string ErrorMessage { get => throw null; set => throw null; } @@ -367,7 +335,6 @@ namespace System public ValidationResult(string errorMessage, System.Collections.Generic.IEnumerable memberNames) => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.Validator` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Validator { public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection validationResults) => throw null; @@ -382,7 +349,6 @@ namespace System namespace Schema { - // Generated from `System.ComponentModel.DataAnnotations.Schema.ColumnAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ColumnAttribute : System.Attribute { public ColumnAttribute() => throw null; @@ -392,20 +358,17 @@ namespace System public string TypeName { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.Schema.ComplexTypeAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComplexTypeAttribute : System.Attribute { public ComplexTypeAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DatabaseGeneratedAttribute : System.Attribute { public DatabaseGeneratedAttribute(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption databaseGeneratedOption) => throw null; public System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption DatabaseGeneratedOption { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DatabaseGeneratedOption : int { Computed = 2, @@ -413,27 +376,23 @@ namespace System None = 0, } - // Generated from `System.ComponentModel.DataAnnotations.Schema.ForeignKeyAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ForeignKeyAttribute : System.Attribute { public ForeignKeyAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.Schema.InversePropertyAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InversePropertyAttribute : System.Attribute { public InversePropertyAttribute(string property) => throw null; public string Property { get => throw null; } } - // Generated from `System.ComponentModel.DataAnnotations.Schema.NotMappedAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotMappedAttribute : System.Attribute { public NotMappedAttribute() => throw null; } - // Generated from `System.ComponentModel.DataAnnotations.Schema.TableAttribute` in `System.ComponentModel.Annotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TableAttribute : System.Attribute { public string Name { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.EventBasedAsync.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.EventBasedAsync.cs index d7b34b9d2e3..a1532ad632c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.EventBasedAsync.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.EventBasedAsync.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.ComponentModel.EventBasedAsync, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace ComponentModel { - // Generated from `System.ComponentModel.AsyncCompletedEventArgs` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncCompletedEventArgs : System.EventArgs { public AsyncCompletedEventArgs(System.Exception error, bool cancelled, object userState) => throw null; @@ -14,10 +14,8 @@ namespace System public object UserState { get => throw null; } } - // Generated from `System.ComponentModel.AsyncCompletedEventHandler` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void AsyncCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); - // Generated from `System.ComponentModel.AsyncOperation` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncOperation { public void OperationCompleted() => throw null; @@ -28,14 +26,12 @@ namespace System // ERR: Stub generator didn't handle member: ~AsyncOperation } - // Generated from `System.ComponentModel.AsyncOperationManager` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class AsyncOperationManager { public static System.ComponentModel.AsyncOperation CreateOperation(object userSuppliedState) => throw null; public static System.Threading.SynchronizationContext SynchronizationContext { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.BackgroundWorker` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BackgroundWorker : System.ComponentModel.Component { public BackgroundWorker() => throw null; @@ -57,7 +53,6 @@ namespace System public bool WorkerSupportsCancellation { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.DoWorkEventArgs` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DoWorkEventArgs : System.ComponentModel.CancelEventArgs { public object Argument { get => throw null; } @@ -65,10 +60,8 @@ namespace System public object Result { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.DoWorkEventHandler` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DoWorkEventHandler(object sender, System.ComponentModel.DoWorkEventArgs e); - // Generated from `System.ComponentModel.ProgressChangedEventArgs` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProgressChangedEventArgs : System.EventArgs { public ProgressChangedEventArgs(int progressPercentage, object userState) => throw null; @@ -76,10 +69,8 @@ namespace System public object UserState { get => throw null; } } - // Generated from `System.ComponentModel.ProgressChangedEventHandler` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ProgressChangedEventHandler(object sender, System.ComponentModel.ProgressChangedEventArgs e); - // Generated from `System.ComponentModel.RunWorkerCompletedEventArgs` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RunWorkerCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public object Result { get => throw null; } @@ -87,7 +78,6 @@ namespace System public object UserState { get => throw null; } } - // Generated from `System.ComponentModel.RunWorkerCompletedEventHandler` in `System.ComponentModel.EventBasedAsync, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void RunWorkerCompletedEventHandler(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e); } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Primitives.cs index e87d1083838..be80b38c754 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.Primitives.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.ComponentModel.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace ComponentModel { - // Generated from `System.ComponentModel.BrowsableAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BrowsableAttribute : System.Attribute { public bool Browsable { get => throw null; } @@ -17,7 +17,6 @@ namespace System public static System.ComponentModel.BrowsableAttribute Yes; } - // Generated from `System.ComponentModel.CategoryAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CategoryAttribute : System.Attribute { public static System.ComponentModel.CategoryAttribute Action { get => throw null; } @@ -43,7 +42,6 @@ namespace System public static System.ComponentModel.CategoryAttribute WindowStyle { get => throw null; } } - // Generated from `System.ComponentModel.Component` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Component : System.MarshalByRefObject, System.ComponentModel.IComponent, System.IDisposable { protected virtual bool CanRaiseEvents { get => throw null; } @@ -60,7 +58,6 @@ namespace System // ERR: Stub generator didn't handle member: ~Component } - // Generated from `System.ComponentModel.ComponentCollection` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentCollection : System.Collections.ReadOnlyCollectionBase { public ComponentCollection(System.ComponentModel.IComponent[] components) => throw null; @@ -69,7 +66,6 @@ namespace System public virtual System.ComponentModel.IComponent this[string name] { get => throw null; } } - // Generated from `System.ComponentModel.DescriptionAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DescriptionAttribute : System.Attribute { public static System.ComponentModel.DescriptionAttribute Default; @@ -82,7 +78,6 @@ namespace System public override bool IsDefaultAttribute() => throw null; } - // Generated from `System.ComponentModel.DesignOnlyAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignOnlyAttribute : System.Attribute { public static System.ComponentModel.DesignOnlyAttribute Default; @@ -95,7 +90,6 @@ namespace System public static System.ComponentModel.DesignOnlyAttribute Yes; } - // Generated from `System.ComponentModel.DesignerAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerAttribute : System.Attribute { public DesignerAttribute(System.Type designerType) => throw null; @@ -110,7 +104,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.DesignerCategoryAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerCategoryAttribute : System.Attribute { public string Category { get => throw null; } @@ -126,7 +119,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.DesignerSerializationVisibility` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DesignerSerializationVisibility : int { Content = 2, @@ -134,7 +126,6 @@ namespace System Visible = 1, } - // Generated from `System.ComponentModel.DesignerSerializationVisibilityAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerSerializationVisibilityAttribute : System.Attribute { public static System.ComponentModel.DesignerSerializationVisibilityAttribute Content; @@ -148,7 +139,6 @@ namespace System public static System.ComponentModel.DesignerSerializationVisibilityAttribute Visible; } - // Generated from `System.ComponentModel.DisplayNameAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DisplayNameAttribute : System.Attribute { public static System.ComponentModel.DisplayNameAttribute Default; @@ -161,7 +151,6 @@ namespace System public override bool IsDefaultAttribute() => throw null; } - // Generated from `System.ComponentModel.EditorAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EditorAttribute : System.Attribute { public EditorAttribute() => throw null; @@ -175,7 +164,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.EventHandlerList` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventHandlerList : System.IDisposable { public void AddHandler(object key, System.Delegate value) => throw null; @@ -186,14 +174,12 @@ namespace System public void RemoveHandler(object key, System.Delegate value) => throw null; } - // Generated from `System.ComponentModel.IComponent` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComponent : System.IDisposable { event System.EventHandler Disposed; System.ComponentModel.ISite Site { get; set; } } - // Generated from `System.ComponentModel.IContainer` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IContainer : System.IDisposable { void Add(System.ComponentModel.IComponent component); @@ -202,7 +188,6 @@ namespace System void Remove(System.ComponentModel.IComponent component); } - // Generated from `System.ComponentModel.ISite` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISite : System.IServiceProvider { System.ComponentModel.IComponent Component { get; } @@ -211,14 +196,12 @@ namespace System string Name { get; set; } } - // Generated from `System.ComponentModel.ISupportInitialize` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISupportInitialize { void BeginInit(); void EndInit(); } - // Generated from `System.ComponentModel.ISynchronizeInvoke` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISynchronizeInvoke { System.IAsyncResult BeginInvoke(System.Delegate method, object[] args); @@ -227,7 +210,6 @@ namespace System bool InvokeRequired { get; } } - // Generated from `System.ComponentModel.ImmutableObjectAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImmutableObjectAttribute : System.Attribute { public static System.ComponentModel.ImmutableObjectAttribute Default; @@ -240,14 +222,12 @@ namespace System public static System.ComponentModel.ImmutableObjectAttribute Yes; } - // Generated from `System.ComponentModel.InitializationEventAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InitializationEventAttribute : System.Attribute { public string EventName { get => throw null; } public InitializationEventAttribute(string eventName) => throw null; } - // Generated from `System.ComponentModel.InvalidAsynchronousStateException` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidAsynchronousStateException : System.ArgumentException { public InvalidAsynchronousStateException() => throw null; @@ -256,7 +236,6 @@ namespace System public InvalidAsynchronousStateException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ComponentModel.InvalidEnumArgumentException` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidEnumArgumentException : System.ArgumentException { public InvalidEnumArgumentException() => throw null; @@ -266,7 +245,6 @@ namespace System public InvalidEnumArgumentException(string argumentName, int invalidValue, System.Type enumClass) => throw null; } - // Generated from `System.ComponentModel.LocalizableAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LocalizableAttribute : System.Attribute { public static System.ComponentModel.LocalizableAttribute Default; @@ -279,7 +257,6 @@ namespace System public static System.ComponentModel.LocalizableAttribute Yes; } - // Generated from `System.ComponentModel.MergablePropertyAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MergablePropertyAttribute : System.Attribute { public bool AllowMerge { get => throw null; } @@ -292,7 +269,6 @@ namespace System public static System.ComponentModel.MergablePropertyAttribute Yes; } - // Generated from `System.ComponentModel.NotifyParentPropertyAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotifyParentPropertyAttribute : System.Attribute { public static System.ComponentModel.NotifyParentPropertyAttribute Default; @@ -305,7 +281,6 @@ namespace System public static System.ComponentModel.NotifyParentPropertyAttribute Yes; } - // Generated from `System.ComponentModel.ParenthesizePropertyNameAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParenthesizePropertyNameAttribute : System.Attribute { public static System.ComponentModel.ParenthesizePropertyNameAttribute Default; @@ -317,7 +292,6 @@ namespace System public ParenthesizePropertyNameAttribute(bool needParenthesis) => throw null; } - // Generated from `System.ComponentModel.ReadOnlyAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyAttribute : System.Attribute { public static System.ComponentModel.ReadOnlyAttribute Default; @@ -330,7 +304,6 @@ namespace System public static System.ComponentModel.ReadOnlyAttribute Yes; } - // Generated from `System.ComponentModel.RefreshProperties` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RefreshProperties : int { All = 1, @@ -338,7 +311,6 @@ namespace System Repaint = 2, } - // Generated from `System.ComponentModel.RefreshPropertiesAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RefreshPropertiesAttribute : System.Attribute { public static System.ComponentModel.RefreshPropertiesAttribute All; @@ -355,7 +327,6 @@ namespace System { namespace Serialization { - // Generated from `System.ComponentModel.Design.Serialization.DesignerSerializerAttribute` in `System.ComponentModel.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerSerializerAttribute : System.Attribute { public DesignerSerializerAttribute(System.Type serializerType, System.Type baseSerializerType) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.TypeConverter.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.TypeConverter.cs index 33883e650cc..6fcf33bc6ae 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.TypeConverter.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.TypeConverter.cs @@ -1,8 +1,8 @@ // This file contains auto-generated code. +// Generated from `System.ComponentModel.TypeConverter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { - // Generated from `System.UriTypeConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UriTypeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -15,7 +15,6 @@ namespace System namespace ComponentModel { - // Generated from `System.ComponentModel.AddingNewEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AddingNewEventArgs : System.EventArgs { public AddingNewEventArgs() => throw null; @@ -23,10 +22,8 @@ namespace System public object NewObject { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.AddingNewEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void AddingNewEventHandler(object sender, System.ComponentModel.AddingNewEventArgs e); - // Generated from `System.ComponentModel.AmbientValueAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AmbientValueAttribute : System.Attribute { public AmbientValueAttribute(System.Type type, string value) => throw null; @@ -45,7 +42,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.ComponentModel.ArrayConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArrayConverter : System.ComponentModel.CollectionConverter { public ArrayConverter() => throw null; @@ -54,7 +50,6 @@ namespace System public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.ComponentModel.AttributeCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AttributeCollection : System.Collections.ICollection, System.Collections.IEnumerable { protected AttributeCollection() => throw null; @@ -78,7 +73,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.ComponentModel.AttributeProviderAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AttributeProviderAttribute : System.Attribute { public AttributeProviderAttribute(System.Type type) => throw null; @@ -88,7 +82,6 @@ namespace System public string TypeName { get => throw null; } } - // Generated from `System.ComponentModel.BaseNumberConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class BaseNumberConverter : System.ComponentModel.TypeConverter { internal BaseNumberConverter() => throw null; @@ -98,7 +91,6 @@ namespace System public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) => throw null; } - // Generated from `System.ComponentModel.BindableAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BindableAttribute : System.Attribute { public bool Bindable { get => throw null; } @@ -115,7 +107,6 @@ namespace System public static System.ComponentModel.BindableAttribute Yes; } - // Generated from `System.ComponentModel.BindableSupport` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum BindableSupport : int { Default = 2, @@ -123,14 +114,12 @@ namespace System Yes = 1, } - // Generated from `System.ComponentModel.BindingDirection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum BindingDirection : int { OneWay = 0, TwoWay = 1, } - // Generated from `System.ComponentModel.BindingList<>` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BindingList : System.Collections.ObjectModel.Collection, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ICancelAddNew, System.ComponentModel.IRaiseItemChangedEvents { void System.ComponentModel.IBindingList.AddIndex(System.ComponentModel.PropertyDescriptor prop) => throw null; @@ -180,7 +169,6 @@ namespace System protected virtual bool SupportsSortingCore { get => throw null; } } - // Generated from `System.ComponentModel.BooleanConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BooleanConverter : System.ComponentModel.TypeConverter { public BooleanConverter() => throw null; @@ -191,16 +179,13 @@ namespace System public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.ComponentModel.ByteConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ByteConverter : System.ComponentModel.BaseNumberConverter { public ByteConverter() => throw null; } - // Generated from `System.ComponentModel.CancelEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void CancelEventHandler(object sender, System.ComponentModel.CancelEventArgs e); - // Generated from `System.ComponentModel.CharConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CharConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -209,7 +194,6 @@ namespace System public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) => throw null; } - // Generated from `System.ComponentModel.CollectionChangeAction` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CollectionChangeAction : int { Add = 1, @@ -217,7 +201,6 @@ namespace System Remove = 2, } - // Generated from `System.ComponentModel.CollectionChangeEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CollectionChangeEventArgs : System.EventArgs { public virtual System.ComponentModel.CollectionChangeAction Action { get => throw null; } @@ -225,10 +208,8 @@ namespace System public virtual object Element { get => throw null; } } - // Generated from `System.ComponentModel.CollectionChangeEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void CollectionChangeEventHandler(object sender, System.ComponentModel.CollectionChangeEventArgs e); - // Generated from `System.ComponentModel.CollectionConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CollectionConverter : System.ComponentModel.TypeConverter { public CollectionConverter() => throw null; @@ -236,7 +217,6 @@ namespace System public override System.ComponentModel.PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, System.Attribute[] attributes) => throw null; } - // Generated from `System.ComponentModel.ComplexBindingPropertiesAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComplexBindingPropertiesAttribute : System.Attribute { public ComplexBindingPropertiesAttribute() => throw null; @@ -249,7 +229,6 @@ namespace System public override int GetHashCode() => throw null; } - // Generated from `System.ComponentModel.ComponentConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentConverter : System.ComponentModel.ReferenceConverter { public ComponentConverter(System.Type type) : base(default(System.Type)) => throw null; @@ -257,7 +236,6 @@ namespace System public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.ComponentModel.ComponentEditor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ComponentEditor { protected ComponentEditor() => throw null; @@ -265,7 +243,6 @@ namespace System public bool EditComponent(object component) => throw null; } - // Generated from `System.ComponentModel.ComponentResourceManager` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentResourceManager : System.Resources.ResourceManager { public void ApplyResources(object value, string objectName) => throw null; @@ -274,7 +251,6 @@ namespace System public ComponentResourceManager(System.Type t) => throw null; } - // Generated from `System.ComponentModel.Container` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Container : System.ComponentModel.IContainer, System.IDisposable { public virtual void Add(System.ComponentModel.IComponent component) => throw null; @@ -291,14 +267,12 @@ namespace System // ERR: Stub generator didn't handle member: ~Container } - // Generated from `System.ComponentModel.ContainerFilterService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ContainerFilterService { protected ContainerFilterService() => throw null; public virtual System.ComponentModel.ComponentCollection FilterComponents(System.ComponentModel.ComponentCollection components) => throw null; } - // Generated from `System.ComponentModel.CultureInfoConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CultureInfoConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -312,7 +286,6 @@ namespace System public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.ComponentModel.CustomTypeDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CustomTypeDescriptor : System.ComponentModel.ICustomTypeDescriptor { protected CustomTypeDescriptor() => throw null; @@ -331,7 +304,6 @@ namespace System public virtual object GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd) => throw null; } - // Generated from `System.ComponentModel.DataObjectAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataObjectAttribute : System.Attribute { public static System.ComponentModel.DataObjectAttribute DataObject; @@ -345,7 +317,6 @@ namespace System public static System.ComponentModel.DataObjectAttribute NonDataObject; } - // Generated from `System.ComponentModel.DataObjectFieldAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataObjectFieldAttribute : System.Attribute { public DataObjectFieldAttribute(bool primaryKey) => throw null; @@ -360,7 +331,6 @@ namespace System public bool PrimaryKey { get => throw null; } } - // Generated from `System.ComponentModel.DataObjectMethodAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataObjectMethodAttribute : System.Attribute { public DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType methodType) => throw null; @@ -372,7 +342,6 @@ namespace System public System.ComponentModel.DataObjectMethodType MethodType { get => throw null; } } - // Generated from `System.ComponentModel.DataObjectMethodType` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DataObjectMethodType : int { Delete = 4, @@ -382,7 +351,15 @@ namespace System Update = 2, } - // Generated from `System.ComponentModel.DateTimeConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class DateOnlyConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) => throw null; + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) => throw null; + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) => throw null; + public DateOnlyConverter() => throw null; + } + public class DateTimeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -392,7 +369,6 @@ namespace System public DateTimeConverter() => throw null; } - // Generated from `System.ComponentModel.DateTimeOffsetConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateTimeOffsetConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -402,7 +378,6 @@ namespace System public DateTimeOffsetConverter() => throw null; } - // Generated from `System.ComponentModel.DecimalConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecimalConverter : System.ComponentModel.BaseNumberConverter { public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) => throw null; @@ -410,7 +385,6 @@ namespace System public DecimalConverter() => throw null; } - // Generated from `System.ComponentModel.DefaultBindingPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultBindingPropertyAttribute : System.Attribute { public static System.ComponentModel.DefaultBindingPropertyAttribute Default; @@ -421,7 +395,6 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.ComponentModel.DefaultEventAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultEventAttribute : System.Attribute { public static System.ComponentModel.DefaultEventAttribute Default; @@ -431,7 +404,6 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.ComponentModel.DefaultPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultPropertyAttribute : System.Attribute { public static System.ComponentModel.DefaultPropertyAttribute Default; @@ -441,7 +413,6 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.ComponentModel.DesignTimeVisibleAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignTimeVisibleAttribute : System.Attribute { public static System.ComponentModel.DesignTimeVisibleAttribute Default; @@ -455,13 +426,11 @@ namespace System public static System.ComponentModel.DesignTimeVisibleAttribute Yes; } - // Generated from `System.ComponentModel.DoubleConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DoubleConverter : System.ComponentModel.BaseNumberConverter { public DoubleConverter() => throw null; } - // Generated from `System.ComponentModel.EnumConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -478,7 +447,6 @@ namespace System protected System.ComponentModel.TypeConverter.StandardValuesCollection Values { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.EventDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EventDescriptor : System.ComponentModel.MemberDescriptor { public abstract void AddEventHandler(object component, System.Delegate value); @@ -491,7 +459,6 @@ namespace System public abstract void RemoveEventHandler(object component, System.Delegate value); } - // Generated from `System.ComponentModel.EventDescriptorCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventDescriptorCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public int Add(System.ComponentModel.EventDescriptor value) => throw null; @@ -532,7 +499,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.ComponentModel.ExpandableObjectConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExpandableObjectConverter : System.ComponentModel.TypeConverter { public ExpandableObjectConverter() => throw null; @@ -540,7 +506,6 @@ namespace System public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.ComponentModel.ExtenderProvidedPropertyAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExtenderProvidedPropertyAttribute : System.Attribute { public override bool Equals(object obj) => throw null; @@ -552,7 +517,6 @@ namespace System public System.Type ReceiverType { get => throw null; } } - // Generated from `System.ComponentModel.GuidConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GuidConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -562,7 +526,11 @@ namespace System public GuidConverter() => throw null; } - // Generated from `System.ComponentModel.HandledEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class HalfConverter : System.ComponentModel.BaseNumberConverter + { + public HalfConverter() => throw null; + } + public class HandledEventArgs : System.EventArgs { public bool Handled { get => throw null; set => throw null; } @@ -570,10 +538,8 @@ namespace System public HandledEventArgs(bool defaultHandledValue) => throw null; } - // Generated from `System.ComponentModel.HandledEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void HandledEventHandler(object sender, System.ComponentModel.HandledEventArgs e); - // Generated from `System.ComponentModel.IBindingList` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IBindingList : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { void AddIndex(System.ComponentModel.PropertyDescriptor property); @@ -594,7 +560,6 @@ namespace System bool SupportsSorting { get; } } - // Generated from `System.ComponentModel.IBindingListView` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IBindingListView : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList { void ApplySort(System.ComponentModel.ListSortDescriptionCollection sorts); @@ -605,14 +570,12 @@ namespace System bool SupportsFiltering { get; } } - // Generated from `System.ComponentModel.ICancelAddNew` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICancelAddNew { void CancelNew(int itemIndex); void EndNew(int itemIndex); } - // Generated from `System.ComponentModel.IComNativeDescriptorHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComNativeDescriptorHandler { System.ComponentModel.AttributeCollection GetAttributes(object component); @@ -629,7 +592,6 @@ namespace System object GetPropertyValue(object component, string propertyName, ref bool success); } - // Generated from `System.ComponentModel.ICustomTypeDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomTypeDescriptor { System.ComponentModel.AttributeCollection GetAttributes(); @@ -646,59 +608,50 @@ namespace System object GetPropertyOwner(System.ComponentModel.PropertyDescriptor pd); } - // Generated from `System.ComponentModel.IDataErrorInfo` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataErrorInfo { string Error { get; } string this[string columnName] { get; } } - // Generated from `System.ComponentModel.IExtenderProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IExtenderProvider { bool CanExtend(object extendee); } - // Generated from `System.ComponentModel.IIntellisenseBuilder` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IIntellisenseBuilder { string Name { get; } bool Show(string language, string value, ref string newValue); } - // Generated from `System.ComponentModel.IListSource` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IListSource { bool ContainsListCollection { get; } System.Collections.IList GetList(); } - // Generated from `System.ComponentModel.INestedContainer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INestedContainer : System.ComponentModel.IContainer, System.IDisposable { System.ComponentModel.IComponent Owner { get; } } - // Generated from `System.ComponentModel.INestedSite` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INestedSite : System.ComponentModel.ISite, System.IServiceProvider { string FullName { get; } } - // Generated from `System.ComponentModel.IRaiseItemChangedEvents` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IRaiseItemChangedEvents { bool RaisesItemChangedEvents { get; } } - // Generated from `System.ComponentModel.ISupportInitializeNotification` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISupportInitializeNotification : System.ComponentModel.ISupportInitialize { event System.EventHandler Initialized; bool IsInitialized { get; } } - // Generated from `System.ComponentModel.ITypeDescriptorContext` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeDescriptorContext : System.IServiceProvider { System.ComponentModel.IContainer Container { get; } @@ -708,14 +661,12 @@ namespace System System.ComponentModel.PropertyDescriptor PropertyDescriptor { get; } } - // Generated from `System.ComponentModel.ITypedList` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypedList { System.ComponentModel.PropertyDescriptorCollection GetItemProperties(System.ComponentModel.PropertyDescriptor[] listAccessors); string GetListName(System.ComponentModel.PropertyDescriptor[] listAccessors); } - // Generated from `System.ComponentModel.InheritanceAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InheritanceAttribute : System.Attribute { public static System.ComponentModel.InheritanceAttribute Default; @@ -731,7 +682,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.ComponentModel.InheritanceLevel` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum InheritanceLevel : int { Inherited = 1, @@ -739,7 +689,6 @@ namespace System NotInherited = 3, } - // Generated from `System.ComponentModel.InstallerTypeAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InstallerTypeAttribute : System.Attribute { public override bool Equals(object obj) => throw null; @@ -749,7 +698,6 @@ namespace System public InstallerTypeAttribute(string typeName) => throw null; } - // Generated from `System.ComponentModel.InstanceCreationEditor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class InstanceCreationEditor { public abstract object CreateInstance(System.ComponentModel.ITypeDescriptorContext context, System.Type instanceType); @@ -757,25 +705,26 @@ namespace System public virtual string Text { get => throw null; } } - // Generated from `System.ComponentModel.Int16Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class Int128Converter : System.ComponentModel.BaseNumberConverter + { + public Int128Converter() => throw null; + } + public class Int16Converter : System.ComponentModel.BaseNumberConverter { public Int16Converter() => throw null; } - // Generated from `System.ComponentModel.Int32Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Int32Converter : System.ComponentModel.BaseNumberConverter { public Int32Converter() => throw null; } - // Generated from `System.ComponentModel.Int64Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Int64Converter : System.ComponentModel.BaseNumberConverter { public Int64Converter() => throw null; } - // Generated from `System.ComponentModel.LicFileLicenseProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LicFileLicenseProvider : System.ComponentModel.LicenseProvider { protected virtual string GetKey(System.Type type) => throw null; @@ -784,7 +733,6 @@ namespace System public LicFileLicenseProvider() => throw null; } - // Generated from `System.ComponentModel.License` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class License : System.IDisposable { public abstract void Dispose(); @@ -792,7 +740,6 @@ namespace System public abstract string LicenseKey { get; } } - // Generated from `System.ComponentModel.LicenseContext` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LicenseContext : System.IServiceProvider { public virtual string GetSavedLicenseKey(System.Type type, System.Reflection.Assembly resourceAssembly) => throw null; @@ -802,7 +749,6 @@ namespace System public virtual System.ComponentModel.LicenseUsageMode UsageMode { get => throw null; } } - // Generated from `System.ComponentModel.LicenseException` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LicenseException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -814,7 +760,6 @@ namespace System public System.Type LicensedType { get => throw null; } } - // Generated from `System.ComponentModel.LicenseManager` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LicenseManager { public static object CreateWithContext(System.Type type, System.ComponentModel.LicenseContext creationContext) => throw null; @@ -830,14 +775,12 @@ namespace System public static System.ComponentModel.License Validate(System.Type type, object instance) => throw null; } - // Generated from `System.ComponentModel.LicenseProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class LicenseProvider { public abstract System.ComponentModel.License GetLicense(System.ComponentModel.LicenseContext context, System.Type type, object instance, bool allowExceptions); protected LicenseProvider() => throw null; } - // Generated from `System.ComponentModel.LicenseProviderAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LicenseProviderAttribute : System.Attribute { public static System.ComponentModel.LicenseProviderAttribute Default; @@ -850,14 +793,12 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.LicenseUsageMode` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LicenseUsageMode : int { Designtime = 1, Runtime = 0, } - // Generated from `System.ComponentModel.ListBindableAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListBindableAttribute : System.Attribute { public static System.ComponentModel.ListBindableAttribute Default; @@ -871,7 +812,6 @@ namespace System public static System.ComponentModel.ListBindableAttribute Yes; } - // Generated from `System.ComponentModel.ListChangedEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListChangedEventArgs : System.EventArgs { public ListChangedEventArgs(System.ComponentModel.ListChangedType listChangedType, System.ComponentModel.PropertyDescriptor propDesc) => throw null; @@ -884,10 +824,8 @@ namespace System public System.ComponentModel.PropertyDescriptor PropertyDescriptor { get => throw null; } } - // Generated from `System.ComponentModel.ListChangedEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ListChangedEventHandler(object sender, System.ComponentModel.ListChangedEventArgs e); - // Generated from `System.ComponentModel.ListChangedType` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ListChangedType : int { ItemAdded = 1, @@ -900,7 +838,6 @@ namespace System Reset = 0, } - // Generated from `System.ComponentModel.ListSortDescription` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListSortDescription { public ListSortDescription(System.ComponentModel.PropertyDescriptor property, System.ComponentModel.ListSortDirection direction) => throw null; @@ -908,7 +845,6 @@ namespace System public System.ComponentModel.ListSortDirection SortDirection { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.ListSortDescriptionCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListSortDescriptionCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { int System.Collections.IList.Add(object value) => throw null; @@ -931,14 +867,12 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.ComponentModel.ListSortDirection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ListSortDirection : int { Ascending = 0, Descending = 1, } - // Generated from `System.ComponentModel.LookupBindingPropertiesAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LookupBindingPropertiesAttribute : System.Attribute { public string DataSource { get => throw null; } @@ -952,7 +886,6 @@ namespace System public string ValueMember { get => throw null; } } - // Generated from `System.ComponentModel.MarshalByValueComponent` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MarshalByValueComponent : System.ComponentModel.IComponent, System.IDisposable, System.IServiceProvider { public virtual System.ComponentModel.IContainer Container { get => throw null; } @@ -968,7 +901,6 @@ namespace System // ERR: Stub generator didn't handle member: ~MarshalByValueComponent } - // Generated from `System.ComponentModel.MaskedTextProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MaskedTextProvider : System.ICloneable { public bool Add(System.Char input) => throw null; @@ -1053,7 +985,6 @@ namespace System public bool VerifyString(string input, out int testPosition, out System.ComponentModel.MaskedTextResultHint resultHint) => throw null; } - // Generated from `System.ComponentModel.MaskedTextResultHint` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MaskedTextResultHint : int { AlphanumericCharacterExpected = -2, @@ -1073,7 +1004,6 @@ namespace System Unknown = 0, } - // Generated from `System.ComponentModel.MemberDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MemberDescriptor { protected virtual System.Attribute[] AttributeArray { get => throw null; set => throw null; } @@ -1100,7 +1030,6 @@ namespace System protected virtual int NameHashCode { get => throw null; } } - // Generated from `System.ComponentModel.MultilineStringConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MultilineStringConverter : System.ComponentModel.TypeConverter { public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) => throw null; @@ -1109,7 +1038,6 @@ namespace System public MultilineStringConverter() => throw null; } - // Generated from `System.ComponentModel.NestedContainer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NestedContainer : System.ComponentModel.Container, System.ComponentModel.IContainer, System.ComponentModel.INestedContainer, System.IDisposable { protected override System.ComponentModel.ISite CreateSite(System.ComponentModel.IComponent component, string name) => throw null; @@ -1120,7 +1048,6 @@ namespace System protected virtual string OwnerName { get => throw null; } } - // Generated from `System.ComponentModel.NullableConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NullableConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1141,7 +1068,6 @@ namespace System public System.ComponentModel.TypeConverter UnderlyingTypeConverter { get => throw null; } } - // Generated from `System.ComponentModel.PasswordPropertyTextAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PasswordPropertyTextAttribute : System.Attribute { public static System.ComponentModel.PasswordPropertyTextAttribute Default; @@ -1155,7 +1081,6 @@ namespace System public static System.ComponentModel.PasswordPropertyTextAttribute Yes; } - // Generated from `System.ComponentModel.PropertyDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class PropertyDescriptor : System.ComponentModel.MemberDescriptor { public virtual void AddValueChanged(object component, System.EventHandler handler) => throw null; @@ -1190,7 +1115,6 @@ namespace System public virtual bool SupportsChangeEvents { get => throw null; } } - // Generated from `System.ComponentModel.PropertyDescriptorCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyDescriptorCollection : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.Collections.IList { public int Add(System.ComponentModel.PropertyDescriptor value) => throw null; @@ -1241,7 +1165,6 @@ namespace System System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } } - // Generated from `System.ComponentModel.PropertyTabAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyTabAttribute : System.Attribute { public bool Equals(System.ComponentModel.PropertyTabAttribute other) => throw null; @@ -1259,7 +1182,6 @@ namespace System public System.ComponentModel.PropertyTabScope[] TabScopes { get => throw null; } } - // Generated from `System.ComponentModel.PropertyTabScope` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PropertyTabScope : int { Component = 3, @@ -1268,7 +1190,6 @@ namespace System Static = 0, } - // Generated from `System.ComponentModel.ProvidePropertyAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProvidePropertyAttribute : System.Attribute { public override bool Equals(object obj) => throw null; @@ -1280,7 +1201,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.RecommendedAsConfigurableAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RecommendedAsConfigurableAttribute : System.Attribute { public static System.ComponentModel.RecommendedAsConfigurableAttribute Default; @@ -1293,7 +1213,6 @@ namespace System public static System.ComponentModel.RecommendedAsConfigurableAttribute Yes; } - // Generated from `System.ComponentModel.ReferenceConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReferenceConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1306,7 +1225,6 @@ namespace System public ReferenceConverter(System.Type type) => throw null; } - // Generated from `System.ComponentModel.RefreshEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RefreshEventArgs : System.EventArgs { public object ComponentChanged { get => throw null; } @@ -1315,10 +1233,8 @@ namespace System public System.Type TypeChanged { get => throw null; } } - // Generated from `System.ComponentModel.RefreshEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void RefreshEventHandler(System.ComponentModel.RefreshEventArgs e); - // Generated from `System.ComponentModel.RunInstallerAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RunInstallerAttribute : System.Attribute { public static System.ComponentModel.RunInstallerAttribute Default; @@ -1331,13 +1247,11 @@ namespace System public static System.ComponentModel.RunInstallerAttribute Yes; } - // Generated from `System.ComponentModel.SByteConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SByteConverter : System.ComponentModel.BaseNumberConverter { public SByteConverter() => throw null; } - // Generated from `System.ComponentModel.SettingsBindableAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SettingsBindableAttribute : System.Attribute { public bool Bindable { get => throw null; } @@ -1348,13 +1262,11 @@ namespace System public static System.ComponentModel.SettingsBindableAttribute Yes; } - // Generated from `System.ComponentModel.SingleConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SingleConverter : System.ComponentModel.BaseNumberConverter { public SingleConverter() => throw null; } - // Generated from `System.ComponentModel.StringConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1362,7 +1274,6 @@ namespace System public StringConverter() => throw null; } - // Generated from `System.ComponentModel.SyntaxCheck` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SyntaxCheck { public static bool CheckMachineName(string value) => throw null; @@ -1370,7 +1281,15 @@ namespace System public static bool CheckRootedPath(string value) => throw null; } - // Generated from `System.ComponentModel.TimeSpanConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class TimeOnlyConverter : System.ComponentModel.TypeConverter + { + public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; + public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) => throw null; + public override object ConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) => throw null; + public override object ConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, System.Type destinationType) => throw null; + public TimeOnlyConverter() => throw null; + } + public class TimeSpanConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1380,7 +1299,6 @@ namespace System public TimeSpanConverter() => throw null; } - // Generated from `System.ComponentModel.ToolboxItemAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ToolboxItemAttribute : System.Attribute { public static System.ComponentModel.ToolboxItemAttribute Default; @@ -1395,7 +1313,6 @@ namespace System public string ToolboxItemTypeName { get => throw null; } } - // Generated from `System.ComponentModel.ToolboxItemFilterAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ToolboxItemFilterAttribute : System.Attribute { public override bool Equals(object obj) => throw null; @@ -1409,7 +1326,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.ToolboxItemFilterType` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ToolboxItemFilterType : int { Allow = 0, @@ -1418,10 +1334,8 @@ namespace System Require = 3, } - // Generated from `System.ComponentModel.TypeConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeConverter { - // Generated from `System.ComponentModel.TypeConverter+SimplePropertyDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected abstract class SimplePropertyDescriptor : System.ComponentModel.PropertyDescriptor { public override bool CanResetValue(object component) => throw null; @@ -1435,7 +1349,6 @@ namespace System } - // Generated from `System.ComponentModel.TypeConverter+StandardValuesCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StandardValuesCollection : System.Collections.ICollection, System.Collections.IEnumerable { public void CopyTo(System.Array array, int index) => throw null; @@ -1489,7 +1402,6 @@ namespace System public TypeConverter() => throw null; } - // Generated from `System.ComponentModel.TypeDescriptionProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TypeDescriptionProvider { public virtual object CreateInstance(System.IServiceProvider provider, System.Type objectType, System.Type[] argTypes, object[] args) => throw null; @@ -1509,7 +1421,6 @@ namespace System protected TypeDescriptionProvider(System.ComponentModel.TypeDescriptionProvider parent) => throw null; } - // Generated from `System.ComponentModel.TypeDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeDescriptor { public static System.ComponentModel.TypeDescriptionProvider AddAttributes(System.Type type, params System.Attribute[] attributes) => throw null; @@ -1581,7 +1492,6 @@ namespace System public static void SortDescriptorArray(System.Collections.IList infos) => throw null; } - // Generated from `System.ComponentModel.TypeListConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TypeListConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1594,25 +1504,26 @@ namespace System protected TypeListConverter(System.Type[] types) => throw null; } - // Generated from `System.ComponentModel.UInt16Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class UInt128Converter : System.ComponentModel.BaseNumberConverter + { + public UInt128Converter() => throw null; + } + public class UInt16Converter : System.ComponentModel.BaseNumberConverter { public UInt16Converter() => throw null; } - // Generated from `System.ComponentModel.UInt32Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UInt32Converter : System.ComponentModel.BaseNumberConverter { public UInt32Converter() => throw null; } - // Generated from `System.ComponentModel.UInt64Converter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UInt64Converter : System.ComponentModel.BaseNumberConverter { public UInt64Converter() => throw null; } - // Generated from `System.ComponentModel.VersionConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VersionConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -1623,7 +1534,6 @@ namespace System public VersionConverter() => throw null; } - // Generated from `System.ComponentModel.WarningException` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WarningException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -1639,7 +1549,6 @@ namespace System namespace Design { - // Generated from `System.ComponentModel.Design.ActiveDesignerEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ActiveDesignerEventArgs : System.EventArgs { public ActiveDesignerEventArgs(System.ComponentModel.Design.IDesignerHost oldDesigner, System.ComponentModel.Design.IDesignerHost newDesigner) => throw null; @@ -1647,10 +1556,8 @@ namespace System public System.ComponentModel.Design.IDesignerHost OldDesigner { get => throw null; } } - // Generated from `System.ComponentModel.Design.ActiveDesignerEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ActiveDesignerEventHandler(object sender, System.ComponentModel.Design.ActiveDesignerEventArgs e); - // Generated from `System.ComponentModel.Design.CheckoutException` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CheckoutException : System.Runtime.InteropServices.ExternalException { public static System.ComponentModel.Design.CheckoutException Canceled; @@ -1661,7 +1568,6 @@ namespace System public CheckoutException(string message, int errorCode) => throw null; } - // Generated from `System.ComponentModel.Design.CommandID` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CommandID { public CommandID(System.Guid menuGroup, int commandID) => throw null; @@ -1672,7 +1578,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.ComponentModel.Design.ComponentChangedEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentChangedEventArgs : System.EventArgs { public object Component { get => throw null; } @@ -1682,10 +1587,8 @@ namespace System public object OldValue { get => throw null; } } - // Generated from `System.ComponentModel.Design.ComponentChangedEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ComponentChangedEventHandler(object sender, System.ComponentModel.Design.ComponentChangedEventArgs e); - // Generated from `System.ComponentModel.Design.ComponentChangingEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentChangingEventArgs : System.EventArgs { public object Component { get => throw null; } @@ -1693,20 +1596,16 @@ namespace System public System.ComponentModel.MemberDescriptor Member { get => throw null; } } - // Generated from `System.ComponentModel.Design.ComponentChangingEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ComponentChangingEventHandler(object sender, System.ComponentModel.Design.ComponentChangingEventArgs e); - // Generated from `System.ComponentModel.Design.ComponentEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentEventArgs : System.EventArgs { public virtual System.ComponentModel.IComponent Component { get => throw null; } public ComponentEventArgs(System.ComponentModel.IComponent component) => throw null; } - // Generated from `System.ComponentModel.Design.ComponentEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ComponentEventHandler(object sender, System.ComponentModel.Design.ComponentEventArgs e); - // Generated from `System.ComponentModel.Design.ComponentRenameEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentRenameEventArgs : System.EventArgs { public object Component { get => throw null; } @@ -1715,10 +1614,8 @@ namespace System public virtual string OldName { get => throw null; } } - // Generated from `System.ComponentModel.Design.ComponentRenameEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ComponentRenameEventHandler(object sender, System.ComponentModel.Design.ComponentRenameEventArgs e); - // Generated from `System.ComponentModel.Design.DesignerCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerCollection : System.Collections.ICollection, System.Collections.IEnumerable { void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; @@ -1733,20 +1630,16 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.ComponentModel.Design.DesignerEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerEventArgs : System.EventArgs { public System.ComponentModel.Design.IDesignerHost Designer { get => throw null; } public DesignerEventArgs(System.ComponentModel.Design.IDesignerHost host) => throw null; } - // Generated from `System.ComponentModel.Design.DesignerEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DesignerEventHandler(object sender, System.ComponentModel.Design.DesignerEventArgs e); - // Generated from `System.ComponentModel.Design.DesignerOptionService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DesignerOptionService : System.ComponentModel.Design.IDesignerOptionService { - // Generated from `System.ComponentModel.Design.DesignerOptionService+DesignerOptionCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerOptionCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { int System.Collections.IList.Add(object value) => throw null; @@ -1783,7 +1676,6 @@ namespace System protected virtual bool ShowDialog(System.ComponentModel.Design.DesignerOptionService.DesignerOptionCollection options, object optionObject) => throw null; } - // Generated from `System.ComponentModel.Design.DesignerTransaction` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DesignerTransaction : System.IDisposable { public void Cancel() => throw null; @@ -1800,7 +1692,6 @@ namespace System // ERR: Stub generator didn't handle member: ~DesignerTransaction } - // Generated from `System.ComponentModel.Design.DesignerTransactionCloseEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerTransactionCloseEventArgs : System.EventArgs { public DesignerTransactionCloseEventArgs(bool commit) => throw null; @@ -1809,10 +1700,8 @@ namespace System public bool TransactionCommitted { get => throw null; } } - // Generated from `System.ComponentModel.Design.DesignerTransactionCloseEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DesignerTransactionCloseEventHandler(object sender, System.ComponentModel.Design.DesignerTransactionCloseEventArgs e); - // Generated from `System.ComponentModel.Design.DesignerVerb` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerVerb : System.ComponentModel.Design.MenuCommand { public string Description { get => throw null; set => throw null; } @@ -1822,7 +1711,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.ComponentModel.Design.DesignerVerbCollection` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesignerVerbCollection : System.Collections.CollectionBase { public int Add(System.ComponentModel.Design.DesignerVerb value) => throw null; @@ -1839,7 +1727,6 @@ namespace System public void Remove(System.ComponentModel.Design.DesignerVerb value) => throw null; } - // Generated from `System.ComponentModel.Design.DesigntimeLicenseContext` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesigntimeLicenseContext : System.ComponentModel.LicenseContext { public DesigntimeLicenseContext() => throw null; @@ -1848,13 +1735,11 @@ namespace System public override System.ComponentModel.LicenseUsageMode UsageMode { get => throw null; } } - // Generated from `System.ComponentModel.Design.DesigntimeLicenseContextSerializer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DesigntimeLicenseContextSerializer { public static void Serialize(System.IO.Stream o, string cryptoKey, System.ComponentModel.Design.DesigntimeLicenseContext context) => throw null; } - // Generated from `System.ComponentModel.Design.HelpContextType` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HelpContextType : int { Ambient = 0, @@ -1863,7 +1748,6 @@ namespace System Window = 1, } - // Generated from `System.ComponentModel.Design.HelpKeywordAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HelpKeywordAttribute : System.Attribute { public static System.ComponentModel.Design.HelpKeywordAttribute Default; @@ -1876,7 +1760,6 @@ namespace System public override bool IsDefaultAttribute() => throw null; } - // Generated from `System.ComponentModel.Design.HelpKeywordType` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HelpKeywordType : int { F1Keyword = 0, @@ -1884,7 +1767,6 @@ namespace System GeneralKeyword = 1, } - // Generated from `System.ComponentModel.Design.IComponentChangeService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComponentChangeService { event System.ComponentModel.Design.ComponentEventHandler ComponentAdded; @@ -1898,20 +1780,17 @@ namespace System void OnComponentChanging(object component, System.ComponentModel.MemberDescriptor member); } - // Generated from `System.ComponentModel.Design.IComponentDiscoveryService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComponentDiscoveryService { System.Collections.ICollection GetComponentTypes(System.ComponentModel.Design.IDesignerHost designerHost, System.Type baseType); } - // Generated from `System.ComponentModel.Design.IComponentInitializer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComponentInitializer { void InitializeExistingComponent(System.Collections.IDictionary defaultValues); void InitializeNewComponent(System.Collections.IDictionary defaultValues); } - // Generated from `System.ComponentModel.Design.IDesigner` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesigner : System.IDisposable { System.ComponentModel.IComponent Component { get; } @@ -1920,7 +1799,6 @@ namespace System System.ComponentModel.Design.DesignerVerbCollection Verbs { get; } } - // Generated from `System.ComponentModel.Design.IDesignerEventService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerEventService { System.ComponentModel.Design.IDesignerHost ActiveDesigner { get; } @@ -1931,7 +1809,6 @@ namespace System event System.EventHandler SelectionChanged; } - // Generated from `System.ComponentModel.Design.IDesignerFilter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerFilter { void PostFilterAttributes(System.Collections.IDictionary attributes); @@ -1942,7 +1819,6 @@ namespace System void PreFilterProperties(System.Collections.IDictionary properties); } - // Generated from `System.ComponentModel.Design.IDesignerHost` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerHost : System.ComponentModel.Design.IServiceContainer, System.IServiceProvider { void Activate(); @@ -1968,20 +1844,17 @@ namespace System event System.EventHandler TransactionOpening; } - // Generated from `System.ComponentModel.Design.IDesignerHostTransactionState` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerHostTransactionState { bool IsClosingTransaction { get; } } - // Generated from `System.ComponentModel.Design.IDesignerOptionService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerOptionService { object GetOptionValue(string pageName, string valueName); void SetOptionValue(string pageName, string valueName, object value); } - // Generated from `System.ComponentModel.Design.IDictionaryService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDictionaryService { object GetKey(object value); @@ -1989,7 +1862,6 @@ namespace System void SetValue(object key, object value); } - // Generated from `System.ComponentModel.Design.IEventBindingService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEventBindingService { string CreateUniqueMethodName(System.ComponentModel.IComponent component, System.ComponentModel.EventDescriptor e); @@ -2002,20 +1874,17 @@ namespace System bool ShowCode(int lineNumber); } - // Generated from `System.ComponentModel.Design.IExtenderListService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IExtenderListService { System.ComponentModel.IExtenderProvider[] GetExtenderProviders(); } - // Generated from `System.ComponentModel.Design.IExtenderProviderService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IExtenderProviderService { void AddExtenderProvider(System.ComponentModel.IExtenderProvider provider); void RemoveExtenderProvider(System.ComponentModel.IExtenderProvider provider); } - // Generated from `System.ComponentModel.Design.IHelpService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IHelpService { void AddContextAttribute(string name, string value, System.ComponentModel.Design.HelpKeywordType keywordType); @@ -2027,14 +1896,12 @@ namespace System void ShowHelpFromUrl(string helpUrl); } - // Generated from `System.ComponentModel.Design.IInheritanceService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IInheritanceService { void AddInheritedComponents(System.ComponentModel.IComponent component, System.ComponentModel.IContainer container); System.ComponentModel.InheritanceAttribute GetInheritanceAttribute(System.ComponentModel.IComponent component); } - // Generated from `System.ComponentModel.Design.IMenuCommandService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IMenuCommandService { void AddCommand(System.ComponentModel.Design.MenuCommand command); @@ -2047,7 +1914,6 @@ namespace System System.ComponentModel.Design.DesignerVerbCollection Verbs { get; } } - // Generated from `System.ComponentModel.Design.IReferenceService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReferenceService { System.ComponentModel.IComponent GetComponent(object reference); @@ -2057,21 +1923,18 @@ namespace System object[] GetReferences(System.Type baseType); } - // Generated from `System.ComponentModel.Design.IResourceService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IResourceService { System.Resources.IResourceReader GetResourceReader(System.Globalization.CultureInfo info); System.Resources.IResourceWriter GetResourceWriter(System.Globalization.CultureInfo info); } - // Generated from `System.ComponentModel.Design.IRootDesigner` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IRootDesigner : System.ComponentModel.Design.IDesigner, System.IDisposable { object GetView(System.ComponentModel.Design.ViewTechnology technology); System.ComponentModel.Design.ViewTechnology[] SupportedTechnologies { get; } } - // Generated from `System.ComponentModel.Design.ISelectionService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISelectionService { bool GetComponentSelected(object component); @@ -2084,7 +1947,6 @@ namespace System void SetSelectedComponents(System.Collections.ICollection components, System.ComponentModel.Design.SelectionTypes selectionType); } - // Generated from `System.ComponentModel.Design.IServiceContainer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IServiceContainer : System.IServiceProvider { void AddService(System.Type serviceType, System.ComponentModel.Design.ServiceCreatorCallback callback); @@ -2095,14 +1957,12 @@ namespace System void RemoveService(System.Type serviceType, bool promote); } - // Generated from `System.ComponentModel.Design.ITreeDesigner` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITreeDesigner : System.ComponentModel.Design.IDesigner, System.IDisposable { System.Collections.ICollection Children { get; } System.ComponentModel.Design.IDesigner Parent { get; } } - // Generated from `System.ComponentModel.Design.ITypeDescriptorFilterService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeDescriptorFilterService { bool FilterAttributes(System.ComponentModel.IComponent component, System.Collections.IDictionary attributes); @@ -2110,13 +1970,11 @@ namespace System bool FilterProperties(System.ComponentModel.IComponent component, System.Collections.IDictionary properties); } - // Generated from `System.ComponentModel.Design.ITypeDiscoveryService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeDiscoveryService { System.Collections.ICollection GetTypes(System.Type baseType, bool excludeGlobalTypes); } - // Generated from `System.ComponentModel.Design.ITypeResolutionService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeResolutionService { System.Reflection.Assembly GetAssembly(System.Reflection.AssemblyName name); @@ -2128,7 +1986,6 @@ namespace System void ReferenceAssembly(System.Reflection.AssemblyName name); } - // Generated from `System.ComponentModel.Design.MenuCommand` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MenuCommand { public virtual bool Checked { get => throw null; set => throw null; } @@ -2146,7 +2003,6 @@ namespace System public virtual bool Visible { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.Design.SelectionTypes` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SelectionTypes : int { @@ -2163,7 +2019,6 @@ namespace System Valid = 31, } - // Generated from `System.ComponentModel.Design.ServiceContainer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ServiceContainer : System.ComponentModel.Design.IServiceContainer, System.IDisposable, System.IServiceProvider { public void AddService(System.Type serviceType, System.ComponentModel.Design.ServiceCreatorCallback callback) => throw null; @@ -2180,10 +2035,8 @@ namespace System public ServiceContainer(System.IServiceProvider parentProvider) => throw null; } - // Generated from `System.ComponentModel.Design.ServiceCreatorCallback` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate object ServiceCreatorCallback(System.ComponentModel.Design.IServiceContainer container, System.Type serviceType); - // Generated from `System.ComponentModel.Design.StandardCommands` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StandardCommands { public static System.ComponentModel.Design.CommandID AlignBottom; @@ -2244,7 +2097,6 @@ namespace System public static System.ComponentModel.Design.CommandID ViewGrid; } - // Generated from `System.ComponentModel.Design.StandardToolWindows` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StandardToolWindows { public static System.Guid ObjectBrowser; @@ -2258,7 +2110,6 @@ namespace System public static System.Guid Toolbox; } - // Generated from `System.ComponentModel.Design.TypeDescriptionProviderService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TypeDescriptionProviderService { public abstract System.ComponentModel.TypeDescriptionProvider GetProvider(System.Type type); @@ -2266,7 +2117,6 @@ namespace System protected TypeDescriptionProviderService() => throw null; } - // Generated from `System.ComponentModel.Design.ViewTechnology` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ViewTechnology : int { Default = 2, @@ -2276,7 +2126,6 @@ namespace System namespace Serialization { - // Generated from `System.ComponentModel.Design.Serialization.ComponentSerializationService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ComponentSerializationService { protected ComponentSerializationService() => throw null; @@ -2293,7 +2142,6 @@ namespace System public abstract void SerializeMemberAbsolute(System.ComponentModel.Design.Serialization.SerializationStore store, object owningObject, System.ComponentModel.MemberDescriptor member); } - // Generated from `System.ComponentModel.Design.Serialization.ContextStack` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContextStack { public void Append(object context) => throw null; @@ -2305,7 +2153,6 @@ namespace System public void Push(object context) => throw null; } - // Generated from `System.ComponentModel.Design.Serialization.DefaultSerializationProviderAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultSerializationProviderAttribute : System.Attribute { public DefaultSerializationProviderAttribute(System.Type providerType) => throw null; @@ -2313,7 +2160,6 @@ namespace System public string ProviderTypeName { get => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.DesignerLoader` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DesignerLoader { public abstract void BeginLoad(System.ComponentModel.Design.Serialization.IDesignerLoaderHost host); @@ -2323,21 +2169,18 @@ namespace System public virtual bool Loading { get => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerLoaderHost` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerLoaderHost : System.ComponentModel.Design.IDesignerHost, System.ComponentModel.Design.IServiceContainer, System.IServiceProvider { void EndLoad(string baseClassName, bool successful, System.Collections.ICollection errorCollection); void Reload(); } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerLoaderHost2` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerLoaderHost2 : System.ComponentModel.Design.IDesignerHost, System.ComponentModel.Design.IServiceContainer, System.ComponentModel.Design.Serialization.IDesignerLoaderHost, System.IServiceProvider { bool CanReloadWithErrors { get; set; } bool IgnoreErrorsDuringReload { get; set; } } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerLoaderService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerLoaderService { void AddLoadDependency(); @@ -2345,7 +2188,6 @@ namespace System bool Reload(); } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerSerializationManager` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerSerializationManager : System.IServiceProvider { void AddSerializationProvider(System.ComponentModel.Design.Serialization.IDesignerSerializationProvider provider); @@ -2363,20 +2205,17 @@ namespace System void SetName(object instance, string name); } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerSerializationProvider` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerSerializationProvider { object GetSerializer(System.ComponentModel.Design.Serialization.IDesignerSerializationManager manager, object currentSerializer, System.Type objectType, System.Type serializerType); } - // Generated from `System.ComponentModel.Design.Serialization.IDesignerSerializationService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDesignerSerializationService { System.Collections.ICollection Deserialize(object serializationData); object Serialize(System.Collections.ICollection objects); } - // Generated from `System.ComponentModel.Design.Serialization.INameCreationService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INameCreationService { string CreateName(System.ComponentModel.IContainer container, System.Type dataType); @@ -2384,7 +2223,6 @@ namespace System void ValidateName(string name); } - // Generated from `System.ComponentModel.Design.Serialization.InstanceDescriptor` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InstanceDescriptor { public System.Collections.ICollection Arguments { get => throw null; } @@ -2395,12 +2233,12 @@ namespace System public System.Reflection.MemberInfo MemberInfo { get => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.MemberRelationship` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct MemberRelationship + public struct MemberRelationship : System.IEquatable { public static bool operator !=(System.ComponentModel.Design.Serialization.MemberRelationship left, System.ComponentModel.Design.Serialization.MemberRelationship right) => throw null; public static bool operator ==(System.ComponentModel.Design.Serialization.MemberRelationship left, System.ComponentModel.Design.Serialization.MemberRelationship right) => throw null; public static System.ComponentModel.Design.Serialization.MemberRelationship Empty; + public bool Equals(System.ComponentModel.Design.Serialization.MemberRelationship other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; public bool IsEmpty { get => throw null; } @@ -2410,7 +2248,6 @@ namespace System public object Owner { get => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.MemberRelationshipService` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MemberRelationshipService { protected virtual System.ComponentModel.Design.Serialization.MemberRelationship GetRelationship(System.ComponentModel.Design.Serialization.MemberRelationship source) => throw null; @@ -2421,7 +2258,6 @@ namespace System public abstract bool SupportsRelationship(System.ComponentModel.Design.Serialization.MemberRelationship source, System.ComponentModel.Design.Serialization.MemberRelationship relationship); } - // Generated from `System.ComponentModel.Design.Serialization.ResolveNameEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResolveNameEventArgs : System.EventArgs { public string Name { get => throw null; } @@ -2429,10 +2265,8 @@ namespace System public object Value { get => throw null; set => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.ResolveNameEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ResolveNameEventHandler(object sender, System.ComponentModel.Design.Serialization.ResolveNameEventArgs e); - // Generated from `System.ComponentModel.Design.Serialization.RootDesignerSerializerAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RootDesignerSerializerAttribute : System.Attribute { public bool Reloadable { get => throw null; } @@ -2444,7 +2278,6 @@ namespace System public override object TypeId { get => throw null; } } - // Generated from `System.ComponentModel.Design.Serialization.SerializationStore` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SerializationStore : System.IDisposable { public abstract void Close(); @@ -2460,7 +2293,6 @@ namespace System } namespace Drawing { - // Generated from `System.Drawing.ColorConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ColorConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -2472,7 +2304,6 @@ namespace System public override bool GetStandardValuesSupported(System.ComponentModel.ITypeDescriptorContext context) => throw null; } - // Generated from `System.Drawing.PointConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PointConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -2486,7 +2317,6 @@ namespace System public PointConverter() => throw null; } - // Generated from `System.Drawing.RectangleConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RectangleConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -2500,7 +2330,6 @@ namespace System public RectangleConverter() => throw null; } - // Generated from `System.Drawing.SizeConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SizeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -2514,7 +2343,6 @@ namespace System public SizeConverter() => throw null; } - // Generated from `System.Drawing.SizeFConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SizeFConverter : System.ComponentModel.TypeConverter { public override bool CanConvertFrom(System.ComponentModel.ITypeDescriptorContext context, System.Type sourceType) => throw null; @@ -2535,7 +2363,6 @@ namespace System { namespace ExtendedProtection { - // Generated from `System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicyTypeConverter` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExtendedProtectionPolicyTypeConverter : System.ComponentModel.TypeConverter { public override bool CanConvertTo(System.ComponentModel.ITypeDescriptorContext context, System.Type destinationType) => throw null; @@ -2548,16 +2375,13 @@ namespace System } namespace Timers { - // Generated from `System.Timers.ElapsedEventArgs` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ElapsedEventArgs : System.EventArgs { public System.DateTime SignalTime { get => throw null; } } - // Generated from `System.Timers.ElapsedEventHandler` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ElapsedEventHandler(object sender, System.Timers.ElapsedEventArgs e); - // Generated from `System.Timers.Timer` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Timer : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize { public bool AutoReset { get => throw null; set => throw null; } @@ -2573,10 +2397,10 @@ namespace System public void Stop() => throw null; public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get => throw null; set => throw null; } public Timer() => throw null; + public Timer(System.TimeSpan interval) => throw null; public Timer(double interval) => throw null; } - // Generated from `System.Timers.TimersDescriptionAttribute` in `System.ComponentModel.TypeConverter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TimersDescriptionAttribute : System.ComponentModel.DescriptionAttribute { public override string Description { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.cs index 39e22fba8d0..ddfcd435eb3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ComponentModel.cs @@ -1,8 +1,8 @@ // This file contains auto-generated code. +// Generated from `System.ComponentModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { - // Generated from `System.IServiceProvider` in `System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IServiceProvider { object GetService(System.Type serviceType); @@ -10,7 +10,6 @@ namespace System namespace ComponentModel { - // Generated from `System.ComponentModel.CancelEventArgs` in `System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CancelEventArgs : System.EventArgs { public bool Cancel { get => throw null; set => throw null; } @@ -18,14 +17,12 @@ namespace System public CancelEventArgs(bool cancel) => throw null; } - // Generated from `System.ComponentModel.IChangeTracking` in `System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IChangeTracking { void AcceptChanges(); bool IsChanged { get; } } - // Generated from `System.ComponentModel.IEditableObject` in `System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEditableObject { void BeginEdit(); @@ -33,7 +30,6 @@ namespace System void EndEdit(); } - // Generated from `System.ComponentModel.IRevertibleChangeTracking` in `System.ComponentModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IRevertibleChangeTracking : System.ComponentModel.IChangeTracking { void RejectChanges(); diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Console.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Console.cs index 08eedc69809..37958e8a2a3 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Console.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Console.cs @@ -1,8 +1,8 @@ // This file contains auto-generated code. +// Generated from `System.Console, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { - // Generated from `System.Console` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Console { public static System.ConsoleColor BackgroundColor { get => throw null; set => throw null; } @@ -94,17 +94,14 @@ namespace System public static void WriteLine(System.UInt64 value) => throw null; } - // Generated from `System.ConsoleCancelEventArgs` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConsoleCancelEventArgs : System.EventArgs { public bool Cancel { get => throw null; set => throw null; } public System.ConsoleSpecialKey SpecialKey { get => throw null; } } - // Generated from `System.ConsoleCancelEventHandler` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ConsoleCancelEventHandler(object sender, System.ConsoleCancelEventArgs e); - // Generated from `System.ConsoleColor` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConsoleColor : int { Black = 0, @@ -125,7 +122,6 @@ namespace System Yellow = 14, } - // Generated from `System.ConsoleKey` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConsoleKey : int { A = 65, @@ -274,7 +270,6 @@ namespace System Zoom = 251, } - // Generated from `System.ConsoleKeyInfo` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConsoleKeyInfo : System.IEquatable { public static bool operator !=(System.ConsoleKeyInfo a, System.ConsoleKeyInfo b) => throw null; @@ -289,7 +284,6 @@ namespace System public System.ConsoleModifiers Modifiers { get => throw null; } } - // Generated from `System.ConsoleModifiers` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ConsoleModifiers : int { @@ -298,7 +292,6 @@ namespace System Shift = 2, } - // Generated from `System.ConsoleSpecialKey` in `System.Console, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConsoleSpecialKey : int { ControlBreak = 1, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Data.Common.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Data.Common.cs index 077da794bc0..86fa07c14cb 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Data.Common.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Data.Common.cs @@ -1,17 +1,16 @@ // This file contains auto-generated code. +// Generated from `System.Data.Common, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Data { - // Generated from `System.Data.AcceptRejectRule` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AcceptRejectRule : int { Cascade = 1, None = 0, } - // Generated from `System.Data.CommandBehavior` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CommandBehavior : int { @@ -24,7 +23,6 @@ namespace System SingleRow = 8, } - // Generated from `System.Data.CommandType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CommandType : int { StoredProcedure = 4, @@ -32,7 +30,6 @@ namespace System Text = 1, } - // Generated from `System.Data.ConflictOption` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConflictOption : int { CompareAllSearchableValues = 1, @@ -40,7 +37,6 @@ namespace System OverwriteChanges = 3, } - // Generated from `System.Data.ConnectionState` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ConnectionState : int { @@ -52,7 +48,6 @@ namespace System Open = 1, } - // Generated from `System.Data.Constraint` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Constraint { protected void CheckStateForProperty() => throw null; @@ -65,7 +60,6 @@ namespace System protected virtual System.Data.DataSet _DataSet { get => throw null; } } - // Generated from `System.Data.ConstraintCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConstraintCollection : System.Data.InternalDataCollectionBase { public void Add(System.Data.Constraint constraint) => throw null; @@ -89,7 +83,6 @@ namespace System public void RemoveAt(int index) => throw null; } - // Generated from `System.Data.ConstraintException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConstraintException : System.Data.DataException { public ConstraintException() => throw null; @@ -98,7 +91,6 @@ namespace System public ConstraintException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.DBConcurrencyException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DBConcurrencyException : System.SystemException { public void CopyToRows(System.Data.DataRow[] array) => throw null; @@ -112,7 +104,6 @@ namespace System public int RowCount { get => throw null; } } - // Generated from `System.Data.DataColumn` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataColumn : System.ComponentModel.MarshalByValueComponent { public bool AllowDBNull { get => throw null; set => throw null; } @@ -147,7 +138,6 @@ namespace System public bool Unique { get => throw null; set => throw null; } } - // Generated from `System.Data.DataColumnChangeEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataColumnChangeEventArgs : System.EventArgs { public System.Data.DataColumn Column { get => throw null; } @@ -156,10 +146,8 @@ namespace System public System.Data.DataRow Row { get => throw null; } } - // Generated from `System.Data.DataColumnChangeEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DataColumnChangeEventHandler(object sender, System.Data.DataColumnChangeEventArgs e); - // Generated from `System.Data.DataColumnCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataColumnCollection : System.Data.InternalDataCollectionBase { public System.Data.DataColumn Add() => throw null; @@ -183,7 +171,6 @@ namespace System public void RemoveAt(int index) => throw null; } - // Generated from `System.Data.DataException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataException : System.SystemException { public DataException() => throw null; @@ -192,7 +179,6 @@ namespace System public DataException(string s, System.Exception innerException) => throw null; } - // Generated from `System.Data.DataReaderExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataReaderExtensions { public static bool GetBoolean(this System.Data.Common.DbDataReader reader, string name) => throw null; @@ -223,7 +209,6 @@ namespace System public static System.Threading.Tasks.Task IsDBNullAsync(this System.Data.Common.DbDataReader reader, string name, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.Data.DataRelation` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRelation { protected void CheckStateForProperty() => throw null; @@ -248,7 +233,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Data.DataRelationCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DataRelationCollection : System.Data.InternalDataCollectionBase { public virtual System.Data.DataRelation Add(System.Data.DataColumn parentColumn, System.Data.DataColumn childColumn) => throw null; @@ -279,7 +263,6 @@ namespace System protected virtual void RemoveCore(System.Data.DataRelation relation) => throw null; } - // Generated from `System.Data.DataRow` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRow { public void AcceptChanges() => throw null; @@ -332,7 +315,6 @@ namespace System public System.Data.DataTable Table { get => throw null; } } - // Generated from `System.Data.DataRowAction` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DataRowAction : int { @@ -346,12 +328,10 @@ namespace System Rollback = 4, } - // Generated from `System.Data.DataRowBuilder` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRowBuilder { } - // Generated from `System.Data.DataRowChangeEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRowChangeEventArgs : System.EventArgs { public System.Data.DataRowAction Action { get => throw null; } @@ -359,10 +339,8 @@ namespace System public System.Data.DataRow Row { get => throw null; } } - // Generated from `System.Data.DataRowChangeEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DataRowChangeEventHandler(object sender, System.Data.DataRowChangeEventArgs e); - // Generated from `System.Data.DataRowCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRowCollection : System.Data.InternalDataCollectionBase { public void Add(System.Data.DataRow row) => throw null; @@ -383,13 +361,11 @@ namespace System public void RemoveAt(int index) => throw null; } - // Generated from `System.Data.DataRowComparer` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataRowComparer { public static System.Data.DataRowComparer Default { get => throw null; } } - // Generated from `System.Data.DataRowComparer<>` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRowComparer : System.Collections.Generic.IEqualityComparer where TRow : System.Data.DataRow { public static System.Data.DataRowComparer Default { get => throw null; } @@ -397,7 +373,6 @@ namespace System public int GetHashCode(TRow row) => throw null; } - // Generated from `System.Data.DataRowExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataRowExtensions { public static T Field(this System.Data.DataRow row, System.Data.DataColumn column) => throw null; @@ -411,7 +386,6 @@ namespace System public static void SetField(this System.Data.DataRow row, string columnName, T value) => throw null; } - // Generated from `System.Data.DataRowState` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DataRowState : int { @@ -422,7 +396,6 @@ namespace System Unchanged = 2, } - // Generated from `System.Data.DataRowVersion` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DataRowVersion : int { Current = 512, @@ -431,7 +404,6 @@ namespace System Proposed = 1024, } - // Generated from `System.Data.DataRowView` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataRowView : System.ComponentModel.ICustomTypeDescriptor, System.ComponentModel.IDataErrorInfo, System.ComponentModel.IEditableObject, System.ComponentModel.INotifyPropertyChanged { public void BeginEdit() => throw null; @@ -468,7 +440,6 @@ namespace System public System.Data.DataRowVersion RowVersion { get => throw null; } } - // Generated from `System.Data.DataSet` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataSet : System.ComponentModel.MarshalByValueComponent, System.ComponentModel.IListSource, System.ComponentModel.ISupportInitialize, System.ComponentModel.ISupportInitializeNotification, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable { public void AcceptChanges() => throw null; @@ -572,7 +543,6 @@ namespace System public void WriteXmlSchema(string fileName, System.Converter multipleTargetConverter) => throw null; } - // Generated from `System.Data.DataSetDateTime` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DataSetDateTime : int { Local = 1, @@ -581,14 +551,12 @@ namespace System Utc = 4, } - // Generated from `System.Data.DataSysDescriptionAttribute` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataSysDescriptionAttribute : System.ComponentModel.DescriptionAttribute { public DataSysDescriptionAttribute(string description) => throw null; public override string Description { get => throw null; } } - // Generated from `System.Data.DataTable` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTable : System.ComponentModel.MarshalByValueComponent, System.ComponentModel.IListSource, System.ComponentModel.ISupportInitialize, System.ComponentModel.ISupportInitializeNotification, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable { public void AcceptChanges() => throw null; @@ -714,7 +682,6 @@ namespace System protected internal bool fInitInProgress; } - // Generated from `System.Data.DataTableClearEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableClearEventArgs : System.EventArgs { public DataTableClearEventArgs(System.Data.DataTable dataTable) => throw null; @@ -723,10 +690,8 @@ namespace System public string TableNamespace { get => throw null; } } - // Generated from `System.Data.DataTableClearEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DataTableClearEventHandler(object sender, System.Data.DataTableClearEventArgs e); - // Generated from `System.Data.DataTableCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableCollection : System.Data.InternalDataCollectionBase { public System.Data.DataTable Add() => throw null; @@ -754,7 +719,6 @@ namespace System public void RemoveAt(int index) => throw null; } - // Generated from `System.Data.DataTableExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataTableExtensions { public static System.Data.DataView AsDataView(this System.Data.DataTable table) => throw null; @@ -765,17 +729,14 @@ namespace System public static void CopyToDataTable(this System.Collections.Generic.IEnumerable source, System.Data.DataTable table, System.Data.LoadOption options, System.Data.FillErrorEventHandler errorHandler) where T : System.Data.DataRow => throw null; } - // Generated from `System.Data.DataTableNewRowEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableNewRowEventArgs : System.EventArgs { public DataTableNewRowEventArgs(System.Data.DataRow dataRow) => throw null; public System.Data.DataRow Row { get => throw null; } } - // Generated from `System.Data.DataTableNewRowEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DataTableNewRowEventHandler(object sender, System.Data.DataTableNewRowEventArgs e); - // Generated from `System.Data.DataTableReader` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableReader : System.Data.Common.DbDataReader { public override void Close() => throw null; @@ -818,7 +779,6 @@ namespace System public override int RecordsAffected { get => throw null; } } - // Generated from `System.Data.DataView` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataView : System.ComponentModel.MarshalByValueComponent, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.IBindingListView, System.ComponentModel.ISupportInitialize, System.ComponentModel.ISupportInitializeNotification, System.ComponentModel.ITypedList { int System.Collections.IList.Add(object value) => throw null; @@ -900,7 +860,6 @@ namespace System protected virtual void UpdateIndex(bool force) => throw null; } - // Generated from `System.Data.DataViewManager` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataViewManager : System.ComponentModel.MarshalByValueComponent, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ComponentModel.IBindingList, System.ComponentModel.ITypedList { int System.Collections.IList.Add(object value) => throw null; @@ -947,7 +906,6 @@ namespace System protected virtual void TableCollectionChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e) => throw null; } - // Generated from `System.Data.DataViewRowState` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DataViewRowState : int { @@ -961,7 +919,6 @@ namespace System Unchanged = 2, } - // Generated from `System.Data.DataViewSetting` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataViewSetting { public bool ApplyDefaultSort { get => throw null; set => throw null; } @@ -972,7 +929,6 @@ namespace System public System.Data.DataTable Table { get => throw null; } } - // Generated from `System.Data.DataViewSettingCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataViewSettingCollection : System.Collections.ICollection, System.Collections.IEnumerable { public void CopyTo(System.Array ar, int index) => throw null; @@ -987,7 +943,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Data.DbType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DbType : int { AnsiString = 0, @@ -1019,7 +974,6 @@ namespace System Xml = 25, } - // Generated from `System.Data.DeletedRowInaccessibleException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DeletedRowInaccessibleException : System.Data.DataException { public DeletedRowInaccessibleException() => throw null; @@ -1028,7 +982,6 @@ namespace System public DeletedRowInaccessibleException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.DuplicateNameException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DuplicateNameException : System.Data.DataException { public DuplicateNameException() => throw null; @@ -1037,14 +990,12 @@ namespace System public DuplicateNameException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.EnumerableRowCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EnumerableRowCollection : System.Collections.IEnumerable { internal EnumerableRowCollection() => throw null; System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Data.EnumerableRowCollection<>` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumerableRowCollection : System.Data.EnumerableRowCollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { internal EnumerableRowCollection() => throw null; @@ -1052,7 +1003,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Data.EnumerableRowCollectionExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class EnumerableRowCollectionExtensions { public static System.Data.EnumerableRowCollection Cast(this System.Data.EnumerableRowCollection source) => throw null; @@ -1068,7 +1018,6 @@ namespace System public static System.Data.EnumerableRowCollection Where(this System.Data.EnumerableRowCollection source, System.Func predicate) => throw null; } - // Generated from `System.Data.EvaluateException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EvaluateException : System.Data.InvalidExpressionException { public EvaluateException() => throw null; @@ -1077,7 +1026,6 @@ namespace System public EvaluateException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.FillErrorEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FillErrorEventArgs : System.EventArgs { public bool Continue { get => throw null; set => throw null; } @@ -1087,10 +1035,8 @@ namespace System public object[] Values { get => throw null; } } - // Generated from `System.Data.FillErrorEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void FillErrorEventHandler(object sender, System.Data.FillErrorEventArgs e); - // Generated from `System.Data.ForeignKeyConstraint` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ForeignKeyConstraint : System.Data.Constraint { public virtual System.Data.AcceptRejectRule AcceptRejectRule { get => throw null; set => throw null; } @@ -1110,14 +1056,12 @@ namespace System public virtual System.Data.Rule UpdateRule { get => throw null; set => throw null; } } - // Generated from `System.Data.IColumnMapping` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IColumnMapping { string DataSetColumn { get; set; } string SourceColumn { get; set; } } - // Generated from `System.Data.IColumnMappingCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IColumnMappingCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { System.Data.IColumnMapping Add(string sourceColumnName, string dataSetColumnName); @@ -1128,7 +1072,6 @@ namespace System void RemoveAt(string sourceColumnName); } - // Generated from `System.Data.IDataAdapter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataAdapter { int Fill(System.Data.DataSet dataSet); @@ -1140,7 +1083,6 @@ namespace System int Update(System.Data.DataSet dataSet); } - // Generated from `System.Data.IDataParameter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataParameter { System.Data.DbType DbType { get; set; } @@ -1152,7 +1094,6 @@ namespace System object Value { get; set; } } - // Generated from `System.Data.IDataParameterCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataParameterCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { bool Contains(string parameterName); @@ -1161,7 +1102,6 @@ namespace System void RemoveAt(string parameterName); } - // Generated from `System.Data.IDataReader` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataReader : System.Data.IDataRecord, System.IDisposable { void Close(); @@ -1173,7 +1113,6 @@ namespace System int RecordsAffected { get; } } - // Generated from `System.Data.IDataRecord` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataRecord { int FieldCount { get; } @@ -1203,7 +1142,6 @@ namespace System object this[string name] { get; } } - // Generated from `System.Data.IDbCommand` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbCommand : System.IDisposable { void Cancel(); @@ -1222,7 +1160,6 @@ namespace System System.Data.UpdateRowSource UpdatedRowSource { get; set; } } - // Generated from `System.Data.IDbConnection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbConnection : System.IDisposable { System.Data.IDbTransaction BeginTransaction(); @@ -1237,7 +1174,6 @@ namespace System System.Data.ConnectionState State { get; } } - // Generated from `System.Data.IDbDataAdapter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbDataAdapter : System.Data.IDataAdapter { System.Data.IDbCommand DeleteCommand { get; set; } @@ -1246,7 +1182,6 @@ namespace System System.Data.IDbCommand UpdateCommand { get; set; } } - // Generated from `System.Data.IDbDataParameter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbDataParameter : System.Data.IDataParameter { System.Byte Precision { get; set; } @@ -1254,7 +1189,6 @@ namespace System int Size { get; set; } } - // Generated from `System.Data.IDbTransaction` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbTransaction : System.IDisposable { void Commit(); @@ -1263,7 +1197,6 @@ namespace System void Rollback(); } - // Generated from `System.Data.ITableMapping` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITableMapping { System.Data.IColumnMappingCollection ColumnMappings { get; } @@ -1271,7 +1204,6 @@ namespace System string SourceTable { get; set; } } - // Generated from `System.Data.ITableMappingCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITableMappingCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { System.Data.ITableMapping Add(string sourceTableName, string dataSetTableName); @@ -1282,7 +1214,6 @@ namespace System void RemoveAt(string sourceTableName); } - // Generated from `System.Data.InRowChangingEventException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InRowChangingEventException : System.Data.DataException { public InRowChangingEventException() => throw null; @@ -1291,7 +1222,6 @@ namespace System public InRowChangingEventException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.InternalDataCollectionBase` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InternalDataCollectionBase : System.Collections.ICollection, System.Collections.IEnumerable { public virtual void CopyTo(System.Array ar, int index) => throw null; @@ -1304,7 +1234,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Data.InvalidConstraintException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidConstraintException : System.Data.DataException { public InvalidConstraintException() => throw null; @@ -1313,7 +1242,6 @@ namespace System public InvalidConstraintException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.InvalidExpressionException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidExpressionException : System.Data.DataException { public InvalidExpressionException() => throw null; @@ -1322,7 +1250,6 @@ namespace System public InvalidExpressionException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.IsolationLevel` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum IsolationLevel : int { Chaos = 16, @@ -1334,14 +1261,12 @@ namespace System Unspecified = -1, } - // Generated from `System.Data.KeyRestrictionBehavior` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum KeyRestrictionBehavior : int { AllowOnly = 0, PreventUsage = 1, } - // Generated from `System.Data.LoadOption` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LoadOption : int { OverwriteChanges = 1, @@ -1349,7 +1274,6 @@ namespace System Upsert = 3, } - // Generated from `System.Data.MappingType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MappingType : int { Attribute = 2, @@ -1358,7 +1282,6 @@ namespace System SimpleContent = 3, } - // Generated from `System.Data.MergeFailedEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MergeFailedEventArgs : System.EventArgs { public string Conflict { get => throw null; } @@ -1366,10 +1289,8 @@ namespace System public System.Data.DataTable Table { get => throw null; } } - // Generated from `System.Data.MergeFailedEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void MergeFailedEventHandler(object sender, System.Data.MergeFailedEventArgs e); - // Generated from `System.Data.MissingMappingAction` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MissingMappingAction : int { Error = 3, @@ -1377,7 +1298,6 @@ namespace System Passthrough = 1, } - // Generated from `System.Data.MissingPrimaryKeyException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingPrimaryKeyException : System.Data.DataException { public MissingPrimaryKeyException() => throw null; @@ -1386,7 +1306,6 @@ namespace System public MissingPrimaryKeyException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.MissingSchemaAction` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MissingSchemaAction : int { Add = 1, @@ -1395,7 +1314,6 @@ namespace System Ignore = 2, } - // Generated from `System.Data.NoNullAllowedException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NoNullAllowedException : System.Data.DataException { public NoNullAllowedException() => throw null; @@ -1404,12 +1322,10 @@ namespace System public NoNullAllowedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.OrderedEnumerableRowCollection<>` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OrderedEnumerableRowCollection : System.Data.EnumerableRowCollection { } - // Generated from `System.Data.ParameterDirection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ParameterDirection : int { Input = 1, @@ -1418,7 +1334,6 @@ namespace System ReturnValue = 6, } - // Generated from `System.Data.PropertyCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyCollection : System.Collections.Hashtable, System.ICloneable { public override object Clone() => throw null; @@ -1426,7 +1341,6 @@ namespace System protected PropertyCollection(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; } - // Generated from `System.Data.ReadOnlyException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyException : System.Data.DataException { public ReadOnlyException() => throw null; @@ -1435,7 +1349,6 @@ namespace System public ReadOnlyException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.RowNotInTableException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RowNotInTableException : System.Data.DataException { public RowNotInTableException() => throw null; @@ -1444,7 +1357,6 @@ namespace System public RowNotInTableException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.Rule` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Rule : int { Cascade = 1, @@ -1453,28 +1365,24 @@ namespace System SetNull = 2, } - // Generated from `System.Data.SchemaSerializationMode` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SchemaSerializationMode : int { ExcludeSchema = 2, IncludeSchema = 1, } - // Generated from `System.Data.SchemaType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SchemaType : int { Mapped = 2, Source = 1, } - // Generated from `System.Data.SerializationFormat` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SerializationFormat : int { Binary = 1, Xml = 0, } - // Generated from `System.Data.SqlDbType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SqlDbType : int { BigInt = 0, @@ -1510,7 +1418,6 @@ namespace System Xml = 25, } - // Generated from `System.Data.StateChangeEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StateChangeEventArgs : System.EventArgs { public System.Data.ConnectionState CurrentState { get => throw null; } @@ -1518,20 +1425,16 @@ namespace System public StateChangeEventArgs(System.Data.ConnectionState originalState, System.Data.ConnectionState currentState) => throw null; } - // Generated from `System.Data.StateChangeEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void StateChangeEventHandler(object sender, System.Data.StateChangeEventArgs e); - // Generated from `System.Data.StatementCompletedEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StatementCompletedEventArgs : System.EventArgs { public int RecordCount { get => throw null; } public StatementCompletedEventArgs(int recordCount) => throw null; } - // Generated from `System.Data.StatementCompletedEventHandler` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void StatementCompletedEventHandler(object sender, System.Data.StatementCompletedEventArgs e); - // Generated from `System.Data.StatementType` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum StatementType : int { Batch = 4, @@ -1541,7 +1444,6 @@ namespace System Update = 2, } - // Generated from `System.Data.StrongTypingException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StrongTypingException : System.Data.DataException { public StrongTypingException() => throw null; @@ -1550,7 +1452,6 @@ namespace System public StrongTypingException(string s, System.Exception innerException) => throw null; } - // Generated from `System.Data.SyntaxErrorException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SyntaxErrorException : System.Data.InvalidExpressionException { public SyntaxErrorException() => throw null; @@ -1559,7 +1460,6 @@ namespace System public SyntaxErrorException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.TypedTableBase<>` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TypedTableBase : System.Data.DataTable, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable where T : System.Data.DataRow { public System.Data.EnumerableRowCollection Cast() => throw null; @@ -1569,7 +1469,6 @@ namespace System protected TypedTableBase(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; } - // Generated from `System.Data.TypedTableBaseExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class TypedTableBaseExtensions { public static System.Data.EnumerableRowCollection AsEnumerable(this System.Data.TypedTableBase source) where TRow : System.Data.DataRow => throw null; @@ -1582,7 +1481,6 @@ namespace System public static System.Data.EnumerableRowCollection Where(this System.Data.TypedTableBase source, System.Func predicate) where TRow : System.Data.DataRow => throw null; } - // Generated from `System.Data.UniqueConstraint` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UniqueConstraint : System.Data.Constraint { public virtual System.Data.DataColumn[] Columns { get => throw null; } @@ -1601,7 +1499,6 @@ namespace System public UniqueConstraint(string name, string[] columnNames, bool isPrimaryKey) => throw null; } - // Generated from `System.Data.UpdateRowSource` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UpdateRowSource : int { Both = 3, @@ -1610,7 +1507,6 @@ namespace System OutputParameters = 1, } - // Generated from `System.Data.UpdateStatus` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UpdateStatus : int { Continue = 0, @@ -1619,7 +1515,6 @@ namespace System SkipCurrentRow = 2, } - // Generated from `System.Data.VersionNotFoundException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VersionNotFoundException : System.Data.DataException { public VersionNotFoundException() => throw null; @@ -1628,7 +1523,6 @@ namespace System public VersionNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Data.XmlReadMode` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlReadMode : int { Auto = 0, @@ -1640,7 +1534,6 @@ namespace System ReadSchema = 1, } - // Generated from `System.Data.XmlWriteMode` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlWriteMode : int { DiffGram = 2, @@ -1650,14 +1543,12 @@ namespace System namespace Common { - // Generated from `System.Data.Common.CatalogLocation` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CatalogLocation : int { End = 2, Start = 1, } - // Generated from `System.Data.Common.DataAdapter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataAdapter : System.ComponentModel.Component, System.Data.IDataAdapter { public bool AcceptChangesDuringFill { get => throw null; set => throw null; } @@ -1692,7 +1583,6 @@ namespace System public virtual int Update(System.Data.DataSet dataSet) => throw null; } - // Generated from `System.Data.Common.DataColumnMapping` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataColumnMapping : System.MarshalByRefObject, System.Data.IColumnMapping, System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -1705,7 +1595,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Data.Common.DataColumnMappingCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataColumnMappingCollection : System.MarshalByRefObject, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Data.IColumnMappingCollection { public int Add(object value) => throw null; @@ -1744,7 +1633,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Data.Common.DataTableMapping` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableMapping : System.MarshalByRefObject, System.Data.ITableMapping, System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -1761,7 +1649,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Data.Common.DataTableMappingCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataTableMappingCollection : System.MarshalByRefObject, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Data.ITableMappingCollection { public int Add(object value) => throw null; @@ -1799,7 +1686,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Data.Common.DbBatch` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbBatch : System.IAsyncDisposable, System.IDisposable { public System.Data.Common.DbBatchCommandCollection BatchCommands { get => throw null; } @@ -1828,7 +1714,6 @@ namespace System public System.Data.Common.DbTransaction Transaction { get => throw null; set => throw null; } } - // Generated from `System.Data.Common.DbBatchCommand` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbBatchCommand { public abstract string CommandText { get; set; } @@ -1839,7 +1724,6 @@ namespace System public abstract int RecordsAffected { get; } } - // Generated from `System.Data.Common.DbBatchCommandCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbBatchCommandCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { public abstract void Add(System.Data.Common.DbBatchCommand item); @@ -1860,7 +1744,6 @@ namespace System protected abstract void SetBatchCommand(int index, System.Data.Common.DbBatchCommand batchCommand); } - // Generated from `System.Data.Common.DbColumn` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbColumn { public bool? AllowDBNull { get => throw null; set => throw null; } @@ -1890,7 +1773,6 @@ namespace System public string UdtAssemblyQualifiedName { get => throw null; set => throw null; } } - // Generated from `System.Data.Common.DbCommand` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbCommand : System.ComponentModel.Component, System.Data.IDbCommand, System.IAsyncDisposable, System.IDisposable { public abstract void Cancel(); @@ -1933,7 +1815,6 @@ namespace System public abstract System.Data.UpdateRowSource UpdatedRowSource { get; set; } } - // Generated from `System.Data.Common.DbCommandBuilder` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbCommandBuilder : System.ComponentModel.Component { protected abstract void ApplyParameterInfo(System.Data.Common.DbParameter parameter, System.Data.DataRow row, System.Data.StatementType statementType, bool whereClause); @@ -1965,7 +1846,6 @@ namespace System public virtual string UnquoteIdentifier(string quotedIdentifier) => throw null; } - // Generated from `System.Data.Common.DbConnection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbConnection : System.ComponentModel.Component, System.Data.IDbConnection, System.IAsyncDisposable, System.IDisposable { protected abstract System.Data.Common.DbTransaction BeginDbTransaction(System.Data.IsolationLevel isolationLevel); @@ -2009,7 +1889,6 @@ namespace System public virtual event System.Data.StateChangeEventHandler StateChange; } - // Generated from `System.Data.Common.DbConnectionStringBuilder` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DbConnectionStringBuilder : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ComponentModel.ICustomTypeDescriptor { void System.Collections.IDictionary.Add(object keyword, object value) => throw null; @@ -2057,7 +1936,6 @@ namespace System public virtual System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Data.Common.DbDataAdapter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbDataAdapter : System.Data.Common.DataAdapter, System.Data.IDataAdapter, System.Data.IDbDataAdapter, System.ICloneable { protected virtual int AddToBatch(System.Data.IDbCommand command) => throw null; @@ -2107,7 +1985,6 @@ namespace System System.Data.IDbCommand System.Data.IDbDataAdapter.UpdateCommand { get => throw null; set => throw null; } } - // Generated from `System.Data.Common.DbDataReader` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbDataReader : System.MarshalByRefObject, System.Collections.IEnumerable, System.Data.IDataReader, System.Data.IDataRecord, System.IAsyncDisposable, System.IDisposable { public virtual void Close() => throw null; @@ -2170,14 +2047,12 @@ namespace System public virtual int VisibleFieldCount { get => throw null; } } - // Generated from `System.Data.Common.DbDataReaderExtensions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DbDataReaderExtensions { public static bool CanGetColumnSchema(this System.Data.Common.DbDataReader reader) => throw null; public static System.Collections.ObjectModel.ReadOnlyCollection GetColumnSchema(this System.Data.Common.DbDataReader reader) => throw null; } - // Generated from `System.Data.Common.DbDataRecord` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbDataRecord : System.ComponentModel.ICustomTypeDescriptor, System.Data.IDataRecord { protected DbDataRecord() => throw null; @@ -2221,14 +2096,32 @@ namespace System public abstract object this[string name] { get; } } - // Generated from `System.Data.Common.DbDataSourceEnumerator` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public abstract class DbDataSource : System.IAsyncDisposable, System.IDisposable + { + public abstract string ConnectionString { get; } + public System.Data.Common.DbBatch CreateBatch() => throw null; + public System.Data.Common.DbCommand CreateCommand(string commandText = default(string)) => throw null; + public System.Data.Common.DbConnection CreateConnection() => throw null; + protected virtual System.Data.Common.DbBatch CreateDbBatch() => throw null; + protected virtual System.Data.Common.DbCommand CreateDbCommand(string commandText = default(string)) => throw null; + protected abstract System.Data.Common.DbConnection CreateDbConnection(); + protected DbDataSource() => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + protected virtual System.Threading.Tasks.ValueTask DisposeAsyncCore() => throw null; + public System.Data.Common.DbConnection OpenConnection() => throw null; + public System.Threading.Tasks.ValueTask OpenConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected virtual System.Data.Common.DbConnection OpenDbConnection() => throw null; + protected virtual System.Threading.Tasks.ValueTask OpenDbConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + } + public abstract class DbDataSourceEnumerator { protected DbDataSourceEnumerator() => throw null; public abstract System.Data.DataTable GetDataSources(); } - // Generated from `System.Data.Common.DbEnumerator` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DbEnumerator : System.Collections.IEnumerator { public object Current { get => throw null; } @@ -2240,7 +2133,6 @@ namespace System public void Reset() => throw null; } - // Generated from `System.Data.Common.DbException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbException : System.Runtime.InteropServices.ExternalException { public System.Data.Common.DbBatchCommand BatchCommand { get => throw null; } @@ -2254,7 +2146,6 @@ namespace System public virtual string SqlState { get => throw null; } } - // Generated from `System.Data.Common.DbMetaDataCollectionNames` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DbMetaDataCollectionNames { public static string DataSourceInformation; @@ -2264,7 +2155,6 @@ namespace System public static string Restrictions; } - // Generated from `System.Data.Common.DbMetaDataColumnNames` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DbMetaDataColumnNames { public static string CollectionName; @@ -2312,7 +2202,6 @@ namespace System public static string TypeName; } - // Generated from `System.Data.Common.DbParameter` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbParameter : System.MarshalByRefObject, System.Data.IDataParameter, System.Data.IDbDataParameter { protected DbParameter() => throw null; @@ -2332,7 +2221,6 @@ namespace System public abstract object Value { get; set; } } - // Generated from `System.Data.Common.DbParameterCollection` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbParameterCollection : System.MarshalByRefObject, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Data.IDataParameterCollection { public abstract int Add(object value); @@ -2369,7 +2257,6 @@ namespace System public abstract object SyncRoot { get; } } - // Generated from `System.Data.Common.DbProviderFactories` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DbProviderFactories { public static System.Data.Common.DbProviderFactory GetFactory(System.Data.DataRow providerRow) => throw null; @@ -2384,7 +2271,6 @@ namespace System public static bool UnregisterFactory(string providerInvariantName) => throw null; } - // Generated from `System.Data.Common.DbProviderFactory` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbProviderFactory { public virtual bool CanCreateBatch { get => throw null; } @@ -2398,19 +2284,18 @@ namespace System public virtual System.Data.Common.DbConnection CreateConnection() => throw null; public virtual System.Data.Common.DbConnectionStringBuilder CreateConnectionStringBuilder() => throw null; public virtual System.Data.Common.DbDataAdapter CreateDataAdapter() => throw null; + public virtual System.Data.Common.DbDataSource CreateDataSource(string connectionString) => throw null; public virtual System.Data.Common.DbDataSourceEnumerator CreateDataSourceEnumerator() => throw null; public virtual System.Data.Common.DbParameter CreateParameter() => throw null; protected DbProviderFactory() => throw null; } - // Generated from `System.Data.Common.DbProviderSpecificTypePropertyAttribute` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DbProviderSpecificTypePropertyAttribute : System.Attribute { public DbProviderSpecificTypePropertyAttribute(bool isProviderSpecificTypeProperty) => throw null; public bool IsProviderSpecificTypeProperty { get => throw null; } } - // Generated from `System.Data.Common.DbTransaction` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DbTransaction : System.MarshalByRefObject, System.Data.IDbTransaction, System.IAsyncDisposable, System.IDisposable { public abstract void Commit(); @@ -2434,7 +2319,6 @@ namespace System public virtual bool SupportsSavepoints { get => throw null; } } - // Generated from `System.Data.Common.GroupByBehavior` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GroupByBehavior : int { ExactMatch = 4, @@ -2444,13 +2328,11 @@ namespace System Unrelated = 2, } - // Generated from `System.Data.Common.IDbColumnSchemaGenerator` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDbColumnSchemaGenerator { System.Collections.ObjectModel.ReadOnlyCollection GetColumnSchema(); } - // Generated from `System.Data.Common.IdentifierCase` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum IdentifierCase : int { Insensitive = 1, @@ -2458,7 +2340,6 @@ namespace System Unknown = 0, } - // Generated from `System.Data.Common.RowUpdatedEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RowUpdatedEventArgs : System.EventArgs { public System.Data.IDbCommand Command { get => throw null; } @@ -2474,7 +2355,6 @@ namespace System public System.Data.Common.DataTableMapping TableMapping { get => throw null; } } - // Generated from `System.Data.Common.RowUpdatingEventArgs` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RowUpdatingEventArgs : System.EventArgs { protected virtual System.Data.IDbCommand BaseCommand { get => throw null; set => throw null; } @@ -2487,7 +2367,6 @@ namespace System public System.Data.Common.DataTableMapping TableMapping { get => throw null; } } - // Generated from `System.Data.Common.SchemaTableColumn` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SchemaTableColumn { public static string AllowDBNull; @@ -2509,7 +2388,6 @@ namespace System public static string ProviderType; } - // Generated from `System.Data.Common.SchemaTableOptionalColumn` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SchemaTableOptionalColumn { public static string AutoIncrementSeed; @@ -2528,7 +2406,6 @@ namespace System public static string ProviderSpecificDataType; } - // Generated from `System.Data.Common.SupportedJoinOperators` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SupportedJoinOperators : int { @@ -2542,13 +2419,11 @@ namespace System } namespace SqlTypes { - // Generated from `System.Data.SqlTypes.INullable` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INullable { bool IsNull { get; } } - // Generated from `System.Data.SqlTypes.SqlAlreadyFilledException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlAlreadyFilledException : System.Data.SqlTypes.SqlTypeException { public SqlAlreadyFilledException() => throw null; @@ -2556,8 +2431,7 @@ namespace System public SqlAlreadyFilledException(string message, System.Exception e) => throw null; } - // Generated from `System.Data.SqlTypes.SqlBinary` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlBinary : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) => throw null; public static System.Data.SqlTypes.SqlBinary operator +(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) => throw null; @@ -2570,6 +2444,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlBinary value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlBinary Concat(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlBinary other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBinary x, System.Data.SqlTypes.SqlBinary y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -2590,14 +2465,14 @@ namespace System public System.Data.SqlTypes.SqlGuid ToSqlGuid() => throw null; public override string ToString() => throw null; public System.Byte[] Value { get => throw null; } + public static System.Data.SqlTypes.SqlBinary WrapBytes(System.Byte[] bytes) => throw null; void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) => throw null; public static explicit operator System.Byte[](System.Data.SqlTypes.SqlBinary x) => throw null; public static explicit operator System.Data.SqlTypes.SqlBinary(System.Data.SqlTypes.SqlGuid x) => throw null; public static implicit operator System.Data.SqlTypes.SqlBinary(System.Byte[] x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlBoolean` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlBoolean : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !(System.Data.SqlTypes.SqlBoolean x) => throw null; public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) => throw null; @@ -2611,6 +2486,7 @@ namespace System public System.Byte ByteValue { get => throw null; } public int CompareTo(System.Data.SqlTypes.SqlBoolean value) => throw null; public int CompareTo(object value) => throw null; + public bool Equals(System.Data.SqlTypes.SqlBoolean other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlBoolean x, System.Data.SqlTypes.SqlBoolean y) => throw null; public override bool Equals(object value) => throw null; public static System.Data.SqlTypes.SqlBoolean False; @@ -2667,8 +2543,7 @@ namespace System public static System.Data.SqlTypes.SqlBoolean operator ~(System.Data.SqlTypes.SqlBoolean x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlByte` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlByte : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) => throw null; public static System.Data.SqlTypes.SqlByte operator %(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) => throw null; @@ -2688,6 +2563,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlByte value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlByte Divide(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlByte other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlByte x, System.Data.SqlTypes.SqlByte y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -2741,7 +2617,6 @@ namespace System public static System.Data.SqlTypes.SqlByte operator ~(System.Data.SqlTypes.SqlByte x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlBytes` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlBytes : System.Data.SqlTypes.INullable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable { public System.Byte[] Buffer { get => throw null; } @@ -2771,7 +2646,6 @@ namespace System public static explicit operator System.Data.SqlTypes.SqlBinary(System.Data.SqlTypes.SqlBytes value) => throw null; } - // Generated from `System.Data.SqlTypes.SqlChars` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlChars : System.Data.SqlTypes.INullable, System.Runtime.Serialization.ISerializable, System.Xml.Serialization.IXmlSerializable { public System.Char[] Buffer { get => throw null; } @@ -2799,7 +2673,6 @@ namespace System public static explicit operator System.Data.SqlTypes.SqlChars(System.Data.SqlTypes.SqlString value) => throw null; } - // Generated from `System.Data.SqlTypes.SqlCompareOptions` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SqlCompareOptions : int { @@ -2812,8 +2685,7 @@ namespace System None = 0, } - // Generated from `System.Data.SqlTypes.SqlDateTime` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlDateTime : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlDateTime x, System.Data.SqlTypes.SqlDateTime y) => throw null; public static System.Data.SqlTypes.SqlDateTime operator +(System.Data.SqlTypes.SqlDateTime x, System.TimeSpan t) => throw null; @@ -2827,6 +2699,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlDateTime value) => throw null; public int CompareTo(object value) => throw null; public int DayTicks { get => throw null; } + public bool Equals(System.Data.SqlTypes.SqlDateTime other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDateTime x, System.Data.SqlTypes.SqlDateTime y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -2864,8 +2737,7 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlDateTime(System.DateTime value) => throw null; } - // Generated from `System.Data.SqlTypes.SqlDecimal` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlDecimal : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) => throw null; public static System.Data.SqlTypes.SqlDecimal operator *(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) => throw null; @@ -2888,6 +2760,7 @@ namespace System public static System.Data.SqlTypes.SqlDecimal ConvertToPrecScale(System.Data.SqlTypes.SqlDecimal n, int precision, int scale) => throw null; public int[] Data { get => throw null; } public static System.Data.SqlTypes.SqlDecimal Divide(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlDecimal other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDecimal x, System.Data.SqlTypes.SqlDecimal y) => throw null; public override bool Equals(object value) => throw null; public static System.Data.SqlTypes.SqlDecimal Floor(System.Data.SqlTypes.SqlDecimal n) => throw null; @@ -2935,6 +2808,7 @@ namespace System public override string ToString() => throw null; public static System.Data.SqlTypes.SqlDecimal Truncate(System.Data.SqlTypes.SqlDecimal n, int position) => throw null; public System.Decimal Value { get => throw null; } + public int WriteTdsValue(System.Span destination) => throw null; void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) => throw null; public static explicit operator System.Data.SqlTypes.SqlDecimal(System.Data.SqlTypes.SqlBoolean x) => throw null; public static explicit operator System.Decimal(System.Data.SqlTypes.SqlDecimal x) => throw null; @@ -2951,8 +2825,7 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlDecimal(System.Int64 x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlDouble` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlDouble : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) => throw null; public static System.Data.SqlTypes.SqlDouble operator *(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) => throw null; @@ -2969,6 +2842,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlDouble value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlDouble Divide(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlDouble other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlDouble x, System.Data.SqlTypes.SqlDouble y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3015,8 +2889,7 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlDouble(double x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlGuid` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlGuid : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) => throw null; public static System.Data.SqlTypes.SqlBoolean operator <(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) => throw null; @@ -3026,6 +2899,7 @@ namespace System public static System.Data.SqlTypes.SqlBoolean operator >=(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) => throw null; public int CompareTo(System.Data.SqlTypes.SqlGuid value) => throw null; public int CompareTo(object value) => throw null; + public bool Equals(System.Data.SqlTypes.SqlGuid other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlGuid x, System.Data.SqlTypes.SqlGuid y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3057,8 +2931,7 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlGuid(System.Guid x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlInt16` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlInt16 : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) => throw null; public static System.Data.SqlTypes.SqlInt16 operator %(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) => throw null; @@ -3079,6 +2952,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlInt16 value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlInt16 Divide(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlInt16 other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt16 x, System.Data.SqlTypes.SqlInt16 y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3132,8 +3006,7 @@ namespace System public static System.Data.SqlTypes.SqlInt16 operator ~(System.Data.SqlTypes.SqlInt16 x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlInt32` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlInt32 : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) => throw null; public static System.Data.SqlTypes.SqlInt32 operator %(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) => throw null; @@ -3154,6 +3027,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlInt32 value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlInt32 Divide(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlInt32 other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt32 x, System.Data.SqlTypes.SqlInt32 y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3207,8 +3081,7 @@ namespace System public static System.Data.SqlTypes.SqlInt32 operator ~(System.Data.SqlTypes.SqlInt32 x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlInt64` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlInt64 : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) => throw null; public static System.Data.SqlTypes.SqlInt64 operator %(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) => throw null; @@ -3229,6 +3102,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlInt64 value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlInt64 Divide(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlInt64 other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlInt64 x, System.Data.SqlTypes.SqlInt64 y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3282,8 +3156,7 @@ namespace System public static System.Data.SqlTypes.SqlInt64 operator ~(System.Data.SqlTypes.SqlInt64 x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlMoney` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlMoney : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; public static System.Data.SqlTypes.SqlMoney operator *(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; @@ -3300,10 +3173,13 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlMoney value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlMoney Divide(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlMoney other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; public override bool Equals(object value) => throw null; + public static System.Data.SqlTypes.SqlMoney FromTdsValue(System.Int64 value) => throw null; public override int GetHashCode() => throw null; System.Xml.Schema.XmlSchema System.Xml.Serialization.IXmlSerializable.GetSchema() => throw null; + public System.Int64 GetTdsValue() => throw null; public static System.Xml.XmlQualifiedName GetXsdType(System.Xml.Schema.XmlSchemaSet schemaSet) => throw null; public static System.Data.SqlTypes.SqlBoolean GreaterThan(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; public static System.Data.SqlTypes.SqlBoolean GreaterThanOrEqual(System.Data.SqlTypes.SqlMoney x, System.Data.SqlTypes.SqlMoney y) => throw null; @@ -3355,7 +3231,6 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlMoney(System.Int64 x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlNotFilledException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlNotFilledException : System.Data.SqlTypes.SqlTypeException { public SqlNotFilledException() => throw null; @@ -3363,7 +3238,6 @@ namespace System public SqlNotFilledException(string message, System.Exception e) => throw null; } - // Generated from `System.Data.SqlTypes.SqlNullValueException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlNullValueException : System.Data.SqlTypes.SqlTypeException { public SqlNullValueException() => throw null; @@ -3371,8 +3245,7 @@ namespace System public SqlNullValueException(string message, System.Exception e) => throw null; } - // Generated from `System.Data.SqlTypes.SqlSingle` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlSingle : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) => throw null; public static System.Data.SqlTypes.SqlSingle operator *(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) => throw null; @@ -3389,6 +3262,7 @@ namespace System public int CompareTo(System.Data.SqlTypes.SqlSingle value) => throw null; public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlSingle Divide(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) => throw null; + public bool Equals(System.Data.SqlTypes.SqlSingle other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlSingle x, System.Data.SqlTypes.SqlSingle y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3436,8 +3310,7 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlSingle(float x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlString` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.Xml.Serialization.IXmlSerializable + public struct SqlString : System.Data.SqlTypes.INullable, System.IComparable, System.IEquatable, System.Xml.Serialization.IXmlSerializable { public static System.Data.SqlTypes.SqlBoolean operator !=(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) => throw null; public static System.Data.SqlTypes.SqlString operator +(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) => throw null; @@ -3456,6 +3329,7 @@ namespace System public int CompareTo(object value) => throw null; public static System.Data.SqlTypes.SqlString Concat(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) => throw null; public System.Globalization.CultureInfo CultureInfo { get => throw null; } + public bool Equals(System.Data.SqlTypes.SqlString other) => throw null; public static System.Data.SqlTypes.SqlBoolean Equals(System.Data.SqlTypes.SqlString x, System.Data.SqlTypes.SqlString y) => throw null; public override bool Equals(object value) => throw null; public override int GetHashCode() => throw null; @@ -3514,7 +3388,6 @@ namespace System public static implicit operator System.Data.SqlTypes.SqlString(string x) => throw null; } - // Generated from `System.Data.SqlTypes.SqlTruncateException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlTruncateException : System.Data.SqlTypes.SqlTypeException { public SqlTruncateException() => throw null; @@ -3522,7 +3395,6 @@ namespace System public SqlTruncateException(string message, System.Exception e) => throw null; } - // Generated from `System.Data.SqlTypes.SqlTypeException` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlTypeException : System.SystemException { public SqlTypeException() => throw null; @@ -3531,7 +3403,6 @@ namespace System public SqlTypeException(string message, System.Exception e) => throw null; } - // Generated from `System.Data.SqlTypes.SqlXml` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SqlXml : System.Data.SqlTypes.INullable, System.Xml.Serialization.IXmlSerializable { public System.Xml.XmlReader CreateReader() => throw null; @@ -3547,7 +3418,6 @@ namespace System void System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) => throw null; } - // Generated from `System.Data.SqlTypes.StorageState` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum StorageState : int { Buffer = 0, @@ -3559,7 +3429,6 @@ namespace System } namespace Xml { - // Generated from `System.Xml.XmlDataDocument` in `System.Data.Common, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDataDocument : System.Xml.XmlDocument { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Contracts.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Contracts.cs index 183c669d9ba..5b371b2efa4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Contracts.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Contracts.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.Contracts, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Contracts { - // Generated from `System.Diagnostics.Contracts.Contract` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Contract { public static void Assert(bool condition) => throw null; @@ -34,33 +34,28 @@ namespace System public static T ValueAtReturn(out T value) => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractAbbreviatorAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractAbbreviatorAttribute : System.Attribute { public ContractAbbreviatorAttribute() => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractArgumentValidatorAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractArgumentValidatorAttribute : System.Attribute { public ContractArgumentValidatorAttribute() => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractClassAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractClassAttribute : System.Attribute { public ContractClassAttribute(System.Type typeContainingContracts) => throw null; public System.Type TypeContainingContracts { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.ContractClassForAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractClassForAttribute : System.Attribute { public ContractClassForAttribute(System.Type typeContractsAreFor) => throw null; public System.Type TypeContractsAreFor { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.ContractFailedEventArgs` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractFailedEventArgs : System.EventArgs { public string Condition { get => throw null; } @@ -74,7 +69,6 @@ namespace System public bool Unwind { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.ContractFailureKind` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ContractFailureKind : int { Assert = 4, @@ -85,13 +79,11 @@ namespace System Precondition = 0, } - // Generated from `System.Diagnostics.Contracts.ContractInvariantMethodAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractInvariantMethodAttribute : System.Attribute { public ContractInvariantMethodAttribute() => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractOptionAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractOptionAttribute : System.Attribute { public string Category { get => throw null; } @@ -102,33 +94,28 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.ContractPublicPropertyNameAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractPublicPropertyNameAttribute : System.Attribute { public ContractPublicPropertyNameAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.ContractReferenceAssemblyAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractReferenceAssemblyAttribute : System.Attribute { public ContractReferenceAssemblyAttribute() => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractRuntimeIgnoredAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractRuntimeIgnoredAttribute : System.Attribute { public ContractRuntimeIgnoredAttribute() => throw null; } - // Generated from `System.Diagnostics.Contracts.ContractVerificationAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractVerificationAttribute : System.Attribute { public ContractVerificationAttribute(bool value) => throw null; public bool Value { get => throw null; } } - // Generated from `System.Diagnostics.Contracts.PureAttribute` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PureAttribute : System.Attribute { public PureAttribute() => throw null; @@ -140,7 +127,6 @@ namespace System { namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.ContractHelper` in `System.Diagnostics.Contracts, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ContractHelper { public static string RaiseContractFailedEvent(System.Diagnostics.Contracts.ContractFailureKind failureKind, string userMessage, string conditionText, System.Exception innerException) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.DiagnosticSource.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.DiagnosticSource.cs index b63e2e1e27d..133fca1016d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.DiagnosticSource.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.DiagnosticSource.cs @@ -1,12 +1,21 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.DiagnosticSource, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.Activity` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Activity : System.IDisposable { + public struct Enumerator + { + public T Current { get => throw null; } + // Stub generator skipped constructor + public System.Diagnostics.Activity.Enumerator GetEnumerator() => throw null; + public bool MoveNext() => throw null; + } + + public Activity(string operationName) => throw null; public System.Diagnostics.ActivityTraceFlags ActivityTraceFlags { get => throw null; set => throw null; } public System.Diagnostics.Activity AddBaggage(string key, string value) => throw null; @@ -16,19 +25,25 @@ namespace System public System.Collections.Generic.IEnumerable> Baggage { get => throw null; } public System.Diagnostics.ActivityContext Context { get => throw null; } public static System.Diagnostics.Activity Current { get => throw null; set => throw null; } + public static event System.EventHandler CurrentChanged; public static System.Diagnostics.ActivityIdFormat DefaultIdFormat { get => throw null; set => throw null; } public string DisplayName { get => throw null; set => throw null; } public void Dispose() => throw null; protected virtual void Dispose(bool disposing) => throw null; public System.TimeSpan Duration { get => throw null; } + public System.Diagnostics.Activity.Enumerator EnumerateEvents() => throw null; + public System.Diagnostics.Activity.Enumerator EnumerateLinks() => throw null; + public System.Diagnostics.Activity.Enumerator> EnumerateTagObjects() => throw null; public System.Collections.Generic.IEnumerable Events { get => throw null; } public static bool ForceDefaultIdFormat { get => throw null; set => throw null; } public string GetBaggageItem(string key) => throw null; public object GetCustomProperty(string propertyName) => throw null; public object GetTagItem(string key) => throw null; + public bool HasRemoteParent { get => throw null; } public string Id { get => throw null; } public System.Diagnostics.ActivityIdFormat IdFormat { get => throw null; } public bool IsAllDataRequested { get => throw null; set => throw null; } + public bool IsStopped { get => throw null; } public System.Diagnostics.ActivityKind Kind { get => throw null; } public System.Collections.Generic.IEnumerable Links { get => throw null; } public string OperationName { get => throw null; } @@ -60,7 +75,13 @@ namespace System public string TraceStateString { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.ActivityContext` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public struct ActivityChangedEventArgs + { + // Stub generator skipped constructor + public System.Diagnostics.Activity Current { get => throw null; set => throw null; } + public System.Diagnostics.Activity Previous { get => throw null; set => throw null; } + } + public struct ActivityContext : System.IEquatable { public static bool operator !=(System.Diagnostics.ActivityContext left, System.Diagnostics.ActivityContext right) => throw null; @@ -76,10 +97,10 @@ namespace System public System.Diagnostics.ActivityTraceFlags TraceFlags { get => throw null; } public System.Diagnostics.ActivityTraceId TraceId { get => throw null; } public string TraceState { get => throw null; } + public static bool TryParse(string traceParent, string traceState, bool isRemote, out System.Diagnostics.ActivityContext context) => throw null; public static bool TryParse(string traceParent, string traceState, out System.Diagnostics.ActivityContext context) => throw null; } - // Generated from `System.Diagnostics.ActivityCreationOptions<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ActivityCreationOptions { // Stub generator skipped constructor @@ -91,20 +112,20 @@ namespace System public System.Diagnostics.ActivitySource Source { get => throw null; } public System.Collections.Generic.IEnumerable> Tags { get => throw null; } public System.Diagnostics.ActivityTraceId TraceId { get => throw null; } + public string TraceState { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.ActivityEvent` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ActivityEvent { // Stub generator skipped constructor public ActivityEvent(string name) => throw null; public ActivityEvent(string name, System.DateTimeOffset timestamp = default(System.DateTimeOffset), System.Diagnostics.ActivityTagsCollection tags = default(System.Diagnostics.ActivityTagsCollection)) => throw null; + public System.Diagnostics.Activity.Enumerator> EnumerateTagObjects() => throw null; public string Name { get => throw null; } public System.Collections.Generic.IEnumerable> Tags { get => throw null; } public System.DateTimeOffset Timestamp { get => throw null; } } - // Generated from `System.Diagnostics.ActivityIdFormat` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum ActivityIdFormat : int { Hierarchical = 1, @@ -112,7 +133,6 @@ namespace System W3C = 2, } - // Generated from `System.Diagnostics.ActivityKind` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum ActivityKind : int { Client = 2, @@ -122,7 +142,6 @@ namespace System Server = 1, } - // Generated from `System.Diagnostics.ActivityLink` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ActivityLink : System.IEquatable { public static bool operator !=(System.Diagnostics.ActivityLink left, System.Diagnostics.ActivityLink right) => throw null; @@ -130,13 +149,13 @@ namespace System // Stub generator skipped constructor public ActivityLink(System.Diagnostics.ActivityContext context, System.Diagnostics.ActivityTagsCollection tags = default(System.Diagnostics.ActivityTagsCollection)) => throw null; public System.Diagnostics.ActivityContext Context { get => throw null; } + public System.Diagnostics.Activity.Enumerator> EnumerateTagObjects() => throw null; public bool Equals(System.Diagnostics.ActivityLink value) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; public System.Collections.Generic.IEnumerable> Tags { get => throw null; } } - // Generated from `System.Diagnostics.ActivityListener` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ActivityListener : System.IDisposable { public ActivityListener() => throw null; @@ -148,7 +167,6 @@ namespace System public System.Func ShouldListenTo { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.ActivitySamplingResult` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum ActivitySamplingResult : int { AllData = 2, @@ -157,7 +175,6 @@ namespace System PropagationData = 1, } - // Generated from `System.Diagnostics.ActivitySource` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ActivitySource : System.IDisposable { public ActivitySource(string name, string version = default(string)) => throw null; @@ -175,7 +192,6 @@ namespace System public string Version { get => throw null; } } - // Generated from `System.Diagnostics.ActivitySpanId` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ActivitySpanId : System.IEquatable { public static bool operator !=(System.Diagnostics.ActivitySpanId spanId1, System.Diagnostics.ActivitySpanId spandId2) => throw null; @@ -193,7 +209,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.ActivityStatusCode` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum ActivityStatusCode : int { Error = 2, @@ -201,10 +216,8 @@ namespace System Unset = 0, } - // Generated from `System.Diagnostics.ActivityTagsCollection` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ActivityTagsCollection : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { - // Generated from `System.Diagnostics.ActivityTagsCollection+Enumerator` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -237,7 +250,6 @@ namespace System public System.Collections.Generic.ICollection Values { get => throw null; } } - // Generated from `System.Diagnostics.ActivityTraceFlags` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum ActivityTraceFlags : int { @@ -245,7 +257,6 @@ namespace System Recorded = 1, } - // Generated from `System.Diagnostics.ActivityTraceId` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ActivityTraceId : System.IEquatable { public static bool operator !=(System.Diagnostics.ActivityTraceId traceId1, System.Diagnostics.ActivityTraceId traceId2) => throw null; @@ -263,7 +274,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.DiagnosticListener` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DiagnosticListener : System.Diagnostics.DiagnosticSource, System.IDisposable, System.IObservable> { public static System.IObservable AllListeners { get => throw null; } @@ -283,7 +293,6 @@ namespace System public override void Write(string name, object value) => throw null; } - // Generated from `System.Diagnostics.DiagnosticSource` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class DiagnosticSource { protected DiagnosticSource() => throw null; @@ -296,14 +305,11 @@ namespace System public abstract void Write(string name, object value); } - // Generated from `System.Diagnostics.DistributedContextPropagator` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class DistributedContextPropagator { - // Generated from `System.Diagnostics.DistributedContextPropagator+PropagatorGetterCallback` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void PropagatorGetterCallback(object carrier, string fieldName, out string fieldValue, out System.Collections.Generic.IEnumerable fieldValues); - // Generated from `System.Diagnostics.DistributedContextPropagator+PropagatorSetterCallback` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void PropagatorSetterCallback(object carrier, string fieldName, string fieldValue); @@ -318,13 +324,10 @@ namespace System public abstract void Inject(System.Diagnostics.Activity activity, object carrier, System.Diagnostics.DistributedContextPropagator.PropagatorSetterCallback setter); } - // Generated from `System.Diagnostics.SampleActivity<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate System.Diagnostics.ActivitySamplingResult SampleActivity(ref System.Diagnostics.ActivityCreationOptions options); - // Generated from `System.Diagnostics.TagList` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct TagList : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IList>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyList>, System.Collections.IEnumerable { - // Generated from `System.Diagnostics.TagList+Enumerator` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -357,7 +360,6 @@ namespace System namespace Metrics { - // Generated from `System.Diagnostics.Metrics.Counter<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Counter : System.Diagnostics.Metrics.Instrument where T : struct { public void Add(T delta) => throw null; @@ -370,7 +372,6 @@ namespace System internal Counter(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; } - // Generated from `System.Diagnostics.Metrics.Histogram<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Histogram : System.Diagnostics.Metrics.Instrument where T : struct { internal Histogram(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; @@ -383,7 +384,6 @@ namespace System public void Record(T value, params System.Collections.Generic.KeyValuePair[] tags) => throw null; } - // Generated from `System.Diagnostics.Metrics.Instrument` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Instrument { public string Description { get => throw null; } @@ -396,7 +396,6 @@ namespace System public string Unit { get => throw null; } } - // Generated from `System.Diagnostics.Metrics.Instrument<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Instrument : System.Diagnostics.Metrics.Instrument where T : struct { protected Instrument(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; @@ -408,7 +407,6 @@ namespace System protected void RecordMeasurement(T measurement, System.Diagnostics.TagList tagList) => throw null; } - // Generated from `System.Diagnostics.Metrics.Measurement<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Measurement where T : struct { // Stub generator skipped constructor @@ -420,10 +418,8 @@ namespace System public T Value { get => throw null; } } - // Generated from `System.Diagnostics.Metrics.MeasurementCallback<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void MeasurementCallback(System.Diagnostics.Metrics.Instrument instrument, T measurement, System.ReadOnlySpan> tags, object state); - // Generated from `System.Diagnostics.Metrics.Meter` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Meter : System.IDisposable { public System.Diagnostics.Metrics.Counter CreateCounter(string name, string unit = default(string), string description = default(string)) where T : struct => throw null; @@ -434,6 +430,10 @@ namespace System public System.Diagnostics.Metrics.ObservableGauge CreateObservableGauge(string name, System.Func>> observeValues, string unit = default(string), string description = default(string)) where T : struct => throw null; public System.Diagnostics.Metrics.ObservableGauge CreateObservableGauge(string name, System.Func> observeValue, string unit = default(string), string description = default(string)) where T : struct => throw null; public System.Diagnostics.Metrics.ObservableGauge CreateObservableGauge(string name, System.Func observeValue, string unit = default(string), string description = default(string)) where T : struct => throw null; + public System.Diagnostics.Metrics.ObservableUpDownCounter CreateObservableUpDownCounter(string name, System.Func>> observeValues, string unit = default(string), string description = default(string)) where T : struct => throw null; + public System.Diagnostics.Metrics.ObservableUpDownCounter CreateObservableUpDownCounter(string name, System.Func> observeValue, string unit = default(string), string description = default(string)) where T : struct => throw null; + public System.Diagnostics.Metrics.ObservableUpDownCounter CreateObservableUpDownCounter(string name, System.Func observeValue, string unit = default(string), string description = default(string)) where T : struct => throw null; + public System.Diagnostics.Metrics.UpDownCounter CreateUpDownCounter(string name, string unit = default(string), string description = default(string)) where T : struct => throw null; public void Dispose() => throw null; public Meter(string name) => throw null; public Meter(string name, string version) => throw null; @@ -441,7 +441,6 @@ namespace System public string Version { get => throw null; } } - // Generated from `System.Diagnostics.Metrics.MeterListener` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class MeterListener : System.IDisposable { public object DisableMeasurementEvents(System.Diagnostics.Metrics.Instrument instrument) => throw null; @@ -455,21 +454,18 @@ namespace System public void Start() => throw null; } - // Generated from `System.Diagnostics.Metrics.ObservableCounter<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ObservableCounter : System.Diagnostics.Metrics.ObservableInstrument where T : struct { internal ObservableCounter(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; protected override System.Collections.Generic.IEnumerable> Observe() => throw null; } - // Generated from `System.Diagnostics.Metrics.ObservableGauge<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ObservableGauge : System.Diagnostics.Metrics.ObservableInstrument where T : struct { internal ObservableGauge(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; protected override System.Collections.Generic.IEnumerable> Observe() => throw null; } - // Generated from `System.Diagnostics.Metrics.ObservableInstrument<>` in `System.Diagnostics.DiagnosticSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ObservableInstrument : System.Diagnostics.Metrics.Instrument where T : struct { public override bool IsObservable { get => throw null; } @@ -477,6 +473,24 @@ namespace System protected abstract System.Collections.Generic.IEnumerable> Observe(); } + public class ObservableUpDownCounter : System.Diagnostics.Metrics.ObservableInstrument where T : struct + { + internal ObservableUpDownCounter(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; + protected override System.Collections.Generic.IEnumerable> Observe() => throw null; + } + + public class UpDownCounter : System.Diagnostics.Metrics.Instrument where T : struct + { + public void Add(T delta) => throw null; + public void Add(T delta, System.Collections.Generic.KeyValuePair tag) => throw null; + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2) => throw null; + public void Add(T delta, System.Collections.Generic.KeyValuePair tag1, System.Collections.Generic.KeyValuePair tag2, System.Collections.Generic.KeyValuePair tag3) => throw null; + public void Add(T delta, System.ReadOnlySpan> tags) => throw null; + public void Add(T delta, System.Diagnostics.TagList tagList) => throw null; + public void Add(T delta, params System.Collections.Generic.KeyValuePair[] tags) => throw null; + internal UpDownCounter(System.Diagnostics.Metrics.Meter meter, string name, string unit, string description) : base(default(System.Diagnostics.Metrics.Meter), default(string), default(string), default(string)) => throw null; + } + } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.FileVersionInfo.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.FileVersionInfo.cs index d0f799c5037..91af358083c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.FileVersionInfo.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.FileVersionInfo.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.FileVersionInfo, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.FileVersionInfo` in `System.Diagnostics.FileVersionInfo, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileVersionInfo { public string Comments { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Process.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Process.cs index 1160ea59cd7..542814f5e97 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Process.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Process.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.Process, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.SafeProcessHandle` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeProcessHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { protected override bool ReleaseHandle() => throw null; @@ -21,23 +21,19 @@ namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.DataReceivedEventArgs` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataReceivedEventArgs : System.EventArgs { public string Data { get => throw null; } } - // Generated from `System.Diagnostics.DataReceivedEventHandler` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void DataReceivedEventHandler(object sender, System.Diagnostics.DataReceivedEventArgs e); - // Generated from `System.Diagnostics.MonitoringDescriptionAttribute` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MonitoringDescriptionAttribute : System.ComponentModel.DescriptionAttribute { public override string Description { get => throw null; } public MonitoringDescriptionAttribute(string description) => throw null; } - // Generated from `System.Diagnostics.Process` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Process : System.ComponentModel.Component, System.IDisposable { public int BasePriority { get => throw null; } @@ -121,15 +117,16 @@ namespace System public int VirtualMemorySize { get => throw null; } public System.Int64 VirtualMemorySize64 { get => throw null; } public void WaitForExit() => throw null; + public bool WaitForExit(System.TimeSpan timeout) => throw null; public bool WaitForExit(int milliseconds) => throw null; public System.Threading.Tasks.Task WaitForExitAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool WaitForInputIdle() => throw null; + public bool WaitForInputIdle(System.TimeSpan timeout) => throw null; public bool WaitForInputIdle(int milliseconds) => throw null; public int WorkingSet { get => throw null; } public System.Int64 WorkingSet64 { get => throw null; } } - // Generated from `System.Diagnostics.ProcessModule` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProcessModule : System.ComponentModel.Component { public System.IntPtr BaseAddress { get => throw null; } @@ -141,7 +138,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.ProcessModuleCollection` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProcessModuleCollection : System.Collections.ReadOnlyCollectionBase { public bool Contains(System.Diagnostics.ProcessModule module) => throw null; @@ -152,7 +148,6 @@ namespace System public ProcessModuleCollection(System.Diagnostics.ProcessModule[] processModules) => throw null; } - // Generated from `System.Diagnostics.ProcessPriorityClass` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProcessPriorityClass : int { AboveNormal = 32768, @@ -163,7 +158,6 @@ namespace System RealTime = 256, } - // Generated from `System.Diagnostics.ProcessStartInfo` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProcessStartInfo { public System.Collections.ObjectModel.Collection ArgumentList { get => throw null; } @@ -195,7 +189,6 @@ namespace System public string WorkingDirectory { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.ProcessThread` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProcessThread : System.ComponentModel.Component { public int BasePriority { get => throw null; } @@ -215,7 +208,6 @@ namespace System public System.Diagnostics.ThreadWaitReason WaitReason { get => throw null; } } - // Generated from `System.Diagnostics.ProcessThreadCollection` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProcessThreadCollection : System.Collections.ReadOnlyCollectionBase { public int Add(System.Diagnostics.ProcessThread thread) => throw null; @@ -229,7 +221,6 @@ namespace System public void Remove(System.Diagnostics.ProcessThread thread) => throw null; } - // Generated from `System.Diagnostics.ProcessWindowStyle` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProcessWindowStyle : int { Hidden = 1, @@ -238,7 +229,6 @@ namespace System Normal = 0, } - // Generated from `System.Diagnostics.ThreadPriorityLevel` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ThreadPriorityLevel : int { AboveNormal = 1, @@ -250,7 +240,6 @@ namespace System TimeCritical = 15, } - // Generated from `System.Diagnostics.ThreadState` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ThreadState : int { Initialized = 0, @@ -263,7 +252,6 @@ namespace System Wait = 5, } - // Generated from `System.Diagnostics.ThreadWaitReason` in `System.Diagnostics.Process, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ThreadWaitReason : int { EventPairHigh = 7, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.StackTrace.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.StackTrace.cs index 53bbc36673e..6853f30d77e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.StackTrace.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.StackTrace.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.StackTrace, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.StackFrame` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StackFrame { public virtual int GetFileColumnNumber() => throw null; @@ -23,7 +23,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.StackFrameExtensions` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class StackFrameExtensions { public static System.IntPtr GetNativeIP(this System.Diagnostics.StackFrame stackFrame) => throw null; @@ -34,7 +33,6 @@ namespace System public static bool HasSource(this System.Diagnostics.StackFrame stackFrame) => throw null; } - // Generated from `System.Diagnostics.StackTrace` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StackTrace { public virtual int FrameCount { get => throw null; } @@ -55,19 +53,16 @@ namespace System namespace SymbolStore { - // Generated from `System.Diagnostics.SymbolStore.ISymbolBinder` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolBinder { System.Diagnostics.SymbolStore.ISymbolReader GetReader(int importer, string filename, string searchPath); } - // Generated from `System.Diagnostics.SymbolStore.ISymbolBinder1` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolBinder1 { System.Diagnostics.SymbolStore.ISymbolReader GetReader(System.IntPtr importer, string filename, string searchPath); } - // Generated from `System.Diagnostics.SymbolStore.ISymbolDocument` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolDocument { System.Guid CheckSumAlgorithmId { get; } @@ -82,14 +77,12 @@ namespace System string URL { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolDocumentWriter` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolDocumentWriter { void SetCheckSum(System.Guid algorithmId, System.Byte[] checkSum); void SetSource(System.Byte[] source); } - // Generated from `System.Diagnostics.SymbolStore.ISymbolMethod` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolMethod { System.Diagnostics.SymbolStore.ISymbolNamespace GetNamespace(); @@ -104,7 +97,6 @@ namespace System System.Diagnostics.SymbolStore.SymbolToken Token { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolNamespace` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolNamespace { System.Diagnostics.SymbolStore.ISymbolNamespace[] GetNamespaces(); @@ -112,7 +104,6 @@ namespace System string Name { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolReader` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolReader { System.Diagnostics.SymbolStore.ISymbolDocument GetDocument(string url, System.Guid language, System.Guid languageVendor, System.Guid documentType); @@ -127,7 +118,6 @@ namespace System System.Diagnostics.SymbolStore.SymbolToken UserEntryPoint { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolScope` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolScope { int EndOffset { get; } @@ -139,7 +129,6 @@ namespace System int StartOffset { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolVariable` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolVariable { int AddressField1 { get; } @@ -153,7 +142,6 @@ namespace System int StartOffset { get; } } - // Generated from `System.Diagnostics.SymbolStore.ISymbolWriter` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISymbolWriter { void Close(); @@ -178,7 +166,6 @@ namespace System void UsingNamespace(string fullName); } - // Generated from `System.Diagnostics.SymbolStore.SymAddressKind` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SymAddressKind : int { BitField = 9, @@ -193,14 +180,12 @@ namespace System NativeStackRegister = 8, } - // Generated from `System.Diagnostics.SymbolStore.SymDocumentType` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SymDocumentType { public SymDocumentType() => throw null; public static System.Guid Text; } - // Generated from `System.Diagnostics.SymbolStore.SymLanguageType` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SymLanguageType { public static System.Guid Basic; @@ -217,15 +202,13 @@ namespace System public SymLanguageType() => throw null; } - // Generated from `System.Diagnostics.SymbolStore.SymLanguageVendor` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SymLanguageVendor { public static System.Guid Microsoft; public SymLanguageVendor() => throw null; } - // Generated from `System.Diagnostics.SymbolStore.SymbolToken` in `System.Diagnostics.StackTrace, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SymbolToken + public struct SymbolToken : System.IEquatable { public static bool operator !=(System.Diagnostics.SymbolStore.SymbolToken a, System.Diagnostics.SymbolStore.SymbolToken b) => throw null; public static bool operator ==(System.Diagnostics.SymbolStore.SymbolToken a, System.Diagnostics.SymbolStore.SymbolToken b) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TextWriterTraceListener.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TextWriterTraceListener.cs index a4761361190..652fd5bdb37 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TextWriterTraceListener.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TextWriterTraceListener.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.TextWriterTraceListener, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.ConsoleTraceListener` in `System.Diagnostics.TextWriterTraceListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConsoleTraceListener : System.Diagnostics.TextWriterTraceListener { public override void Close() => throw null; @@ -12,7 +12,6 @@ namespace System public ConsoleTraceListener(bool useErrorStream) => throw null; } - // Generated from `System.Diagnostics.DelimitedListTraceListener` in `System.Diagnostics.TextWriterTraceListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DelimitedListTraceListener : System.Diagnostics.TextWriterTraceListener { public DelimitedListTraceListener(System.IO.Stream stream) => throw null; @@ -29,7 +28,6 @@ namespace System public override void TraceEvent(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, string format, params object[] args) => throw null; } - // Generated from `System.Diagnostics.TextWriterTraceListener` in `System.Diagnostics.TextWriterTraceListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TextWriterTraceListener : System.Diagnostics.TraceListener { public override void Close() => throw null; @@ -47,7 +45,6 @@ namespace System public System.IO.TextWriter Writer { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.XmlWriterTraceListener` in `System.Diagnostics.TextWriterTraceListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlWriterTraceListener : System.Diagnostics.TextWriterTraceListener { public override void Close() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TraceSource.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TraceSource.cs index 81ef7fd8e9d..29ef410e43e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TraceSource.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.TraceSource.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.TraceSource, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Diagnostics { - // Generated from `System.Diagnostics.BooleanSwitch` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BooleanSwitch : System.Diagnostics.Switch { public BooleanSwitch(string displayName, string description) : base(default(string), default(string)) => throw null; @@ -13,7 +13,6 @@ namespace System protected override void OnValueChanged() => throw null; } - // Generated from `System.Diagnostics.CorrelationManager` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CorrelationManager { public System.Guid ActivityId { get => throw null; set => throw null; } @@ -23,7 +22,6 @@ namespace System public void StopLogicalOperation() => throw null; } - // Generated from `System.Diagnostics.DefaultTraceListener` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultTraceListener : System.Diagnostics.TraceListener { public bool AssertUiEnabled { get => throw null; set => throw null; } @@ -35,7 +33,6 @@ namespace System public override void WriteLine(string message) => throw null; } - // Generated from `System.Diagnostics.EventTypeFilter` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventTypeFilter : System.Diagnostics.TraceFilter { public System.Diagnostics.SourceLevels EventType { get => throw null; set => throw null; } @@ -43,7 +40,19 @@ namespace System public override bool ShouldTrace(System.Diagnostics.TraceEventCache cache, string source, System.Diagnostics.TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data) => throw null; } - // Generated from `System.Diagnostics.SourceFilter` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class InitializingSwitchEventArgs : System.EventArgs + { + public InitializingSwitchEventArgs(System.Diagnostics.Switch @switch) => throw null; + public System.Diagnostics.Switch Switch { get => throw null; } + } + + public class InitializingTraceSourceEventArgs : System.EventArgs + { + public InitializingTraceSourceEventArgs(System.Diagnostics.TraceSource traceSource) => throw null; + public System.Diagnostics.TraceSource TraceSource { get => throw null; } + public bool WasInitialized { get => throw null; set => throw null; } + } + public class SourceFilter : System.Diagnostics.TraceFilter { public override bool ShouldTrace(System.Diagnostics.TraceEventCache cache, string source, System.Diagnostics.TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data) => throw null; @@ -51,7 +60,6 @@ namespace System public SourceFilter(string source) => throw null; } - // Generated from `System.Diagnostics.SourceLevels` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SourceLevels : int { @@ -65,7 +73,6 @@ namespace System Warning = 7, } - // Generated from `System.Diagnostics.SourceSwitch` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SourceSwitch : System.Diagnostics.Switch { public System.Diagnostics.SourceLevels Level { get => throw null; set => throw null; } @@ -75,22 +82,23 @@ namespace System public SourceSwitch(string displayName, string defaultSwitchValue) : base(default(string), default(string)) => throw null; } - // Generated from `System.Diagnostics.Switch` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Switch { public System.Collections.Specialized.StringDictionary Attributes { get => throw null; } + public string DefaultValue { get => throw null; } public string Description { get => throw null; } public string DisplayName { get => throw null; } protected virtual string[] GetSupportedAttributes() => throw null; + public static event System.EventHandler Initializing; protected virtual void OnSwitchSettingChanged() => throw null; protected virtual void OnValueChanged() => throw null; + public void Refresh() => throw null; protected Switch(string displayName, string description) => throw null; protected Switch(string displayName, string description, string defaultSwitchValue) => throw null; protected int SwitchSetting { get => throw null; set => throw null; } - protected string Value { get => throw null; set => throw null; } + public string Value { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.SwitchAttribute` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SwitchAttribute : System.Attribute { public static System.Diagnostics.SwitchAttribute[] GetAll(System.Reflection.Assembly assembly) => throw null; @@ -100,14 +108,12 @@ namespace System public System.Type SwitchType { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.SwitchLevelAttribute` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SwitchLevelAttribute : System.Attribute { public SwitchLevelAttribute(System.Type switchLevelType) => throw null; public System.Type SwitchLevelType { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Trace` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Trace { public static void Assert(bool condition) => throw null; @@ -124,6 +130,7 @@ namespace System public static int IndentSize { get => throw null; set => throw null; } public static System.Diagnostics.TraceListenerCollection Listeners { get => throw null; } public static void Refresh() => throw null; + public static event System.EventHandler Refreshing; public static void TraceError(string message) => throw null; public static void TraceError(string format, params object[] args) => throw null; public static void TraceInformation(string message) => throw null; @@ -150,7 +157,6 @@ namespace System public static void WriteLineIf(bool condition, string message, string category) => throw null; } - // Generated from `System.Diagnostics.TraceEventCache` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TraceEventCache { public string Callstack { get => throw null; } @@ -162,7 +168,6 @@ namespace System public TraceEventCache() => throw null; } - // Generated from `System.Diagnostics.TraceEventType` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TraceEventType : int { Critical = 1, @@ -177,14 +182,12 @@ namespace System Warning = 4, } - // Generated from `System.Diagnostics.TraceFilter` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TraceFilter { public abstract bool ShouldTrace(System.Diagnostics.TraceEventCache cache, string source, System.Diagnostics.TraceEventType eventType, int id, string formatOrMessage, object[] args, object data1, object[] data); protected TraceFilter() => throw null; } - // Generated from `System.Diagnostics.TraceLevel` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TraceLevel : int { Error = 1, @@ -194,7 +197,6 @@ namespace System Warning = 2, } - // Generated from `System.Diagnostics.TraceListener` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TraceListener : System.MarshalByRefObject, System.IDisposable { public System.Collections.Specialized.StringDictionary Attributes { get => throw null; } @@ -231,7 +233,6 @@ namespace System public virtual void WriteLine(string message, string category) => throw null; } - // Generated from `System.Diagnostics.TraceListenerCollection` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TraceListenerCollection : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public int Add(System.Diagnostics.TraceListener listener) => throw null; @@ -262,7 +263,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Diagnostics.TraceOptions` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TraceOptions : int { @@ -275,13 +275,14 @@ namespace System Timestamp = 4, } - // Generated from `System.Diagnostics.TraceSource` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TraceSource { public System.Collections.Specialized.StringDictionary Attributes { get => throw null; } public void Close() => throw null; + public System.Diagnostics.SourceLevels DefaultLevel { get => throw null; } public void Flush() => throw null; protected virtual string[] GetSupportedAttributes() => throw null; + public static event System.EventHandler Initializing; public System.Diagnostics.TraceListenerCollection Listeners { get => throw null; } public string Name { get => throw null; } public System.Diagnostics.SourceSwitch Switch { get => throw null; set => throw null; } @@ -297,7 +298,6 @@ namespace System public void TraceTransfer(int id, string message, System.Guid relatedActivityId) => throw null; } - // Generated from `System.Diagnostics.TraceSwitch` in `System.Diagnostics.TraceSource, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TraceSwitch : System.Diagnostics.Switch { public System.Diagnostics.TraceLevel Level { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Tracing.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Tracing.cs index 9d97c8e31cb..2089760e949 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Tracing.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Diagnostics.Tracing.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Diagnostics.Tracing, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Tracing { - // Generated from `System.Diagnostics.Tracing.DiagnosticCounter` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DiagnosticCounter : System.IDisposable { public void AddMetadata(string key, string value) => throw null; @@ -18,7 +18,6 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventActivityOptions` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventActivityOptions : int { @@ -28,7 +27,6 @@ namespace System Recursive = 4, } - // Generated from `System.Diagnostics.Tracing.EventAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventAttribute : System.Attribute { public System.Diagnostics.Tracing.EventActivityOptions ActivityOptions { get => throw null; set => throw null; } @@ -44,7 +42,6 @@ namespace System public System.Byte Version { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventChannel` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventChannel : byte { Admin = 16, @@ -54,7 +51,6 @@ namespace System Operational = 17, } - // Generated from `System.Diagnostics.Tracing.EventCommand` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventCommand : int { Disable = -3, @@ -63,7 +59,6 @@ namespace System Update = 0, } - // Generated from `System.Diagnostics.Tracing.EventCommandEventArgs` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventCommandEventArgs : System.EventArgs { public System.Collections.Generic.IDictionary Arguments { get => throw null; } @@ -72,7 +67,6 @@ namespace System public bool EnableEvent(int eventId) => throw null; } - // Generated from `System.Diagnostics.Tracing.EventCounter` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventCounter : System.Diagnostics.Tracing.DiagnosticCounter { public EventCounter(string name, System.Diagnostics.Tracing.EventSource eventSource) => throw null; @@ -81,14 +75,12 @@ namespace System public void WriteMetric(float value) => throw null; } - // Generated from `System.Diagnostics.Tracing.EventDataAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventDataAttribute : System.Attribute { public EventDataAttribute() => throw null; public string Name { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventFieldAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventFieldAttribute : System.Attribute { public EventFieldAttribute() => throw null; @@ -96,7 +88,6 @@ namespace System public System.Diagnostics.Tracing.EventFieldTags Tags { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventFieldFormat` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventFieldFormat : int { Boolean = 3, @@ -108,20 +99,17 @@ namespace System Xml = 11, } - // Generated from `System.Diagnostics.Tracing.EventFieldTags` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventFieldTags : int { None = 0, } - // Generated from `System.Diagnostics.Tracing.EventIgnoreAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventIgnoreAttribute : System.Attribute { public EventIgnoreAttribute() => throw null; } - // Generated from `System.Diagnostics.Tracing.EventKeywords` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventKeywords : long { @@ -137,7 +125,6 @@ namespace System WdiDiagnostic = 1125899906842624, } - // Generated from `System.Diagnostics.Tracing.EventLevel` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventLevel : int { Critical = 1, @@ -148,7 +135,6 @@ namespace System Warning = 3, } - // Generated from `System.Diagnostics.Tracing.EventListener` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EventListener : System.IDisposable { public void DisableEvents(System.Diagnostics.Tracing.EventSource eventSource) => throw null; @@ -164,7 +150,6 @@ namespace System protected internal virtual void OnEventWritten(System.Diagnostics.Tracing.EventWrittenEventArgs eventData) => throw null; } - // Generated from `System.Diagnostics.Tracing.EventManifestOptions` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventManifestOptions : int { @@ -175,7 +160,6 @@ namespace System Strict = 1, } - // Generated from `System.Diagnostics.Tracing.EventOpcode` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventOpcode : int { DataCollectionStart = 3, @@ -191,10 +175,8 @@ namespace System Suspend = 8, } - // Generated from `System.Diagnostics.Tracing.EventSource` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventSource : System.IDisposable { - // Generated from `System.Diagnostics.Tracing.EventSource+EventData` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected internal struct EventData { public System.IntPtr DataPointer { get => throw null; set => throw null; } @@ -262,7 +244,6 @@ namespace System // ERR: Stub generator didn't handle member: ~EventSource } - // Generated from `System.Diagnostics.Tracing.EventSourceAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventSourceAttribute : System.Attribute { public EventSourceAttribute() => throw null; @@ -271,14 +252,12 @@ namespace System public string Name { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventSourceCreatedEventArgs` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventSourceCreatedEventArgs : System.EventArgs { public System.Diagnostics.Tracing.EventSource EventSource { get => throw null; } public EventSourceCreatedEventArgs() => throw null; } - // Generated from `System.Diagnostics.Tracing.EventSourceException` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventSourceException : System.Exception { public EventSourceException() => throw null; @@ -287,7 +266,6 @@ namespace System public EventSourceException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Diagnostics.Tracing.EventSourceOptions` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EventSourceOptions { public System.Diagnostics.Tracing.EventActivityOptions ActivityOptions { get => throw null; set => throw null; } @@ -298,7 +276,6 @@ namespace System public System.Diagnostics.Tracing.EventTags Tags { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.Tracing.EventSourceSettings` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventSourceSettings : int { @@ -308,20 +285,17 @@ namespace System ThrowOnEventWriteErrors = 1, } - // Generated from `System.Diagnostics.Tracing.EventTags` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventTags : int { None = 0, } - // Generated from `System.Diagnostics.Tracing.EventTask` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventTask : int { None = 0, } - // Generated from `System.Diagnostics.Tracing.EventWrittenEventArgs` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventWrittenEventArgs : System.EventArgs { public System.Guid ActivityId { get => throw null; } @@ -343,7 +317,6 @@ namespace System public System.Byte Version { get => throw null; } } - // Generated from `System.Diagnostics.Tracing.IncrementingEventCounter` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IncrementingEventCounter : System.Diagnostics.Tracing.DiagnosticCounter { public System.TimeSpan DisplayRateTimeScale { get => throw null; set => throw null; } @@ -352,7 +325,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.Tracing.IncrementingPollingCounter` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IncrementingPollingCounter : System.Diagnostics.Tracing.DiagnosticCounter { public System.TimeSpan DisplayRateTimeScale { get => throw null; set => throw null; } @@ -360,13 +332,11 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Diagnostics.Tracing.NonEventAttribute` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NonEventAttribute : System.Attribute { public NonEventAttribute() => throw null; } - // Generated from `System.Diagnostics.Tracing.PollingCounter` in `System.Diagnostics.Tracing, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PollingCounter : System.Diagnostics.Tracing.DiagnosticCounter { public PollingCounter(string name, System.Diagnostics.Tracing.EventSource eventSource, System.Func metricProvider) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Drawing.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Drawing.Primitives.cs index 6fe715a2059..fcd96e8c416 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Drawing.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Drawing.Primitives.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Drawing.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Drawing { - // Generated from `System.Drawing.Color` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Color : System.IEquatable { public static bool operator !=(System.Drawing.Color left, System.Drawing.Color right) => throw null; @@ -179,7 +179,6 @@ namespace System public static System.Drawing.Color YellowGreen { get => throw null; } } - // Generated from `System.Drawing.ColorTranslator` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ColorTranslator { public static System.Drawing.Color FromHtml(string htmlColor) => throw null; @@ -190,7 +189,6 @@ namespace System public static int ToWin32(System.Drawing.Color c) => throw null; } - // Generated from `System.Drawing.KnownColor` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum KnownColor : int { ActiveBorder = 1, @@ -370,7 +368,6 @@ namespace System YellowGreen = 167, } - // Generated from `System.Drawing.Point` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Point : System.IEquatable { public static bool operator !=(System.Drawing.Point left, System.Drawing.Point right) => throw null; @@ -400,7 +397,6 @@ namespace System public static implicit operator System.Drawing.PointF(System.Drawing.Point p) => throw null; } - // Generated from `System.Drawing.PointF` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PointF : System.IEquatable { public static bool operator !=(System.Drawing.PointF left, System.Drawing.PointF right) => throw null; @@ -429,7 +425,6 @@ namespace System public static explicit operator System.Drawing.PointF(System.Numerics.Vector2 vector) => throw null; } - // Generated from `System.Drawing.Rectangle` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Rectangle : System.IEquatable { public static bool operator !=(System.Drawing.Rectangle left, System.Drawing.Rectangle right) => throw null; @@ -471,7 +466,6 @@ namespace System public int Y { get => throw null; set => throw null; } } - // Generated from `System.Drawing.RectangleF` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct RectangleF : System.IEquatable { public static bool operator !=(System.Drawing.RectangleF left, System.Drawing.RectangleF right) => throw null; @@ -515,7 +509,6 @@ namespace System public static implicit operator System.Drawing.RectangleF(System.Drawing.Rectangle r) => throw null; } - // Generated from `System.Drawing.Size` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Size : System.IEquatable { public static bool operator !=(System.Drawing.Size sz1, System.Drawing.Size sz2) => throw null; @@ -548,7 +541,6 @@ namespace System public static implicit operator System.Drawing.SizeF(System.Drawing.Size p) => throw null; } - // Generated from `System.Drawing.SizeF` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SizeF : System.IEquatable { public static bool operator !=(System.Drawing.SizeF sz1, System.Drawing.SizeF sz2) => throw null; @@ -581,7 +573,6 @@ namespace System public static explicit operator System.Drawing.SizeF(System.Numerics.Vector2 vector) => throw null; } - // Generated from `System.Drawing.SystemColors` in `System.Drawing.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SystemColors { public static System.Drawing.Color ActiveBorder { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Asn1.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Asn1.cs index 2c48ec46956..c4c8d6fce0b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Asn1.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Asn1.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Formats.Asn1, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Asn1 { - // Generated from `System.Formats.Asn1.Asn1Tag` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Asn1Tag : System.IEquatable { public static bool operator !=(System.Formats.Asn1.Asn1Tag left, System.Formats.Asn1.Asn1Tag right) => throw null; @@ -44,7 +44,6 @@ namespace System public static System.Formats.Asn1.Asn1Tag UtcTime; } - // Generated from `System.Formats.Asn1.AsnContentException` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AsnContentException : System.Exception { public AsnContentException() => throw null; @@ -53,7 +52,6 @@ namespace System public AsnContentException(string message, System.Exception inner) => throw null; } - // Generated from `System.Formats.Asn1.AsnDecoder` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class AsnDecoder { public static System.Byte[] ReadBitString(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out int unusedBitCount, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) => throw null; @@ -89,7 +87,6 @@ namespace System public static bool TryReadUInt64(System.ReadOnlySpan source, System.Formats.Asn1.AsnEncodingRules ruleSet, out System.UInt64 value, out int bytesConsumed, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) => throw null; } - // Generated from `System.Formats.Asn1.AsnEncodingRules` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum AsnEncodingRules : int { BER = 0, @@ -97,7 +94,6 @@ namespace System DER = 2, } - // Generated from `System.Formats.Asn1.AsnReader` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AsnReader { public AsnReader(System.ReadOnlyMemory data, System.Formats.Asn1.AsnEncodingRules ruleSet, System.Formats.Asn1.AsnReaderOptions options = default(System.Formats.Asn1.AsnReaderOptions)) => throw null; @@ -141,7 +137,6 @@ namespace System public bool TryReadUInt64(out System.UInt64 value, System.Formats.Asn1.Asn1Tag? expectedTag = default(System.Formats.Asn1.Asn1Tag?)) => throw null; } - // Generated from `System.Formats.Asn1.AsnReaderOptions` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct AsnReaderOptions { // Stub generator skipped constructor @@ -149,10 +144,8 @@ namespace System public int UtcTimeTwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Formats.Asn1.AsnWriter` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AsnWriter { - // Generated from `System.Formats.Asn1.AsnWriter+Scope` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Scope : System.IDisposable { public void Dispose() => throw null; @@ -161,6 +154,7 @@ namespace System public AsnWriter(System.Formats.Asn1.AsnEncodingRules ruleSet) => throw null; + public AsnWriter(System.Formats.Asn1.AsnEncodingRules ruleSet, int initialCapacity) => throw null; public void CopyTo(System.Formats.Asn1.AsnWriter destination) => throw null; public System.Byte[] Encode() => throw null; public int Encode(System.Span destination) => throw null; @@ -200,7 +194,6 @@ namespace System public void WriteUtcTime(System.DateTimeOffset value, int twoDigitYearMax, System.Formats.Asn1.Asn1Tag? tag = default(System.Formats.Asn1.Asn1Tag?)) => throw null; } - // Generated from `System.Formats.Asn1.TagClass` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum TagClass : int { Application = 64, @@ -209,7 +202,6 @@ namespace System Universal = 0, } - // Generated from `System.Formats.Asn1.UniversalTagNumber` in `System.Formats.Asn1, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum UniversalTagNumber : int { BMPString = 30, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Tar.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Tar.cs new file mode 100644 index 00000000000..76c2ed09ae4 --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Formats.Tar.cs @@ -0,0 +1,140 @@ +// This file contains auto-generated code. +// Generated from `System.Formats.Tar, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. + +namespace System +{ + namespace Formats + { + namespace Tar + { + public class GnuTarEntry : System.Formats.Tar.PosixTarEntry + { + public System.DateTimeOffset AccessTime { get => throw null; set => throw null; } + public System.DateTimeOffset ChangeTime { get => throw null; set => throw null; } + public GnuTarEntry(System.Formats.Tar.TarEntry other) => throw null; + public GnuTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) => throw null; + } + + public class PaxGlobalExtendedAttributesTarEntry : System.Formats.Tar.PosixTarEntry + { + public System.Collections.Generic.IReadOnlyDictionary GlobalExtendedAttributes { get => throw null; } + public PaxGlobalExtendedAttributesTarEntry(System.Collections.Generic.IEnumerable> globalExtendedAttributes) => throw null; + } + + public class PaxTarEntry : System.Formats.Tar.PosixTarEntry + { + public System.Collections.Generic.IReadOnlyDictionary ExtendedAttributes { get => throw null; } + public PaxTarEntry(System.Formats.Tar.TarEntry other) => throw null; + public PaxTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) => throw null; + public PaxTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName, System.Collections.Generic.IEnumerable> extendedAttributes) => throw null; + } + + public abstract class PosixTarEntry : System.Formats.Tar.TarEntry + { + public int DeviceMajor { get => throw null; set => throw null; } + public int DeviceMinor { get => throw null; set => throw null; } + public string GroupName { get => throw null; set => throw null; } + internal PosixTarEntry() => throw null; + public string UserName { get => throw null; set => throw null; } + } + + public abstract class TarEntry + { + public int Checksum { get => throw null; } + public System.IO.Stream DataStream { get => throw null; set => throw null; } + public System.Formats.Tar.TarEntryType EntryType { get => throw null; } + public void ExtractToFile(string destinationFileName, bool overwrite) => throw null; + public System.Threading.Tasks.Task ExtractToFileAsync(string destinationFileName, bool overwrite, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Formats.Tar.TarEntryFormat Format { get => throw null; } + public int Gid { get => throw null; set => throw null; } + public System.Int64 Length { get => throw null; } + public string LinkName { get => throw null; set => throw null; } + public System.IO.UnixFileMode Mode { get => throw null; set => throw null; } + public System.DateTimeOffset ModificationTime { get => throw null; set => throw null; } + public string Name { get => throw null; set => throw null; } + internal TarEntry() => throw null; + public override string ToString() => throw null; + public int Uid { get => throw null; set => throw null; } + } + + public enum TarEntryFormat : int + { + Gnu = 4, + Pax = 3, + Unknown = 0, + Ustar = 2, + V7 = 1, + } + + public enum TarEntryType : byte + { + BlockDevice = 52, + CharacterDevice = 51, + ContiguousFile = 55, + Directory = 53, + DirectoryList = 68, + ExtendedAttributes = 120, + Fifo = 54, + GlobalExtendedAttributes = 103, + HardLink = 49, + LongLink = 75, + LongPath = 76, + MultiVolume = 77, + RegularFile = 48, + RenamedOrSymlinked = 78, + SparseFile = 83, + SymbolicLink = 50, + TapeVolume = 86, + V7RegularFile = 0, + } + + public static class TarFile + { + public static void CreateFromDirectory(string sourceDirectoryName, System.IO.Stream destination, bool includeBaseDirectory) => throw null; + public static void CreateFromDirectory(string sourceDirectoryName, string destinationFileName, bool includeBaseDirectory) => throw null; + public static System.Threading.Tasks.Task CreateFromDirectoryAsync(string sourceDirectoryName, System.IO.Stream destination, bool includeBaseDirectory, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task CreateFromDirectoryAsync(string sourceDirectoryName, string destinationFileName, bool includeBaseDirectory, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static void ExtractToDirectory(System.IO.Stream source, string destinationDirectoryName, bool overwriteFiles) => throw null; + public static void ExtractToDirectory(string sourceFileName, string destinationDirectoryName, bool overwriteFiles) => throw null; + public static System.Threading.Tasks.Task ExtractToDirectoryAsync(System.IO.Stream source, string destinationDirectoryName, bool overwriteFiles, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task ExtractToDirectoryAsync(string sourceFileName, string destinationDirectoryName, bool overwriteFiles, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + } + + public class TarReader : System.IAsyncDisposable, System.IDisposable + { + public void Dispose() => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public System.Formats.Tar.TarEntry GetNextEntry(bool copyData = default(bool)) => throw null; + public System.Threading.Tasks.ValueTask GetNextEntryAsync(bool copyData = default(bool), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public TarReader(System.IO.Stream archiveStream, bool leaveOpen = default(bool)) => throw null; + } + + public class TarWriter : System.IAsyncDisposable, System.IDisposable + { + public void Dispose() => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public System.Formats.Tar.TarEntryFormat Format { get => throw null; } + public TarWriter(System.IO.Stream archiveStream) => throw null; + public TarWriter(System.IO.Stream archiveStream, System.Formats.Tar.TarEntryFormat format = default(System.Formats.Tar.TarEntryFormat), bool leaveOpen = default(bool)) => throw null; + public TarWriter(System.IO.Stream archiveStream, bool leaveOpen = default(bool)) => throw null; + public void WriteEntry(System.Formats.Tar.TarEntry entry) => throw null; + public void WriteEntry(string fileName, string entryName) => throw null; + public System.Threading.Tasks.Task WriteEntryAsync(System.Formats.Tar.TarEntry entry, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.Task WriteEntryAsync(string fileName, string entryName, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + } + + public class UstarTarEntry : System.Formats.Tar.PosixTarEntry + { + public UstarTarEntry(System.Formats.Tar.TarEntry other) => throw null; + public UstarTarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) => throw null; + } + + public class V7TarEntry : System.Formats.Tar.TarEntry + { + public V7TarEntry(System.Formats.Tar.TarEntry other) => throw null; + public V7TarEntry(System.Formats.Tar.TarEntryType entryType, string entryName) => throw null; + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.Brotli.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.Brotli.cs index e33f82838c0..c1a3d5debcc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.Brotli.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.Brotli.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Compression.Brotli, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Compression { - // Generated from `System.IO.Compression.BrotliDecoder` in `System.IO.Compression.Brotli, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public struct BrotliDecoder : System.IDisposable { // Stub generator skipped constructor @@ -15,7 +15,6 @@ namespace System public static bool TryDecompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; } - // Generated from `System.IO.Compression.BrotliEncoder` in `System.IO.Compression.Brotli, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public struct BrotliEncoder : System.IDisposable { // Stub generator skipped constructor @@ -28,7 +27,6 @@ namespace System public static bool TryCompress(System.ReadOnlySpan source, System.Span destination, out int bytesWritten, int quality, int window) => throw null; } - // Generated from `System.IO.Compression.BrotliStream` in `System.IO.Compression.Brotli, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class BrotliStream : System.IO.Stream { public System.IO.Stream BaseStream { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.ZipFile.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.ZipFile.cs index e1b983b8182..2e9edb888ef 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.ZipFile.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.ZipFile.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Compression.ZipFile, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Compression { - // Generated from `System.IO.Compression.ZipFile` in `System.IO.Compression.ZipFile, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public static class ZipFile { public static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName) => throw null; @@ -21,7 +21,6 @@ namespace System public static System.IO.Compression.ZipArchive OpenRead(string archiveFileName) => throw null; } - // Generated from `System.IO.Compression.ZipFileExtensions` in `System.IO.Compression.ZipFile, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public static class ZipFileExtensions { public static System.IO.Compression.ZipArchiveEntry CreateEntryFromFile(this System.IO.Compression.ZipArchive destination, string sourceFileName, string entryName) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.cs index 5d7bca00fc6..d622100714e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Compression.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Compression, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Compression { - // Generated from `System.IO.Compression.CompressionLevel` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public enum CompressionLevel : int { Fastest = 1, @@ -15,14 +15,12 @@ namespace System SmallestSize = 3, } - // Generated from `System.IO.Compression.CompressionMode` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public enum CompressionMode : int { Compress = 1, Decompress = 0, } - // Generated from `System.IO.Compression.DeflateStream` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class DeflateStream : System.IO.Stream { public System.IO.Stream BaseStream { get => throw null; } @@ -56,9 +54,9 @@ namespace System public override void Write(System.ReadOnlySpan buffer) => throw null; public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override void WriteByte(System.Byte value) => throw null; } - // Generated from `System.IO.Compression.GZipStream` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class GZipStream : System.IO.Stream { public System.IO.Stream BaseStream { get => throw null; } @@ -92,9 +90,9 @@ namespace System public override void Write(System.ReadOnlySpan buffer) => throw null; public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override void WriteByte(System.Byte value) => throw null; } - // Generated from `System.IO.Compression.ZLibStream` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class ZLibStream : System.IO.Stream { public System.IO.Stream BaseStream { get => throw null; } @@ -131,9 +129,9 @@ namespace System public ZLibStream(System.IO.Stream stream, System.IO.Compression.CompressionMode mode, bool leaveOpen) => throw null; } - // Generated from `System.IO.Compression.ZipArchive` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class ZipArchive : System.IDisposable { + public string Comment { get => throw null; set => throw null; } public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName) => throw null; public System.IO.Compression.ZipArchiveEntry CreateEntry(string entryName, System.IO.Compression.CompressionLevel compressionLevel) => throw null; public void Dispose() => throw null; @@ -147,15 +145,16 @@ namespace System public ZipArchive(System.IO.Stream stream, System.IO.Compression.ZipArchiveMode mode, bool leaveOpen, System.Text.Encoding entryNameEncoding) => throw null; } - // Generated from `System.IO.Compression.ZipArchiveEntry` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public class ZipArchiveEntry { public System.IO.Compression.ZipArchive Archive { get => throw null; } + public string Comment { get => throw null; set => throw null; } public System.Int64 CompressedLength { get => throw null; } public System.UInt32 Crc32 { get => throw null; } public void Delete() => throw null; public int ExternalAttributes { get => throw null; set => throw null; } public string FullName { get => throw null; } + public bool IsEncrypted { get => throw null; } public System.DateTimeOffset LastWriteTime { get => throw null; set => throw null; } public System.Int64 Length { get => throw null; } public string Name { get => throw null; } @@ -163,7 +162,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.IO.Compression.ZipArchiveMode` in `System.IO.Compression, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089` public enum ZipArchiveMode : int { Create = 1, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.AccessControl.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.AccessControl.cs index 9c4becadf63..8dd026736ca 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.AccessControl.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.AccessControl.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.IO.FileSystem.AccessControl, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace IO { - // Generated from `System.IO.FileSystemAclExtensions` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class FileSystemAclExtensions { public static void Create(this System.IO.DirectoryInfo directoryInfo, System.Security.AccessControl.DirectorySecurity directorySecurity) => throw null; @@ -25,7 +25,6 @@ namespace System { namespace AccessControl { - // Generated from `System.Security.AccessControl.DirectoryObjectSecurity` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DirectoryObjectSecurity : System.Security.AccessControl.ObjectSecurity { public virtual System.Security.AccessControl.AccessRule AccessRuleFactory(System.Security.Principal.IdentityReference identityReference, int accessMask, bool isInherited, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags, System.Security.AccessControl.AccessControlType type, System.Guid objectType, System.Guid inheritedObjectType) => throw null; @@ -49,21 +48,18 @@ namespace System protected void SetAuditRule(System.Security.AccessControl.ObjectAuditRule rule) => throw null; } - // Generated from `System.Security.AccessControl.DirectorySecurity` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DirectorySecurity : System.Security.AccessControl.FileSystemSecurity { public DirectorySecurity() => throw null; public DirectorySecurity(string name, System.Security.AccessControl.AccessControlSections includeSections) => throw null; } - // Generated from `System.Security.AccessControl.FileSecurity` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSecurity : System.Security.AccessControl.FileSystemSecurity { public FileSecurity() => throw null; public FileSecurity(string fileName, System.Security.AccessControl.AccessControlSections includeSections) => throw null; } - // Generated from `System.Security.AccessControl.FileSystemAccessRule` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystemAccessRule : System.Security.AccessControl.AccessRule { public FileSystemAccessRule(System.Security.Principal.IdentityReference identity, System.Security.AccessControl.FileSystemRights fileSystemRights, System.Security.AccessControl.AccessControlType type) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AccessControlType)) => throw null; @@ -73,7 +69,6 @@ namespace System public System.Security.AccessControl.FileSystemRights FileSystemRights { get => throw null; } } - // Generated from `System.Security.AccessControl.FileSystemAuditRule` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystemAuditRule : System.Security.AccessControl.AuditRule { public FileSystemAuditRule(System.Security.Principal.IdentityReference identity, System.Security.AccessControl.FileSystemRights fileSystemRights, System.Security.AccessControl.AuditFlags flags) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AuditFlags)) => throw null; @@ -83,7 +78,6 @@ namespace System public System.Security.AccessControl.FileSystemRights FileSystemRights { get => throw null; } } - // Generated from `System.Security.AccessControl.FileSystemRights` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileSystemRights : int { @@ -112,7 +106,6 @@ namespace System WriteExtendedAttributes = 16, } - // Generated from `System.Security.AccessControl.FileSystemSecurity` in `System.IO.FileSystem.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class FileSystemSecurity : System.Security.AccessControl.NativeObjectSecurity { public override System.Type AccessRightType { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.DriveInfo.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.DriveInfo.cs index df4b006e111..f5730af1388 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.DriveInfo.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.DriveInfo.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.IO.FileSystem.DriveInfo, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace IO { - // Generated from `System.IO.DriveInfo` in `System.IO.FileSystem.DriveInfo, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DriveInfo : System.Runtime.Serialization.ISerializable { public System.Int64 AvailableFreeSpace { get => throw null; } @@ -22,7 +22,6 @@ namespace System public string VolumeLabel { get => throw null; set => throw null; } } - // Generated from `System.IO.DriveNotFoundException` in `System.IO.FileSystem.DriveInfo, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DriveNotFoundException : System.IO.IOException { public DriveNotFoundException() => throw null; @@ -31,7 +30,6 @@ namespace System public DriveNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.IO.DriveType` in `System.IO.FileSystem.DriveInfo, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DriveType : int { CDRom = 5, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.Watcher.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.Watcher.cs index 298ab86edfa..9019b06e86c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.Watcher.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.FileSystem.Watcher.cs @@ -1,20 +1,18 @@ // This file contains auto-generated code. +// Generated from `System.IO.FileSystem.Watcher, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace IO { - // Generated from `System.IO.ErrorEventArgs` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ErrorEventArgs : System.EventArgs { public ErrorEventArgs(System.Exception exception) => throw null; public virtual System.Exception GetException() => throw null; } - // Generated from `System.IO.ErrorEventHandler` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ErrorEventHandler(object sender, System.IO.ErrorEventArgs e); - // Generated from `System.IO.FileSystemEventArgs` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystemEventArgs : System.EventArgs { public System.IO.WatcherChangeTypes ChangeType { get => throw null; } @@ -23,10 +21,8 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.IO.FileSystemEventHandler` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void FileSystemEventHandler(object sender, System.IO.FileSystemEventArgs e); - // Generated from `System.IO.FileSystemWatcher` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystemWatcher : System.ComponentModel.Component, System.ComponentModel.ISupportInitialize { public void BeginInit() => throw null; @@ -55,10 +51,10 @@ namespace System public override System.ComponentModel.ISite Site { get => throw null; set => throw null; } public System.ComponentModel.ISynchronizeInvoke SynchronizingObject { get => throw null; set => throw null; } public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType) => throw null; + public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType, System.TimeSpan timeout) => throw null; public System.IO.WaitForChangedResult WaitForChanged(System.IO.WatcherChangeTypes changeType, int timeout) => throw null; } - // Generated from `System.IO.InternalBufferOverflowException` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InternalBufferOverflowException : System.SystemException { public InternalBufferOverflowException() => throw null; @@ -67,7 +63,6 @@ namespace System public InternalBufferOverflowException(string message, System.Exception inner) => throw null; } - // Generated from `System.IO.NotifyFilters` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum NotifyFilters : int { @@ -81,7 +76,6 @@ namespace System Size = 8, } - // Generated from `System.IO.RenamedEventArgs` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RenamedEventArgs : System.IO.FileSystemEventArgs { public string OldFullPath { get => throw null; } @@ -89,10 +83,8 @@ namespace System public RenamedEventArgs(System.IO.WatcherChangeTypes changeType, string directory, string name, string oldName) : base(default(System.IO.WatcherChangeTypes), default(string), default(string)) => throw null; } - // Generated from `System.IO.RenamedEventHandler` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void RenamedEventHandler(object sender, System.IO.RenamedEventArgs e); - // Generated from `System.IO.WaitForChangedResult` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct WaitForChangedResult { public System.IO.WatcherChangeTypes ChangeType { get => throw null; set => throw null; } @@ -102,7 +94,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.IO.WatcherChangeTypes` in `System.IO.FileSystem.Watcher, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum WatcherChangeTypes : int { diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.IsolatedStorage.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.IsolatedStorage.cs index bf01af848e9..42aaa82f2ad 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.IsolatedStorage.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.IsolatedStorage.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.IsolatedStorage, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,13 +7,11 @@ namespace System { namespace IsolatedStorage { - // Generated from `System.IO.IsolatedStorage.INormalizeForIsolatedStorage` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INormalizeForIsolatedStorage { object Normalize(); } - // Generated from `System.IO.IsolatedStorage.IsolatedStorage` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IsolatedStorage : System.MarshalByRefObject { public object ApplicationIdentity { get => throw null; } @@ -33,7 +32,6 @@ namespace System public virtual System.Int64 UsedSize { get => throw null; } } - // Generated from `System.IO.IsolatedStorage.IsolatedStorageException` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IsolatedStorageException : System.Exception { public IsolatedStorageException() => throw null; @@ -42,7 +40,6 @@ namespace System public IsolatedStorageException(string message, System.Exception inner) => throw null; } - // Generated from `System.IO.IsolatedStorage.IsolatedStorageFile` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IsolatedStorageFile : System.IO.IsolatedStorage.IsolatedStorage, System.IDisposable { public override System.Int64 AvailableFreeSpace { get => throw null; } @@ -90,7 +87,6 @@ namespace System public override System.Int64 UsedSize { get => throw null; } } - // Generated from `System.IO.IsolatedStorage.IsolatedStorageFileStream` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IsolatedStorageFileStream : System.IO.FileStream { public override System.IAsyncResult BeginRead(System.Byte[] array, int offset, int numBytes, System.AsyncCallback userCallback, object stateObject) => throw null; @@ -134,7 +130,6 @@ namespace System public override void WriteByte(System.Byte value) => throw null; } - // Generated from `System.IO.IsolatedStorage.IsolatedStorageScope` in `System.IO.IsolatedStorage, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum IsolatedStorageScope : int { diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.MemoryMappedFiles.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.MemoryMappedFiles.cs index f0c049e01b3..3635bb66008 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.MemoryMappedFiles.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.MemoryMappedFiles.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.MemoryMappedFiles, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeMemoryMappedFileHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public override bool IsInvalid { get => throw null; } @@ -14,7 +14,6 @@ namespace Microsoft public SafeMemoryMappedFileHandle() : base(default(bool)) => throw null; } - // Generated from `Microsoft.Win32.SafeHandles.SafeMemoryMappedViewHandle` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeMemoryMappedViewHandle : System.Runtime.InteropServices.SafeBuffer { protected override bool ReleaseHandle() => throw null; @@ -30,7 +29,6 @@ namespace System { namespace MemoryMappedFiles { - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedFile` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemoryMappedFile : System.IDisposable { public static System.IO.MemoryMappedFiles.MemoryMappedFile CreateFromFile(System.IO.FileStream fileStream, string mapName, System.Int64 capacity, System.IO.MemoryMappedFiles.MemoryMappedFileAccess access, System.IO.HandleInheritability inheritability, bool leaveOpen) => throw null; @@ -59,7 +57,6 @@ namespace System public Microsoft.Win32.SafeHandles.SafeMemoryMappedFileHandle SafeMemoryMappedFileHandle { get => throw null; } } - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedFileAccess` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MemoryMappedFileAccess : int { CopyOnWrite = 3, @@ -70,7 +67,6 @@ namespace System Write = 2, } - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedFileOptions` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MemoryMappedFileOptions : int { @@ -78,7 +74,6 @@ namespace System None = 0, } - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedFileRights` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MemoryMappedFileRights : int { @@ -97,7 +92,6 @@ namespace System Write = 2, } - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedViewAccessor` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemoryMappedViewAccessor : System.IO.UnmanagedMemoryAccessor { protected override void Dispose(bool disposing) => throw null; @@ -106,7 +100,6 @@ namespace System public Microsoft.Win32.SafeHandles.SafeMemoryMappedViewHandle SafeMemoryMappedViewHandle { get => throw null; } } - // Generated from `System.IO.MemoryMappedFiles.MemoryMappedViewStream` in `System.IO.MemoryMappedFiles, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemoryMappedViewStream : System.IO.UnmanagedMemoryStream { protected override void Dispose(bool disposing) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.AccessControl.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.AccessControl.cs index 1e2e39ca8cf..673ebe72872 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.AccessControl.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.AccessControl.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Pipes.AccessControl, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,19 +7,16 @@ namespace System { namespace Pipes { - // Generated from `System.IO.Pipes.AnonymousPipeServerStreamAcl` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class AnonymousPipeServerStreamAcl { public static System.IO.Pipes.AnonymousPipeServerStream Create(System.IO.Pipes.PipeDirection direction, System.IO.HandleInheritability inheritability, int bufferSize, System.IO.Pipes.PipeSecurity pipeSecurity) => throw null; } - // Generated from `System.IO.Pipes.NamedPipeServerStreamAcl` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class NamedPipeServerStreamAcl { public static System.IO.Pipes.NamedPipeServerStream Create(string pipeName, System.IO.Pipes.PipeDirection direction, int maxNumberOfServerInstances, System.IO.Pipes.PipeTransmissionMode transmissionMode, System.IO.Pipes.PipeOptions options, int inBufferSize, int outBufferSize, System.IO.Pipes.PipeSecurity pipeSecurity, System.IO.HandleInheritability inheritability = default(System.IO.HandleInheritability), System.IO.Pipes.PipeAccessRights additionalAccessRights = default(System.IO.Pipes.PipeAccessRights)) => throw null; } - // Generated from `System.IO.Pipes.PipeAccessRights` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PipeAccessRights : int { @@ -41,7 +39,6 @@ namespace System WriteExtendedAttributes = 16, } - // Generated from `System.IO.Pipes.PipeAccessRule` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PipeAccessRule : System.Security.AccessControl.AccessRule { public System.IO.Pipes.PipeAccessRights PipeAccessRights { get => throw null; } @@ -49,7 +46,6 @@ namespace System public PipeAccessRule(string identity, System.IO.Pipes.PipeAccessRights rights, System.Security.AccessControl.AccessControlType type) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AccessControlType)) => throw null; } - // Generated from `System.IO.Pipes.PipeAuditRule` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PipeAuditRule : System.Security.AccessControl.AuditRule { public System.IO.Pipes.PipeAccessRights PipeAccessRights { get => throw null; } @@ -57,7 +53,6 @@ namespace System public PipeAuditRule(string identity, System.IO.Pipes.PipeAccessRights rights, System.Security.AccessControl.AuditFlags flags) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AuditFlags)) => throw null; } - // Generated from `System.IO.Pipes.PipeSecurity` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PipeSecurity : System.Security.AccessControl.NativeObjectSecurity { public override System.Type AccessRightType { get => throw null; } @@ -80,7 +75,6 @@ namespace System public void SetAuditRule(System.IO.Pipes.PipeAuditRule rule) => throw null; } - // Generated from `System.IO.Pipes.PipesAclExtensions` in `System.IO.Pipes.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class PipesAclExtensions { public static System.IO.Pipes.PipeSecurity GetAccessControl(this System.IO.Pipes.PipeStream stream) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.cs index 221d01852a5..bd3581006a0 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.IO.Pipes.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.IO.Pipes, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.SafePipeHandle` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafePipeHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public override bool IsInvalid { get => throw null; } @@ -24,7 +24,6 @@ namespace System { namespace Pipes { - // Generated from `System.IO.Pipes.AnonymousPipeClientStream` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AnonymousPipeClientStream : System.IO.Pipes.PipeStream { public AnonymousPipeClientStream(System.IO.Pipes.PipeDirection direction, Microsoft.Win32.SafeHandles.SafePipeHandle safePipeHandle) : base(default(System.IO.Pipes.PipeDirection), default(int)) => throw null; @@ -35,7 +34,6 @@ namespace System // ERR: Stub generator didn't handle member: ~AnonymousPipeClientStream } - // Generated from `System.IO.Pipes.AnonymousPipeServerStream` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AnonymousPipeServerStream : System.IO.Pipes.PipeStream { public AnonymousPipeServerStream() : base(default(System.IO.Pipes.PipeDirection), default(int)) => throw null; @@ -52,14 +50,15 @@ namespace System // ERR: Stub generator didn't handle member: ~AnonymousPipeServerStream } - // Generated from `System.IO.Pipes.NamedPipeClientStream` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NamedPipeClientStream : System.IO.Pipes.PipeStream { protected internal override void CheckPipePropertyOperations() => throw null; public void Connect() => throw null; + public void Connect(System.TimeSpan timeout) => throw null; public void Connect(int timeout) => throw null; public System.Threading.Tasks.Task ConnectAsync() => throw null; public System.Threading.Tasks.Task ConnectAsync(System.Threading.CancellationToken cancellationToken) => throw null; + public System.Threading.Tasks.Task ConnectAsync(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) => throw null; public System.Threading.Tasks.Task ConnectAsync(int timeout) => throw null; public System.Threading.Tasks.Task ConnectAsync(int timeout, System.Threading.CancellationToken cancellationToken) => throw null; public NamedPipeClientStream(System.IO.Pipes.PipeDirection direction, bool isAsync, bool isConnected, Microsoft.Win32.SafeHandles.SafePipeHandle safePipeHandle) : base(default(System.IO.Pipes.PipeDirection), default(int)) => throw null; @@ -73,7 +72,6 @@ namespace System // ERR: Stub generator didn't handle member: ~NamedPipeClientStream } - // Generated from `System.IO.Pipes.NamedPipeServerStream` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NamedPipeServerStream : System.IO.Pipes.PipeStream { public System.IAsyncResult BeginWaitForConnection(System.AsyncCallback callback, object state) => throw null; @@ -95,7 +93,6 @@ namespace System // ERR: Stub generator didn't handle member: ~NamedPipeServerStream } - // Generated from `System.IO.Pipes.PipeDirection` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PipeDirection : int { In = 1, @@ -103,7 +100,6 @@ namespace System Out = 2, } - // Generated from `System.IO.Pipes.PipeOptions` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PipeOptions : int { @@ -113,7 +109,6 @@ namespace System WriteThrough = -2147483648, } - // Generated from `System.IO.Pipes.PipeStream` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class PipeStream : System.IO.Stream { public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -158,10 +153,8 @@ namespace System public override void WriteByte(System.Byte value) => throw null; } - // Generated from `System.IO.Pipes.PipeStreamImpersonationWorker` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void PipeStreamImpersonationWorker(); - // Generated from `System.IO.Pipes.PipeTransmissionMode` in `System.IO.Pipes, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PipeTransmissionMode : int { Byte = 0, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Expressions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Expressions.cs index 7f1e3c12426..8f8f33ee915 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Expressions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Expressions.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Linq.Expressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Dynamic { - // Generated from `System.Dynamic.BinaryOperationBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class BinaryOperationBinder : System.Dynamic.DynamicMetaObjectBinder { protected BinaryOperationBinder(System.Linq.Expressions.ExpressionType operation) => throw null; @@ -15,7 +15,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.BindingRestrictions` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class BindingRestrictions { public static System.Dynamic.BindingRestrictions Combine(System.Collections.Generic.IList contributingObjects) => throw null; @@ -27,7 +26,6 @@ namespace System public System.Linq.Expressions.Expression ToExpression() => throw null; } - // Generated from `System.Dynamic.CallInfo` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallInfo { public int ArgumentCount { get => throw null; } @@ -38,7 +36,6 @@ namespace System public override int GetHashCode() => throw null; } - // Generated from `System.Dynamic.ConvertBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ConvertBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -50,7 +47,6 @@ namespace System public System.Type Type { get => throw null; } } - // Generated from `System.Dynamic.CreateInstanceBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CreateInstanceBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -61,7 +57,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.DeleteIndexBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DeleteIndexBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -72,7 +67,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.DeleteMemberBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DeleteMemberBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -84,7 +78,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.DynamicMetaObject` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicMetaObject { public virtual System.Dynamic.DynamicMetaObject BindBinaryOperation(System.Dynamic.BinaryOperationBinder binder, System.Dynamic.DynamicMetaObject arg) => throw null; @@ -112,7 +105,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Dynamic.DynamicMetaObjectBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DynamicMetaObjectBinder : System.Runtime.CompilerServices.CallSiteBinder { public abstract System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args); @@ -124,7 +116,6 @@ namespace System public virtual System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.DynamicObject` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicObject : System.Dynamic.IDynamicMetaObjectProvider { protected DynamicObject() => throw null; @@ -144,7 +135,6 @@ namespace System public virtual bool TryUnaryOperation(System.Dynamic.UnaryOperationBinder binder, out object result) => throw null; } - // Generated from `System.Dynamic.ExpandoObject` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExpandoObject : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable, System.ComponentModel.INotifyPropertyChanged, System.Dynamic.IDynamicMetaObjectProvider { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -168,7 +158,6 @@ namespace System System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; } } - // Generated from `System.Dynamic.GetIndexBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GetIndexBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -179,7 +168,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.GetMemberBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GetMemberBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -191,19 +179,16 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.IDynamicMetaObjectProvider` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDynamicMetaObjectProvider { System.Dynamic.DynamicMetaObject GetMetaObject(System.Linq.Expressions.Expression parameter); } - // Generated from `System.Dynamic.IInvokeOnGetBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IInvokeOnGetBinder { bool InvokeOnGet { get; } } - // Generated from `System.Dynamic.InvokeBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class InvokeBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -214,7 +199,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.InvokeMemberBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class InvokeMemberBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -228,7 +212,6 @@ namespace System public override System.Type ReturnType { get => throw null; } } - // Generated from `System.Dynamic.SetIndexBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SetIndexBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -239,7 +222,6 @@ namespace System protected SetIndexBinder(System.Dynamic.CallInfo callInfo) => throw null; } - // Generated from `System.Dynamic.SetMemberBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SetMemberBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -251,7 +233,6 @@ namespace System protected SetMemberBinder(string name, bool ignoreCase) => throw null; } - // Generated from `System.Dynamic.UnaryOperationBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class UnaryOperationBinder : System.Dynamic.DynamicMetaObjectBinder { public override System.Dynamic.DynamicMetaObject Bind(System.Dynamic.DynamicMetaObject target, System.Dynamic.DynamicMetaObject[] args) => throw null; @@ -265,17 +246,14 @@ namespace System } namespace Linq { - // Generated from `System.Linq.IOrderedQueryable` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IOrderedQueryable : System.Collections.IEnumerable, System.Linq.IQueryable { } - // Generated from `System.Linq.IOrderedQueryable<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IOrderedQueryable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Linq.IOrderedQueryable, System.Linq.IQueryable, System.Linq.IQueryable { } - // Generated from `System.Linq.IQueryProvider` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IQueryProvider { System.Linq.IQueryable CreateQuery(System.Linq.Expressions.Expression expression); @@ -284,7 +262,6 @@ namespace System TResult Execute(System.Linq.Expressions.Expression expression); } - // Generated from `System.Linq.IQueryable` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IQueryable : System.Collections.IEnumerable { System.Type ElementType { get; } @@ -292,14 +269,12 @@ namespace System System.Linq.IQueryProvider Provider { get; } } - // Generated from `System.Linq.IQueryable<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IQueryable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Linq.IQueryable { } namespace Expressions { - // Generated from `System.Linq.Expressions.BinaryExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BinaryExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -314,7 +289,6 @@ namespace System public System.Linq.Expressions.BinaryExpression Update(System.Linq.Expressions.Expression left, System.Linq.Expressions.LambdaExpression conversion, System.Linq.Expressions.Expression right) => throw null; } - // Generated from `System.Linq.Expressions.BlockExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BlockExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -326,7 +300,6 @@ namespace System public System.Collections.ObjectModel.ReadOnlyCollection Variables { get => throw null; } } - // Generated from `System.Linq.Expressions.CatchBlock` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CatchBlock { public System.Linq.Expressions.Expression Body { get => throw null; } @@ -337,7 +310,6 @@ namespace System public System.Linq.Expressions.ParameterExpression Variable { get => throw null; } } - // Generated from `System.Linq.Expressions.ConditionalExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConditionalExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -349,7 +321,6 @@ namespace System public System.Linq.Expressions.ConditionalExpression Update(System.Linq.Expressions.Expression test, System.Linq.Expressions.Expression ifTrue, System.Linq.Expressions.Expression ifFalse) => throw null; } - // Generated from `System.Linq.Expressions.ConstantExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConstantExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -358,7 +329,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Linq.Expressions.DebugInfoExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebugInfoExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -372,7 +342,6 @@ namespace System public override System.Type Type { get => throw null; } } - // Generated from `System.Linq.Expressions.DefaultExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -380,7 +349,6 @@ namespace System public override System.Type Type { get => throw null; } } - // Generated from `System.Linq.Expressions.DynamicExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicExpression : System.Linq.Expressions.Expression, System.Linq.Expressions.IArgumentProvider, System.Linq.Expressions.IDynamicExpression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -408,14 +376,12 @@ namespace System public System.Linq.Expressions.DynamicExpression Update(System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.DynamicExpressionVisitor` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DynamicExpressionVisitor : System.Linq.Expressions.ExpressionVisitor { protected DynamicExpressionVisitor() => throw null; protected internal override System.Linq.Expressions.Expression VisitDynamic(System.Linq.Expressions.DynamicExpression node) => throw null; } - // Generated from `System.Linq.Expressions.ElementInit` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ElementInit : System.Linq.Expressions.IArgumentProvider { public System.Reflection.MethodInfo AddMethod { get => throw null; } @@ -426,7 +392,6 @@ namespace System public System.Linq.Expressions.ElementInit Update(System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.Expression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Expression { protected internal virtual System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -751,7 +716,6 @@ namespace System protected internal virtual System.Linq.Expressions.Expression VisitChildren(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; } - // Generated from `System.Linq.Expressions.Expression<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Expression : System.Linq.Expressions.LambdaExpression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -761,7 +725,6 @@ namespace System public System.Linq.Expressions.Expression Update(System.Linq.Expressions.Expression body, System.Collections.Generic.IEnumerable parameters) => throw null; } - // Generated from `System.Linq.Expressions.ExpressionType` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ExpressionType : int { Add = 0, @@ -851,7 +814,6 @@ namespace System Unbox = 62, } - // Generated from `System.Linq.Expressions.ExpressionVisitor` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ExpressionVisitor { protected ExpressionVisitor() => throw null; @@ -896,7 +858,6 @@ namespace System protected internal virtual System.Linq.Expressions.Expression VisitUnary(System.Linq.Expressions.UnaryExpression node) => throw null; } - // Generated from `System.Linq.Expressions.GotoExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GotoExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -908,7 +869,6 @@ namespace System public System.Linq.Expressions.Expression Value { get => throw null; } } - // Generated from `System.Linq.Expressions.GotoExpressionKind` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GotoExpressionKind : int { Break = 2, @@ -917,14 +877,12 @@ namespace System Return = 1, } - // Generated from `System.Linq.Expressions.IArgumentProvider` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IArgumentProvider { int ArgumentCount { get; } System.Linq.Expressions.Expression GetArgument(int index); } - // Generated from `System.Linq.Expressions.IDynamicExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDynamicExpression : System.Linq.Expressions.IArgumentProvider { object CreateCallSite(); @@ -932,7 +890,6 @@ namespace System System.Linq.Expressions.Expression Rewrite(System.Linq.Expressions.Expression[] args); } - // Generated from `System.Linq.Expressions.IndexExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IndexExpression : System.Linq.Expressions.Expression, System.Linq.Expressions.IArgumentProvider { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -946,7 +903,6 @@ namespace System public System.Linq.Expressions.IndexExpression Update(System.Linq.Expressions.Expression @object, System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.InvocationExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvocationExpression : System.Linq.Expressions.Expression, System.Linq.Expressions.IArgumentProvider { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -959,7 +915,6 @@ namespace System public System.Linq.Expressions.InvocationExpression Update(System.Linq.Expressions.Expression expression, System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.LabelExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LabelExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -970,7 +925,6 @@ namespace System public System.Linq.Expressions.LabelExpression Update(System.Linq.Expressions.LabelTarget target, System.Linq.Expressions.Expression defaultValue) => throw null; } - // Generated from `System.Linq.Expressions.LabelTarget` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LabelTarget { public string Name { get => throw null; } @@ -978,7 +932,6 @@ namespace System public System.Type Type { get => throw null; } } - // Generated from `System.Linq.Expressions.LambdaExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class LambdaExpression : System.Linq.Expressions.Expression { public System.Linq.Expressions.Expression Body { get => throw null; } @@ -994,7 +947,6 @@ namespace System public override System.Type Type { get => throw null; } } - // Generated from `System.Linq.Expressions.ListInitExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ListInitExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1007,7 +959,6 @@ namespace System public System.Linq.Expressions.ListInitExpression Update(System.Linq.Expressions.NewExpression newExpression, System.Collections.Generic.IEnumerable initializers) => throw null; } - // Generated from `System.Linq.Expressions.LoopExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LoopExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1019,7 +970,6 @@ namespace System public System.Linq.Expressions.LoopExpression Update(System.Linq.Expressions.LabelTarget breakLabel, System.Linq.Expressions.LabelTarget continueLabel, System.Linq.Expressions.Expression body) => throw null; } - // Generated from `System.Linq.Expressions.MemberAssignment` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberAssignment : System.Linq.Expressions.MemberBinding { public System.Linq.Expressions.Expression Expression { get => throw null; } @@ -1027,7 +977,6 @@ namespace System public System.Linq.Expressions.MemberAssignment Update(System.Linq.Expressions.Expression expression) => throw null; } - // Generated from `System.Linq.Expressions.MemberBinding` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MemberBinding { public System.Linq.Expressions.MemberBindingType BindingType { get => throw null; } @@ -1036,7 +985,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Linq.Expressions.MemberBindingType` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MemberBindingType : int { Assignment = 0, @@ -1044,7 +992,6 @@ namespace System MemberBinding = 1, } - // Generated from `System.Linq.Expressions.MemberExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1054,7 +1001,6 @@ namespace System public System.Linq.Expressions.MemberExpression Update(System.Linq.Expressions.Expression expression) => throw null; } - // Generated from `System.Linq.Expressions.MemberInitExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberInitExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1067,7 +1013,6 @@ namespace System public System.Linq.Expressions.MemberInitExpression Update(System.Linq.Expressions.NewExpression newExpression, System.Collections.Generic.IEnumerable bindings) => throw null; } - // Generated from `System.Linq.Expressions.MemberListBinding` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberListBinding : System.Linq.Expressions.MemberBinding { public System.Collections.ObjectModel.ReadOnlyCollection Initializers { get => throw null; } @@ -1075,7 +1020,6 @@ namespace System public System.Linq.Expressions.MemberListBinding Update(System.Collections.Generic.IEnumerable initializers) => throw null; } - // Generated from `System.Linq.Expressions.MemberMemberBinding` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberMemberBinding : System.Linq.Expressions.MemberBinding { public System.Collections.ObjectModel.ReadOnlyCollection Bindings { get => throw null; } @@ -1083,7 +1027,6 @@ namespace System public System.Linq.Expressions.MemberMemberBinding Update(System.Collections.Generic.IEnumerable bindings) => throw null; } - // Generated from `System.Linq.Expressions.MethodCallExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodCallExpression : System.Linq.Expressions.Expression, System.Linq.Expressions.IArgumentProvider { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1097,7 +1040,6 @@ namespace System public System.Linq.Expressions.MethodCallExpression Update(System.Linq.Expressions.Expression @object, System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.NewArrayExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NewArrayExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1106,7 +1048,6 @@ namespace System public System.Linq.Expressions.NewArrayExpression Update(System.Collections.Generic.IEnumerable expressions) => throw null; } - // Generated from `System.Linq.Expressions.NewExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NewExpression : System.Linq.Expressions.Expression, System.Linq.Expressions.IArgumentProvider { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1120,7 +1061,6 @@ namespace System public System.Linq.Expressions.NewExpression Update(System.Collections.Generic.IEnumerable arguments) => throw null; } - // Generated from `System.Linq.Expressions.ParameterExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParameterExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1130,7 +1070,6 @@ namespace System public override System.Type Type { get => throw null; } } - // Generated from `System.Linq.Expressions.RuntimeVariablesExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RuntimeVariablesExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1140,7 +1079,6 @@ namespace System public System.Collections.ObjectModel.ReadOnlyCollection Variables { get => throw null; } } - // Generated from `System.Linq.Expressions.SwitchCase` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SwitchCase { public System.Linq.Expressions.Expression Body { get => throw null; } @@ -1149,7 +1087,6 @@ namespace System public System.Linq.Expressions.SwitchCase Update(System.Collections.Generic.IEnumerable testValues, System.Linq.Expressions.Expression body) => throw null; } - // Generated from `System.Linq.Expressions.SwitchExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SwitchExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1162,7 +1099,6 @@ namespace System public System.Linq.Expressions.SwitchExpression Update(System.Linq.Expressions.Expression switchValue, System.Collections.Generic.IEnumerable cases, System.Linq.Expressions.Expression defaultBody) => throw null; } - // Generated from `System.Linq.Expressions.SymbolDocumentInfo` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SymbolDocumentInfo { public virtual System.Guid DocumentType { get => throw null; } @@ -1171,7 +1107,6 @@ namespace System public virtual System.Guid LanguageVendor { get => throw null; } } - // Generated from `System.Linq.Expressions.TryExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TryExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1184,7 +1119,6 @@ namespace System public System.Linq.Expressions.TryExpression Update(System.Linq.Expressions.Expression body, System.Collections.Generic.IEnumerable handlers, System.Linq.Expressions.Expression @finally, System.Linq.Expressions.Expression fault) => throw null; } - // Generated from `System.Linq.Expressions.TypeBinaryExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeBinaryExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1195,7 +1129,6 @@ namespace System public System.Linq.Expressions.TypeBinaryExpression Update(System.Linq.Expressions.Expression expression) => throw null; } - // Generated from `System.Linq.Expressions.UnaryExpression` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnaryExpression : System.Linq.Expressions.Expression { protected internal override System.Linq.Expressions.Expression Accept(System.Linq.Expressions.ExpressionVisitor visitor) => throw null; @@ -1216,7 +1149,6 @@ namespace System { namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.CallSite` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallSite { public System.Runtime.CompilerServices.CallSiteBinder Binder { get => throw null; } @@ -1224,7 +1156,6 @@ namespace System public static System.Runtime.CompilerServices.CallSite Create(System.Type delegateType, System.Runtime.CompilerServices.CallSiteBinder binder) => throw null; } - // Generated from `System.Runtime.CompilerServices.CallSite<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallSite : System.Runtime.CompilerServices.CallSite where T : class { public static System.Runtime.CompilerServices.CallSite Create(System.Runtime.CompilerServices.CallSiteBinder binder) => throw null; @@ -1232,7 +1163,6 @@ namespace System public T Update { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.CallSiteBinder` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CallSiteBinder { public abstract System.Linq.Expressions.Expression Bind(object[] args, System.Collections.ObjectModel.ReadOnlyCollection parameters, System.Linq.Expressions.LabelTarget returnLabel); @@ -1242,13 +1172,11 @@ namespace System public static System.Linq.Expressions.LabelTarget UpdateLabel { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.CallSiteHelpers` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CallSiteHelpers { public static bool IsInternalFrame(System.Reflection.MethodBase mb) => throw null; } - // Generated from `System.Runtime.CompilerServices.DebugInfoGenerator` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DebugInfoGenerator { public static System.Runtime.CompilerServices.DebugInfoGenerator CreatePdbGenerator() => throw null; @@ -1256,7 +1184,6 @@ namespace System public abstract void MarkSequencePoint(System.Linq.Expressions.LambdaExpression method, int ilOffset, System.Linq.Expressions.DebugInfoExpression sequencePoint); } - // Generated from `System.Runtime.CompilerServices.DynamicAttribute` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicAttribute : System.Attribute { public DynamicAttribute() => throw null; @@ -1264,14 +1191,12 @@ namespace System public System.Collections.Generic.IList TransformFlags { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.IRuntimeVariables` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IRuntimeVariables { int Count { get; } object this[int index] { get; set; } } - // Generated from `System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyCollectionBuilder : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public void Add(T item) => throw null; @@ -1308,7 +1233,6 @@ namespace System public System.Collections.ObjectModel.ReadOnlyCollection ToReadOnlyCollection() => throw null; } - // Generated from `System.Runtime.CompilerServices.RuleCache<>` in `System.Linq.Expressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RuleCache where T : class { } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Parallel.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Parallel.cs index 8cca385f2bf..a151bca4688 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Parallel.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Parallel.cs @@ -1,16 +1,15 @@ // This file contains auto-generated code. +// Generated from `System.Linq.Parallel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Linq { - // Generated from `System.Linq.OrderedParallelQuery<>` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OrderedParallelQuery : System.Linq.ParallelQuery { public override System.Collections.Generic.IEnumerator GetEnumerator() => throw null; } - // Generated from `System.Linq.ParallelEnumerable` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ParallelEnumerable { public static TResult Aggregate(this System.Linq.ParallelQuery source, System.Func seedFactory, System.Func updateAccumulatorFunc, System.Func combineAccumulatorsFunc, System.Func resultSelector) => throw null; @@ -218,14 +217,12 @@ namespace System public static System.Linq.ParallelQuery Zip(this System.Linq.ParallelQuery first, System.Linq.ParallelQuery second, System.Func resultSelector) => throw null; } - // Generated from `System.Linq.ParallelExecutionMode` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ParallelExecutionMode : int { Default = 0, ForceParallelism = 1, } - // Generated from `System.Linq.ParallelMergeOptions` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ParallelMergeOptions : int { AutoBuffered = 2, @@ -234,14 +231,12 @@ namespace System NotBuffered = 1, } - // Generated from `System.Linq.ParallelQuery` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParallelQuery : System.Collections.IEnumerable { System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; internal ParallelQuery() => throw null; } - // Generated from `System.Linq.ParallelQuery<>` in `System.Linq.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParallelQuery : System.Linq.ParallelQuery, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual System.Collections.Generic.IEnumerator GetEnumerator() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Queryable.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Queryable.cs index ba1896a4172..199d450bc94 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Queryable.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.Queryable.cs @@ -1,28 +1,25 @@ // This file contains auto-generated code. +// Generated from `System.Linq.Queryable, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Linq { - // Generated from `System.Linq.EnumerableExecutor` in `System.Linq.Queryable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EnumerableExecutor { internal EnumerableExecutor() => throw null; } - // Generated from `System.Linq.EnumerableExecutor<>` in `System.Linq.Queryable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumerableExecutor : System.Linq.EnumerableExecutor { public EnumerableExecutor(System.Linq.Expressions.Expression expression) => throw null; } - // Generated from `System.Linq.EnumerableQuery` in `System.Linq.Queryable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EnumerableQuery { internal EnumerableQuery() => throw null; } - // Generated from `System.Linq.EnumerableQuery<>` in `System.Linq.Queryable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumerableQuery : System.Linq.EnumerableQuery, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.Linq.IOrderedQueryable, System.Linq.IOrderedQueryable, System.Linq.IQueryProvider, System.Linq.IQueryable, System.Linq.IQueryable { System.Linq.IQueryable System.Linq.IQueryProvider.CreateQuery(System.Linq.Expressions.Expression expression) => throw null; @@ -39,7 +36,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Linq.Queryable` in `System.Linq.Queryable, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Queryable { public static TResult Aggregate(this System.Linq.IQueryable source, TAccumulate seed, System.Linq.Expressions.Expression> func, System.Linq.Expressions.Expression> selector) => throw null; @@ -133,10 +129,14 @@ namespace System public static TSource MinBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) => throw null; public static TSource MinBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IQueryable OfType(this System.Linq.IQueryable source) => throw null; + public static System.Linq.IOrderedQueryable Order(this System.Linq.IQueryable source) => throw null; + public static System.Linq.IOrderedQueryable Order(this System.Linq.IQueryable source, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IOrderedQueryable OrderBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) => throw null; public static System.Linq.IOrderedQueryable OrderBy(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IOrderedQueryable OrderByDescending(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector) => throw null; public static System.Linq.IOrderedQueryable OrderByDescending(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> keySelector, System.Collections.Generic.IComparer comparer) => throw null; + public static System.Linq.IOrderedQueryable OrderDescending(this System.Linq.IQueryable source) => throw null; + public static System.Linq.IOrderedQueryable OrderDescending(this System.Linq.IQueryable source, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IQueryable Prepend(this System.Linq.IQueryable source, TSource element) => throw null; public static System.Linq.IQueryable Reverse(this System.Linq.IQueryable source) => throw null; public static System.Linq.IQueryable Select(this System.Linq.IQueryable source, System.Linq.Expressions.Expression> selector) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.cs index f83bf76f605..f288e27be77 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Linq.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Linq, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Linq { - // Generated from `System.Linq.Enumerable` in `System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Enumerable { public static TResult Aggregate(this System.Collections.Generic.IEnumerable source, TAccumulate seed, System.Func func, System.Func resultSelector) => throw null; @@ -138,10 +138,14 @@ namespace System public static TSource MinBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector) => throw null; public static TSource MinBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Collections.Generic.IComparer comparer) => throw null; public static System.Collections.Generic.IEnumerable OfType(this System.Collections.IEnumerable source) => throw null; + public static System.Linq.IOrderedEnumerable Order(this System.Collections.Generic.IEnumerable source) => throw null; + public static System.Linq.IOrderedEnumerable Order(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IOrderedEnumerable OrderBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector) => throw null; public static System.Linq.IOrderedEnumerable OrderBy(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Collections.Generic.IComparer comparer) => throw null; public static System.Linq.IOrderedEnumerable OrderByDescending(this System.Collections.Generic.IEnumerable source, System.Func keySelector) => throw null; public static System.Linq.IOrderedEnumerable OrderByDescending(this System.Collections.Generic.IEnumerable source, System.Func keySelector, System.Collections.Generic.IComparer comparer) => throw null; + public static System.Linq.IOrderedEnumerable OrderDescending(this System.Collections.Generic.IEnumerable source) => throw null; + public static System.Linq.IOrderedEnumerable OrderDescending(this System.Collections.Generic.IEnumerable source, System.Collections.Generic.IComparer comparer) => throw null; public static System.Collections.Generic.IEnumerable Prepend(this System.Collections.Generic.IEnumerable source, TSource element) => throw null; public static System.Collections.Generic.IEnumerable Range(int start, int count) => throw null; public static System.Collections.Generic.IEnumerable Repeat(TResult element, int count) => throw null; @@ -217,13 +221,11 @@ namespace System public static System.Collections.Generic.IEnumerable<(TFirst, TSecond)> Zip(this System.Collections.Generic.IEnumerable first, System.Collections.Generic.IEnumerable second) => throw null; } - // Generated from `System.Linq.IGrouping<,>` in `System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IGrouping : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { TKey Key { get; } } - // Generated from `System.Linq.ILookup<,>` in `System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ILookup : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { bool Contains(TKey key); @@ -231,13 +233,11 @@ namespace System System.Collections.Generic.IEnumerable this[TKey key] { get; } } - // Generated from `System.Linq.IOrderedEnumerable<>` in `System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IOrderedEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { System.Linq.IOrderedEnumerable CreateOrderedEnumerable(System.Func keySelector, System.Collections.Generic.IComparer comparer, bool descending); } - // Generated from `System.Linq.Lookup<,>` in `System.Linq, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Lookup : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable, System.Linq.ILookup { public System.Collections.Generic.IEnumerable ApplyResultSelector(System.Func, TResult> resultSelector) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Memory.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Memory.cs index 0b1f6aaaa4a..ce4a7e45a61 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Memory.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Memory.cs @@ -1,11 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Memory, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { - // Generated from `System.MemoryExtensions` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class MemoryExtensions { - // Generated from `System.MemoryExtensions+TryWriteInterpolatedStringHandler` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct TryWriteInterpolatedStringHandler { public bool AppendFormatted(System.ReadOnlySpan value) => throw null; @@ -56,6 +55,10 @@ namespace System public static int BinarySearch(this System.Span span, T value, TComparer comparer) where TComparer : System.Collections.Generic.IComparer => throw null; public static int BinarySearch(this System.ReadOnlySpan span, System.IComparable comparable) => throw null; public static int BinarySearch(this System.Span span, System.IComparable comparable) => throw null; + public static int CommonPrefixLength(this System.ReadOnlySpan span, System.ReadOnlySpan other) => throw null; + public static int CommonPrefixLength(this System.ReadOnlySpan span, System.ReadOnlySpan other, System.Collections.Generic.IEqualityComparer comparer) => throw null; + public static int CommonPrefixLength(this System.Span span, System.ReadOnlySpan other) => throw null; + public static int CommonPrefixLength(this System.Span span, System.ReadOnlySpan other, System.Collections.Generic.IEqualityComparer comparer) => throw null; public static int CompareTo(this System.ReadOnlySpan span, System.ReadOnlySpan other, System.StringComparison comparisonType) => throw null; public static bool Contains(this System.ReadOnlySpan span, System.ReadOnlySpan value, System.StringComparison comparisonType) => throw null; public static bool Contains(this System.ReadOnlySpan span, T value) where T : System.IEquatable => throw null; @@ -81,6 +84,14 @@ namespace System public static int IndexOfAny(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; public static int IndexOfAny(this System.Span span, T value0, T value1) where T : System.IEquatable => throw null; public static int IndexOfAny(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.ReadOnlySpan span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.ReadOnlySpan span, T value) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.ReadOnlySpan span, T value0, T value1) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.ReadOnlySpan span, T value0, T value1, T value2) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.Span span, T value) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.Span span, T value0, T value1) where T : System.IEquatable => throw null; + public static int IndexOfAnyExcept(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable => throw null; public static bool IsWhiteSpace(this System.ReadOnlySpan span) => throw null; public static int LastIndexOf(this System.ReadOnlySpan span, System.ReadOnlySpan value, System.StringComparison comparisonType) => throw null; public static int LastIndexOf(this System.ReadOnlySpan span, System.ReadOnlySpan value) where T : System.IEquatable => throw null; @@ -93,6 +104,14 @@ namespace System public static int LastIndexOfAny(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; public static int LastIndexOfAny(this System.Span span, T value0, T value1) where T : System.IEquatable => throw null; public static int LastIndexOfAny(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.ReadOnlySpan span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.ReadOnlySpan span, T value) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.ReadOnlySpan span, T value0, T value1) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.ReadOnlySpan span, T value0, T value1, T value2) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.Span span, System.ReadOnlySpan values) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.Span span, T value) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.Span span, T value0, T value1) where T : System.IEquatable => throw null; + public static int LastIndexOfAnyExcept(this System.Span span, T value0, T value1, T value2) where T : System.IEquatable => throw null; public static bool Overlaps(this System.ReadOnlySpan span, System.ReadOnlySpan other) => throw null; public static bool Overlaps(this System.ReadOnlySpan span, System.ReadOnlySpan other, out int elementOffset) => throw null; public static bool Overlaps(this System.Span span, System.ReadOnlySpan other) => throw null; @@ -163,7 +182,6 @@ namespace System public static bool TryWrite(this System.Span destination, ref System.MemoryExtensions.TryWriteInterpolatedStringHandler handler, out int charsWritten) => throw null; } - // Generated from `System.SequencePosition` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct SequencePosition : System.IEquatable { public bool Equals(System.SequencePosition other) => throw null; @@ -177,7 +195,6 @@ namespace System namespace Buffers { - // Generated from `System.Buffers.ArrayBufferWriter<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ArrayBufferWriter : System.Buffers.IBufferWriter { public void Advance(int count) => throw null; @@ -193,7 +210,6 @@ namespace System public System.ReadOnlySpan WrittenSpan { get => throw null; } } - // Generated from `System.Buffers.BuffersExtensions` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class BuffersExtensions { public static void CopyTo(System.Buffers.ReadOnlySequence source, System.Span destination) => throw null; @@ -202,7 +218,6 @@ namespace System public static void Write(this System.Buffers.IBufferWriter writer, System.ReadOnlySpan value) => throw null; } - // Generated from `System.Buffers.IBufferWriter<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IBufferWriter { void Advance(int count); @@ -210,7 +225,6 @@ namespace System System.Span GetSpan(int sizeHint = default(int)); } - // Generated from `System.Buffers.MemoryPool<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class MemoryPool : System.IDisposable { public void Dispose() => throw null; @@ -221,10 +235,8 @@ namespace System public static System.Buffers.MemoryPool Shared { get => throw null; } } - // Generated from `System.Buffers.ReadOnlySequence<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ReadOnlySequence { - // Generated from `System.Buffers.ReadOnlySequence<>+Enumerator` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Enumerator { public System.ReadOnlyMemory Current { get => throw null; } @@ -264,7 +276,6 @@ namespace System public bool TryGet(ref System.SequencePosition position, out System.ReadOnlyMemory memory, bool advance = default(bool)) => throw null; } - // Generated from `System.Buffers.ReadOnlySequenceSegment<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ReadOnlySequenceSegment { public System.ReadOnlyMemory Memory { get => throw null; set => throw null; } @@ -273,7 +284,6 @@ namespace System public System.Int64 RunningIndex { get => throw null; set => throw null; } } - // Generated from `System.Buffers.SequenceReader<>` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct SequenceReader where T : unmanaged, System.IEquatable { public void Advance(System.Int64 count) => throw null; @@ -302,6 +312,7 @@ namespace System public bool TryPeek(System.Int64 offset, out T value) => throw null; public bool TryPeek(out T value) => throw null; public bool TryRead(out T value) => throw null; + public bool TryReadExact(int count, out System.Buffers.ReadOnlySequence sequence) => throw null; public bool TryReadTo(out System.Buffers.ReadOnlySequence sequence, System.ReadOnlySpan delimiter, bool advancePastDelimiter = default(bool)) => throw null; public bool TryReadTo(out System.Buffers.ReadOnlySequence sequence, T delimiter, T delimiterEscape, bool advancePastDelimiter = default(bool)) => throw null; public bool TryReadTo(out System.Buffers.ReadOnlySequence sequence, T delimiter, bool advancePastDelimiter = default(bool)) => throw null; @@ -314,7 +325,6 @@ namespace System public System.ReadOnlySpan UnreadSpan { get => throw null; } } - // Generated from `System.Buffers.SequenceReaderExtensions` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class SequenceReaderExtensions { public static bool TryReadBigEndian(ref System.Buffers.SequenceReader reader, out int value) => throw null; @@ -325,7 +335,6 @@ namespace System public static bool TryReadLittleEndian(ref System.Buffers.SequenceReader reader, out System.Int16 value) => throw null; } - // Generated from `System.Buffers.StandardFormat` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct StandardFormat : System.IEquatable { public static bool operator !=(System.Buffers.StandardFormat left, System.Buffers.StandardFormat right) => throw null; @@ -350,7 +359,6 @@ namespace System namespace Binary { - // Generated from `System.Buffers.Binary.BinaryPrimitives` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class BinaryPrimitives { public static double ReadDoubleBigEndian(System.ReadOnlySpan source) => throw null; @@ -438,18 +446,6 @@ namespace System } namespace Text { - // Generated from `System.Buffers.Text.Base64` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` - public static class Base64 - { - public static System.Buffers.OperationStatus DecodeFromUtf8(System.ReadOnlySpan utf8, System.Span bytes, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = default(bool)) => throw null; - public static System.Buffers.OperationStatus DecodeFromUtf8InPlace(System.Span buffer, out int bytesWritten) => throw null; - public static System.Buffers.OperationStatus EncodeToUtf8(System.ReadOnlySpan bytes, System.Span utf8, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = default(bool)) => throw null; - public static System.Buffers.OperationStatus EncodeToUtf8InPlace(System.Span buffer, int dataLength, out int bytesWritten) => throw null; - public static int GetMaxDecodedFromUtf8Length(int length) => throw null; - public static int GetMaxEncodedToUtf8Length(int length) => throw null; - } - - // Generated from `System.Buffers.Text.Utf8Formatter` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Utf8Formatter { public static bool TryFormat(System.DateTime value, System.Span destination, out int bytesWritten, System.Buffers.StandardFormat format = default(System.Buffers.StandardFormat)) => throw null; @@ -470,7 +466,6 @@ namespace System public static bool TryFormat(System.UInt16 value, System.Span destination, out int bytesWritten, System.Buffers.StandardFormat format = default(System.Buffers.StandardFormat)) => throw null; } - // Generated from `System.Buffers.Text.Utf8Parser` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Utf8Parser { public static bool TryParse(System.ReadOnlySpan source, out System.DateTime value, out int bytesConsumed, System.Char standardFormat = default(System.Char)) => throw null; @@ -497,7 +492,6 @@ namespace System { namespace InteropServices { - // Generated from `System.Runtime.InteropServices.MemoryMarshal` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class MemoryMarshal { public static System.ReadOnlySpan AsBytes(System.ReadOnlySpan span) where T : struct => throw null; @@ -527,7 +521,6 @@ namespace System public static void Write(System.Span destination, ref T value) where T : struct => throw null; } - // Generated from `System.Runtime.InteropServices.SequenceMarshal` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class SequenceMarshal { public static bool TryGetArray(System.Buffers.ReadOnlySequence sequence, out System.ArraySegment segment) => throw null; @@ -540,7 +533,6 @@ namespace System } namespace Text { - // Generated from `System.Text.EncodingExtensions` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class EncodingExtensions { public static void Convert(this System.Text.Decoder decoder, System.Buffers.ReadOnlySequence bytes, System.Buffers.IBufferWriter writer, bool flush, out System.Int64 charsUsed, out bool completed) => throw null; @@ -557,7 +549,6 @@ namespace System public static string GetString(this System.Text.Encoding encoding, System.Buffers.ReadOnlySequence bytes) => throw null; } - // Generated from `System.Text.SpanLineEnumerator` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct SpanLineEnumerator { public System.ReadOnlySpan Current { get => throw null; } @@ -566,7 +557,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Text.SpanRuneEnumerator` in `System.Memory, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct SpanRuneEnumerator { public System.Text.Rune Current { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.Json.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.Json.cs index b9d7e73fdce..d446b901ee7 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.Json.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.Json.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Http.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -8,9 +9,20 @@ namespace System { namespace Json { - // Generated from `System.Net.Http.Json.HttpClientJsonExtensions` in `System.Net.Http.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class HttpClientJsonExtensions { + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Type type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Type type, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task DeleteFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, System.Type type, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -23,6 +35,12 @@ namespace System public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Text.Json.JsonSerializerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task GetFromJsonAsync(this System.Net.Http.HttpClient client, string requestUri, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, string requestUri, TValue value, System.Threading.CancellationToken cancellationToken) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, string requestUri, TValue value, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.Task PatchAsJsonAsync(this System.Net.Http.HttpClient client, string requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Threading.CancellationToken cancellationToken) => throw null; public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.Task PostAsJsonAsync(this System.Net.Http.HttpClient client, System.Uri requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -37,7 +55,6 @@ namespace System public static System.Threading.Tasks.Task PutAsJsonAsync(this System.Net.Http.HttpClient client, string requestUri, TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.Net.Http.Json.HttpContentJsonExtensions` in `System.Net.Http.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class HttpContentJsonExtensions { public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Type type, System.Text.Json.Serialization.JsonSerializerContext context, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; @@ -46,7 +63,6 @@ namespace System public static System.Threading.Tasks.Task ReadFromJsonAsync(this System.Net.Http.HttpContent content, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.Net.Http.Json.JsonContent` in `System.Net.Http.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonContent : System.Net.Http.HttpContent { public static System.Net.Http.Json.JsonContent Create(object inputValue, System.Type inputType, System.Net.Http.Headers.MediaTypeHeaderValue mediaType = default(System.Net.Http.Headers.MediaTypeHeaderValue), System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions)) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.cs index 320e4ceec59..b90cbb9cb5a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Http.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Http, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Http { - // Generated from `System.Net.Http.ByteArrayContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ByteArrayContent : System.Net.Http.HttpContent { public ByteArrayContent(System.Byte[] content) => throw null; @@ -19,14 +19,12 @@ namespace System protected internal override bool TryComputeLength(out System.Int64 length) => throw null; } - // Generated from `System.Net.Http.ClientCertificateOption` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ClientCertificateOption : int { Automatic = 1, Manual = 0, } - // Generated from `System.Net.Http.DelegatingHandler` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DelegatingHandler : System.Net.Http.HttpMessageHandler { protected DelegatingHandler() => throw null; @@ -37,17 +35,14 @@ namespace System protected internal override System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Net.Http.FormUrlEncodedContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FormUrlEncodedContent : System.Net.Http.ByteArrayContent { public FormUrlEncodedContent(System.Collections.Generic.IEnumerable> nameValueCollection) : base(default(System.Byte[])) => throw null; protected override System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Net.Http.HeaderEncodingSelector<>` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Text.Encoding HeaderEncodingSelector(string headerName, TContext context); - // Generated from `System.Net.Http.HttpClient` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpClient : System.Net.Http.HttpMessageInvoker { public System.Uri BaseAddress { get => throw null; set => throw null; } @@ -108,7 +103,6 @@ namespace System public System.TimeSpan Timeout { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.HttpClientHandler` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpClientHandler : System.Net.Http.HttpMessageHandler { public bool AllowAutoRedirect { get => throw null; set => throw null; } @@ -141,14 +135,12 @@ namespace System public bool UseProxy { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.HttpCompletionOption` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpCompletionOption : int { ResponseContentRead = 0, ResponseHeadersRead = 1, } - // Generated from `System.Net.Http.HttpContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class HttpContent : System.IDisposable { public void CopyTo(System.IO.Stream stream, System.Net.TransportContext context, System.Threading.CancellationToken cancellationToken) => throw null; @@ -179,14 +171,12 @@ namespace System protected internal abstract bool TryComputeLength(out System.Int64 length); } - // Generated from `System.Net.Http.HttpKeepAlivePingPolicy` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpKeepAlivePingPolicy : int { Always = 1, WithActiveRequests = 0, } - // Generated from `System.Net.Http.HttpMessageHandler` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class HttpMessageHandler : System.IDisposable { public void Dispose() => throw null; @@ -196,7 +186,6 @@ namespace System protected internal abstract System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken); } - // Generated from `System.Net.Http.HttpMessageInvoker` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpMessageInvoker : System.IDisposable { public void Dispose() => throw null; @@ -207,11 +196,11 @@ namespace System public virtual System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Net.Http.HttpMethod` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpMethod : System.IEquatable { public static bool operator !=(System.Net.Http.HttpMethod left, System.Net.Http.HttpMethod right) => throw null; public static bool operator ==(System.Net.Http.HttpMethod left, System.Net.Http.HttpMethod right) => throw null; + public static System.Net.Http.HttpMethod Connect { get => throw null; } public static System.Net.Http.HttpMethod Delete { get => throw null; } public bool Equals(System.Net.Http.HttpMethod other) => throw null; public override bool Equals(object obj) => throw null; @@ -228,7 +217,12 @@ namespace System public static System.Net.Http.HttpMethod Trace { get => throw null; } } - // Generated from `System.Net.Http.HttpRequestException` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class HttpProtocolException : System.IO.IOException + { + public System.Int64 ErrorCode { get => throw null; } + public HttpProtocolException(System.Int64 errorCode, string message, System.Exception innerException) => throw null; + } + public class HttpRequestException : System.Exception { public HttpRequestException() => throw null; @@ -238,7 +232,6 @@ namespace System public System.Net.HttpStatusCode? StatusCode { get => throw null; } } - // Generated from `System.Net.Http.HttpRequestMessage` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpRequestMessage : System.IDisposable { public System.Net.Http.HttpContent Content { get => throw null; set => throw null; } @@ -257,7 +250,6 @@ namespace System public System.Net.Http.HttpVersionPolicy VersionPolicy { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.HttpRequestOptions` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpRequestOptions : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null; @@ -281,7 +273,6 @@ namespace System System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; } } - // Generated from `System.Net.Http.HttpRequestOptionsKey<>` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct HttpRequestOptionsKey { // Stub generator skipped constructor @@ -289,7 +280,6 @@ namespace System public string Key { get => throw null; } } - // Generated from `System.Net.Http.HttpResponseMessage` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpResponseMessage : System.IDisposable { public System.Net.Http.HttpContent Content { get => throw null; set => throw null; } @@ -308,7 +298,6 @@ namespace System public System.Version Version { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.HttpVersionPolicy` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpVersionPolicy : int { RequestVersionExact = 2, @@ -316,7 +305,6 @@ namespace System RequestVersionOrLower = 0, } - // Generated from `System.Net.Http.MessageProcessingHandler` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MessageProcessingHandler : System.Net.Http.DelegatingHandler { protected MessageProcessingHandler() => throw null; @@ -327,7 +315,6 @@ namespace System protected internal override System.Threading.Tasks.Task SendAsync(System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Net.Http.MultipartContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MultipartContent : System.Net.Http.HttpContent, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.Http.HttpContent content) => throw null; @@ -347,7 +334,6 @@ namespace System protected internal override bool TryComputeLength(out System.Int64 length) => throw null; } - // Generated from `System.Net.Http.MultipartFormDataContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MultipartFormDataContent : System.Net.Http.MultipartContent { public override void Add(System.Net.Http.HttpContent content) => throw null; @@ -358,7 +344,6 @@ namespace System protected override System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Net.Http.ReadOnlyMemoryContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyMemoryContent : System.Net.Http.HttpContent { protected override System.IO.Stream CreateContentReadStream(System.Threading.CancellationToken cancellationToken) => throw null; @@ -370,14 +355,12 @@ namespace System protected internal override bool TryComputeLength(out System.Int64 length) => throw null; } - // Generated from `System.Net.Http.SocketsHttpConnectionContext` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketsHttpConnectionContext { public System.Net.DnsEndPoint DnsEndPoint { get => throw null; } public System.Net.Http.HttpRequestMessage InitialRequestMessage { get => throw null; } } - // Generated from `System.Net.Http.SocketsHttpHandler` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketsHttpHandler : System.Net.Http.HttpMessageHandler { public System.Diagnostics.DistributedContextPropagator ActivityHeadersPropagator { get => throw null; set => throw null; } @@ -417,7 +400,6 @@ namespace System public bool UseProxy { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.SocketsHttpPlaintextStreamFilterContext` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketsHttpPlaintextStreamFilterContext { public System.Net.Http.HttpRequestMessage InitialRequestMessage { get => throw null; } @@ -425,7 +407,6 @@ namespace System public System.IO.Stream PlaintextStream { get => throw null; } } - // Generated from `System.Net.Http.StreamContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StreamContent : System.Net.Http.HttpContent { protected override System.IO.Stream CreateContentReadStream(System.Threading.CancellationToken cancellationToken) => throw null; @@ -439,18 +420,18 @@ namespace System protected internal override bool TryComputeLength(out System.Int64 length) => throw null; } - // Generated from `System.Net.Http.StringContent` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringContent : System.Net.Http.ByteArrayContent { protected override System.Threading.Tasks.Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context, System.Threading.CancellationToken cancellationToken) => throw null; public StringContent(string content) : base(default(System.Byte[])) => throw null; public StringContent(string content, System.Text.Encoding encoding) : base(default(System.Byte[])) => throw null; + public StringContent(string content, System.Text.Encoding encoding, System.Net.Http.Headers.MediaTypeHeaderValue mediaType) : base(default(System.Byte[])) => throw null; public StringContent(string content, System.Text.Encoding encoding, string mediaType) : base(default(System.Byte[])) => throw null; + public StringContent(string content, System.Net.Http.Headers.MediaTypeHeaderValue mediaType) : base(default(System.Byte[])) => throw null; } namespace Headers { - // Generated from `System.Net.Http.Headers.AuthenticationHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AuthenticationHeaderValue : System.ICloneable { public AuthenticationHeaderValue(string scheme) => throw null; @@ -465,7 +446,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.AuthenticationHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.CacheControlHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CacheControlHeaderValue : System.ICloneable { public CacheControlHeaderValue() => throw null; @@ -493,7 +473,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.CacheControlHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.ContentDispositionHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContentDispositionHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -515,7 +494,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.ContentDispositionHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.ContentRangeHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContentRangeHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -535,7 +513,6 @@ namespace System public string Unit { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.Headers.EntityTagHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EntityTagHeaderValue : System.ICloneable { public static System.Net.Http.Headers.EntityTagHeaderValue Any { get => throw null; } @@ -551,10 +528,8 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.EntityTagHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.HeaderStringValues` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct HeaderStringValues : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Net.Http.Headers.HeaderStringValues+Enumerator` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public string Current { get => throw null; } @@ -574,7 +549,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Http.Headers.HttpContentHeaders` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpContentHeaders : System.Net.Http.Headers.HttpHeaders { public System.Collections.Generic.ICollection Allow { get => throw null; } @@ -590,7 +564,6 @@ namespace System public System.DateTimeOffset? LastModified { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.Headers.HttpHeaderValueCollection<>` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpHeaderValueCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable where T : class { public void Add(T item) => throw null; @@ -607,7 +580,6 @@ namespace System public bool TryParseAdd(string input) => throw null; } - // Generated from `System.Net.Http.Headers.HttpHeaders` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class HttpHeaders : System.Collections.Generic.IEnumerable>>, System.Collections.IEnumerable { public void Add(string name, System.Collections.Generic.IEnumerable values) => throw null; @@ -626,10 +598,8 @@ namespace System public bool TryGetValues(string name, out System.Collections.Generic.IEnumerable values) => throw null; } - // Generated from `System.Net.Http.Headers.HttpHeadersNonValidated` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct HttpHeadersNonValidated : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.IEnumerable { - // Generated from `System.Net.Http.Headers.HttpHeadersNonValidated+Enumerator` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator>, System.Collections.IEnumerator, System.IDisposable { public System.Collections.Generic.KeyValuePair Current { get => throw null; } @@ -655,7 +625,6 @@ namespace System System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } } - // Generated from `System.Net.Http.Headers.HttpRequestHeaders` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpRequestHeaders : System.Net.Http.Headers.HttpHeaders { public System.Net.Http.Headers.HttpHeaderValueCollection Accept { get => throw null; } @@ -678,6 +647,7 @@ namespace System public System.DateTimeOffset? IfUnmodifiedSince { get => throw null; set => throw null; } public int? MaxForwards { get => throw null; set => throw null; } public System.Net.Http.Headers.HttpHeaderValueCollection Pragma { get => throw null; } + public string Protocol { get => throw null; set => throw null; } public System.Net.Http.Headers.AuthenticationHeaderValue ProxyAuthorization { get => throw null; set => throw null; } public System.Net.Http.Headers.RangeHeaderValue Range { get => throw null; set => throw null; } public System.Uri Referrer { get => throw null; set => throw null; } @@ -691,7 +661,6 @@ namespace System public System.Net.Http.Headers.HttpHeaderValueCollection Warning { get => throw null; } } - // Generated from `System.Net.Http.Headers.HttpResponseHeaders` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpResponseHeaders : System.Net.Http.Headers.HttpHeaders { public System.Net.Http.Headers.HttpHeaderValueCollection AcceptRanges { get => throw null; } @@ -716,7 +685,6 @@ namespace System public System.Net.Http.Headers.HttpHeaderValueCollection WwwAuthenticate { get => throw null; } } - // Generated from `System.Net.Http.Headers.MediaTypeHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MediaTypeHeaderValue : System.ICloneable { public string CharSet { get => throw null; set => throw null; } @@ -726,13 +694,13 @@ namespace System public string MediaType { get => throw null; set => throw null; } protected MediaTypeHeaderValue(System.Net.Http.Headers.MediaTypeHeaderValue source) => throw null; public MediaTypeHeaderValue(string mediaType) => throw null; + public MediaTypeHeaderValue(string mediaType, string charSet) => throw null; public System.Collections.Generic.ICollection Parameters { get => throw null; } public static System.Net.Http.Headers.MediaTypeHeaderValue Parse(string input) => throw null; public override string ToString() => throw null; public static bool TryParse(string input, out System.Net.Http.Headers.MediaTypeHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.MediaTypeWithQualityHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MediaTypeWithQualityHeaderValue : System.Net.Http.Headers.MediaTypeHeaderValue, System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -743,7 +711,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.MediaTypeWithQualityHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.NameValueHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NameValueHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -759,7 +726,6 @@ namespace System public string Value { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.Headers.NameValueWithParametersHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NameValueWithParametersHeaderValue : System.Net.Http.Headers.NameValueHeaderValue, System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -774,7 +740,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.NameValueWithParametersHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.ProductHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProductHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -789,7 +754,6 @@ namespace System public string Version { get => throw null; } } - // Generated from `System.Net.Http.Headers.ProductInfoHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProductInfoHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -805,7 +769,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.ProductInfoHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.RangeConditionHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RangeConditionHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -821,7 +784,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.RangeConditionHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.RangeHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RangeHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -836,7 +798,6 @@ namespace System public string Unit { get => throw null; set => throw null; } } - // Generated from `System.Net.Http.Headers.RangeItemHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RangeItemHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -848,7 +809,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Http.Headers.RetryConditionHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RetryConditionHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -863,7 +823,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.RetryConditionHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.StringWithQualityHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringWithQualityHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -878,7 +837,6 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Net.Http.Headers.TransferCodingHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TransferCodingHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -893,7 +851,6 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Net.Http.Headers.TransferCodingWithQualityHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TransferCodingWithQualityHeaderValue : System.Net.Http.Headers.TransferCodingHeaderValue, System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -904,7 +861,6 @@ namespace System public static bool TryParse(string input, out System.Net.Http.Headers.TransferCodingWithQualityHeaderValue parsedValue) => throw null; } - // Generated from `System.Net.Http.Headers.ViaHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ViaHeaderValue : System.ICloneable { object System.ICloneable.Clone() => throw null; @@ -922,7 +878,6 @@ namespace System public ViaHeaderValue(string protocolVersion, string receivedBy, string protocolName, string comment) => throw null; } - // Generated from `System.Net.Http.Headers.WarningHeaderValue` in `System.Net.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WarningHeaderValue : System.ICloneable { public string Agent { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.HttpListener.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.HttpListener.cs index c1642a72074..954ca76fba4 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.HttpListener.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.HttpListener.cs @@ -1,16 +1,14 @@ // This file contains auto-generated code. +// Generated from `System.Net.HttpListener, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Net { - // Generated from `System.Net.AuthenticationSchemeSelector` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate System.Net.AuthenticationSchemes AuthenticationSchemeSelector(System.Net.HttpListenerRequest httpRequest); - // Generated from `System.Net.HttpListener` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListener : System.IDisposable { - // Generated from `System.Net.HttpListener+ExtendedProtectionSelector` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy ExtendedProtectionSelector(System.Net.HttpListenerRequest request); @@ -38,14 +36,12 @@ namespace System public bool UnsafeConnectionNtlmAuthentication { get => throw null; set => throw null; } } - // Generated from `System.Net.HttpListenerBasicIdentity` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerBasicIdentity : System.Security.Principal.GenericIdentity { public HttpListenerBasicIdentity(string username, string password) : base(default(System.Security.Principal.GenericIdentity)) => throw null; public virtual string Password { get => throw null; } } - // Generated from `System.Net.HttpListenerContext` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerContext { public System.Threading.Tasks.Task AcceptWebSocketAsync(string subProtocol) => throw null; @@ -57,7 +53,6 @@ namespace System public System.Security.Principal.IPrincipal User { get => throw null; } } - // Generated from `System.Net.HttpListenerException` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerException : System.ComponentModel.Win32Exception { public override int ErrorCode { get => throw null; } @@ -67,7 +62,6 @@ namespace System public HttpListenerException(int errorCode, string message) => throw null; } - // Generated from `System.Net.HttpListenerPrefixCollection` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerPrefixCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public void Add(string uriPrefix) => throw null; @@ -83,7 +77,6 @@ namespace System public bool Remove(string uriPrefix) => throw null; } - // Generated from `System.Net.HttpListenerRequest` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerRequest { public string[] AcceptTypes { get => throw null; } @@ -121,7 +114,6 @@ namespace System public string[] UserLanguages { get => throw null; } } - // Generated from `System.Net.HttpListenerResponse` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerResponse : System.IDisposable { public void Abort() => throw null; @@ -148,7 +140,6 @@ namespace System public string StatusDescription { get => throw null; set => throw null; } } - // Generated from `System.Net.HttpListenerTimeoutManager` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerTimeoutManager { public System.TimeSpan DrainEntityBody { get => throw null; set => throw null; } @@ -161,7 +152,6 @@ namespace System namespace WebSockets { - // Generated from `System.Net.WebSockets.HttpListenerWebSocketContext` in `System.Net.HttpListener, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpListenerWebSocketContext : System.Net.WebSockets.WebSocketContext { public override System.Net.CookieCollection CookieCollection { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Mail.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Mail.cs index abab9ff0953..4abf2e6a759 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Mail.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Mail.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Mail, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Mail { - // Generated from `System.Net.Mail.AlternateView` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AlternateView : System.Net.Mail.AttachmentBase { public AlternateView(System.IO.Stream contentStream) : base(default(System.IO.Stream)) => throw null; @@ -23,7 +23,6 @@ namespace System public System.Net.Mail.LinkedResourceCollection LinkedResources { get => throw null; } } - // Generated from `System.Net.Mail.AlternateViewCollection` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AlternateViewCollection : System.Collections.ObjectModel.Collection, System.IDisposable { protected override void ClearItems() => throw null; @@ -33,7 +32,6 @@ namespace System protected override void SetItem(int index, System.Net.Mail.AlternateView item) => throw null; } - // Generated from `System.Net.Mail.Attachment` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Attachment : System.Net.Mail.AttachmentBase { public Attachment(System.IO.Stream contentStream, System.Net.Mime.ContentType contentType) : base(default(System.IO.Stream)) => throw null; @@ -50,7 +48,6 @@ namespace System public System.Text.Encoding NameEncoding { get => throw null; set => throw null; } } - // Generated from `System.Net.Mail.AttachmentBase` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class AttachmentBase : System.IDisposable { protected AttachmentBase(System.IO.Stream contentStream) => throw null; @@ -67,7 +64,6 @@ namespace System public System.Net.Mime.TransferEncoding TransferEncoding { get => throw null; set => throw null; } } - // Generated from `System.Net.Mail.AttachmentCollection` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class AttachmentCollection : System.Collections.ObjectModel.Collection, System.IDisposable { protected override void ClearItems() => throw null; @@ -77,7 +73,6 @@ namespace System protected override void SetItem(int index, System.Net.Mail.Attachment item) => throw null; } - // Generated from `System.Net.Mail.DeliveryNotificationOptions` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum DeliveryNotificationOptions : int { @@ -88,7 +83,6 @@ namespace System OnSuccess = 1, } - // Generated from `System.Net.Mail.LinkedResource` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class LinkedResource : System.Net.Mail.AttachmentBase { public System.Uri ContentLink { get => throw null; set => throw null; } @@ -103,7 +97,6 @@ namespace System public LinkedResource(string fileName, string mediaType) : base(default(System.IO.Stream)) => throw null; } - // Generated from `System.Net.Mail.LinkedResourceCollection` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class LinkedResourceCollection : System.Collections.ObjectModel.Collection, System.IDisposable { protected override void ClearItems() => throw null; @@ -113,7 +106,6 @@ namespace System protected override void SetItem(int index, System.Net.Mail.LinkedResource item) => throw null; } - // Generated from `System.Net.Mail.MailAddress` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class MailAddress { public string Address { get => throw null; } @@ -131,7 +123,6 @@ namespace System public string User { get => throw null; } } - // Generated from `System.Net.Mail.MailAddressCollection` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class MailAddressCollection : System.Collections.ObjectModel.Collection { public void Add(string addresses) => throw null; @@ -141,7 +132,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Mail.MailMessage` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class MailMessage : System.IDisposable { public System.Net.Mail.AlternateViewCollection AlternateViews { get => throw null; } @@ -171,7 +161,6 @@ namespace System public System.Net.Mail.MailAddressCollection To { get => throw null; } } - // Generated from `System.Net.Mail.MailPriority` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum MailPriority : int { High = 2, @@ -179,10 +168,8 @@ namespace System Normal = 0, } - // Generated from `System.Net.Mail.SendCompletedEventHandler` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void SendCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e); - // Generated from `System.Net.Mail.SmtpClient` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SmtpClient : System.IDisposable { public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get => throw null; } @@ -215,14 +202,12 @@ namespace System public bool UseDefaultCredentials { get => throw null; set => throw null; } } - // Generated from `System.Net.Mail.SmtpDeliveryFormat` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum SmtpDeliveryFormat : int { International = 1, SevenBit = 0, } - // Generated from `System.Net.Mail.SmtpDeliveryMethod` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum SmtpDeliveryMethod : int { Network = 0, @@ -230,7 +215,6 @@ namespace System SpecifiedPickupDirectory = 1, } - // Generated from `System.Net.Mail.SmtpException` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SmtpException : System.Exception, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -244,7 +228,6 @@ namespace System public System.Net.Mail.SmtpStatusCode StatusCode { get => throw null; set => throw null; } } - // Generated from `System.Net.Mail.SmtpFailedRecipientException` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SmtpFailedRecipientException : System.Net.Mail.SmtpException, System.Runtime.Serialization.ISerializable { public string FailedRecipient { get => throw null; } @@ -259,7 +242,6 @@ namespace System public SmtpFailedRecipientException(string message, string failedRecipient, System.Exception innerException) => throw null; } - // Generated from `System.Net.Mail.SmtpFailedRecipientsException` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SmtpFailedRecipientsException : System.Net.Mail.SmtpFailedRecipientException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -272,7 +254,6 @@ namespace System public SmtpFailedRecipientsException(string message, System.Net.Mail.SmtpFailedRecipientException[] innerExceptions) => throw null; } - // Generated from `System.Net.Mail.SmtpStatusCode` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum SmtpStatusCode : int { BadCommandSequence = 503, @@ -305,7 +286,6 @@ namespace System } namespace Mime { - // Generated from `System.Net.Mime.ContentDisposition` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ContentDisposition { public ContentDisposition() => throw null; @@ -323,7 +303,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Mime.ContentType` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ContentType { public string Boundary { get => throw null; set => throw null; } @@ -338,17 +317,14 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Mime.DispositionTypeNames` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class DispositionTypeNames { public const string Attachment = default; public const string Inline = default; } - // Generated from `System.Net.Mime.MediaTypeNames` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class MediaTypeNames { - // Generated from `System.Net.Mime.MediaTypeNames+Application` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Application { public const string Json = default; @@ -361,7 +337,6 @@ namespace System } - // Generated from `System.Net.Mime.MediaTypeNames+Image` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Image { public const string Gif = default; @@ -370,7 +345,6 @@ namespace System } - // Generated from `System.Net.Mime.MediaTypeNames+Text` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Text { public const string Html = default; @@ -382,7 +356,6 @@ namespace System } - // Generated from `System.Net.Mime.TransferEncoding` in `System.Net.Mail, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum TransferEncoding : int { Base64 = 1, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NameResolution.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NameResolution.cs index 3685fa6656c..6224965e325 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NameResolution.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NameResolution.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Net.NameResolution, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Net { - // Generated from `System.Net.Dns` in `System.Net.NameResolution, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Dns { public static System.IAsyncResult BeginGetHostAddresses(string hostNameOrAddress, System.AsyncCallback requestCallback, object state) => throw null; @@ -35,7 +35,6 @@ namespace System public static System.Net.IPHostEntry Resolve(string hostName) => throw null; } - // Generated from `System.Net.IPHostEntry` in `System.Net.NameResolution, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPHostEntry { public System.Net.IPAddress[] AddressList { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NetworkInformation.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NetworkInformation.cs index e0bd215f663..9d5c2758e18 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NetworkInformation.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.NetworkInformation.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.NetworkInformation, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace NetworkInformation { - // Generated from `System.Net.NetworkInformation.DuplicateAddressDetectionState` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DuplicateAddressDetectionState : int { Deprecated = 3, @@ -16,14 +16,12 @@ namespace System Tentative = 1, } - // Generated from `System.Net.NetworkInformation.GatewayIPAddressInformation` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GatewayIPAddressInformation { public abstract System.Net.IPAddress Address { get; } protected GatewayIPAddressInformation() => throw null; } - // Generated from `System.Net.NetworkInformation.GatewayIPAddressInformationCollection` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GatewayIPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.NetworkInformation.GatewayIPAddressInformation address) => throw null; @@ -39,7 +37,6 @@ namespace System public virtual bool Remove(System.Net.NetworkInformation.GatewayIPAddressInformation address) => throw null; } - // Generated from `System.Net.NetworkInformation.IPAddressInformation` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPAddressInformation { public abstract System.Net.IPAddress Address { get; } @@ -48,7 +45,6 @@ namespace System public abstract bool IsTransient { get; } } - // Generated from `System.Net.NetworkInformation.IPAddressInformationCollection` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.NetworkInformation.IPAddressInformation address) => throw null; @@ -63,7 +59,6 @@ namespace System public virtual bool Remove(System.Net.NetworkInformation.IPAddressInformation address) => throw null; } - // Generated from `System.Net.NetworkInformation.IPGlobalProperties` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPGlobalProperties { public virtual System.IAsyncResult BeginGetUnicastAddresses(System.AsyncCallback callback, object state) => throw null; @@ -90,7 +85,6 @@ namespace System public abstract System.Net.NetworkInformation.NetBiosNodeType NodeType { get; } } - // Generated from `System.Net.NetworkInformation.IPGlobalStatistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPGlobalStatistics { public abstract int DefaultTtl { get; } @@ -118,7 +112,6 @@ namespace System public abstract System.Int64 ReceivedPacketsWithUnknownProtocol { get; } } - // Generated from `System.Net.NetworkInformation.IPInterfaceProperties` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPInterfaceProperties { public abstract System.Net.NetworkInformation.IPAddressInformationCollection AnycastAddresses { get; } @@ -136,7 +129,6 @@ namespace System public abstract System.Net.NetworkInformation.IPAddressCollection WinsServersAddresses { get; } } - // Generated from `System.Net.NetworkInformation.IPInterfaceStatistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPInterfaceStatistics { public abstract System.Int64 BytesReceived { get; } @@ -154,7 +146,6 @@ namespace System public abstract System.Int64 UnicastPacketsSent { get; } } - // Generated from `System.Net.NetworkInformation.IPv4InterfaceProperties` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPv4InterfaceProperties { protected IPv4InterfaceProperties() => throw null; @@ -167,7 +158,6 @@ namespace System public abstract bool UsesWins { get; } } - // Generated from `System.Net.NetworkInformation.IPv4InterfaceStatistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPv4InterfaceStatistics { public abstract System.Int64 BytesReceived { get; } @@ -185,7 +175,6 @@ namespace System public abstract System.Int64 UnicastPacketsSent { get; } } - // Generated from `System.Net.NetworkInformation.IPv6InterfaceProperties` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IPv6InterfaceProperties { public virtual System.Int64 GetScopeId(System.Net.NetworkInformation.ScopeLevel scopeLevel) => throw null; @@ -194,7 +183,6 @@ namespace System public abstract int Mtu { get; } } - // Generated from `System.Net.NetworkInformation.IcmpV4Statistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IcmpV4Statistics { public abstract System.Int64 AddressMaskRepliesReceived { get; } @@ -226,7 +214,6 @@ namespace System public abstract System.Int64 TimestampRequestsSent { get; } } - // Generated from `System.Net.NetworkInformation.IcmpV6Statistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IcmpV6Statistics { public abstract System.Int64 DestinationUnreachableMessagesReceived { get; } @@ -264,7 +251,6 @@ namespace System public abstract System.Int64 TimeExceededMessagesSent { get; } } - // Generated from `System.Net.NetworkInformation.MulticastIPAddressInformation` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MulticastIPAddressInformation : System.Net.NetworkInformation.IPAddressInformation { public abstract System.Int64 AddressPreferredLifetime { get; } @@ -276,7 +262,6 @@ namespace System public abstract System.Net.NetworkInformation.SuffixOrigin SuffixOrigin { get; } } - // Generated from `System.Net.NetworkInformation.MulticastIPAddressInformationCollection` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MulticastIPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.NetworkInformation.MulticastIPAddressInformation address) => throw null; @@ -292,7 +277,6 @@ namespace System public virtual bool Remove(System.Net.NetworkInformation.MulticastIPAddressInformation address) => throw null; } - // Generated from `System.Net.NetworkInformation.NetBiosNodeType` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NetBiosNodeType : int { Broadcast = 1, @@ -302,19 +286,15 @@ namespace System Unknown = 0, } - // Generated from `System.Net.NetworkInformation.NetworkAddressChangedEventHandler` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void NetworkAddressChangedEventHandler(object sender, System.EventArgs e); - // Generated from `System.Net.NetworkInformation.NetworkAvailabilityChangedEventHandler` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void NetworkAvailabilityChangedEventHandler(object sender, System.Net.NetworkInformation.NetworkAvailabilityEventArgs e); - // Generated from `System.Net.NetworkInformation.NetworkAvailabilityEventArgs` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetworkAvailabilityEventArgs : System.EventArgs { public bool IsAvailable { get => throw null; } } - // Generated from `System.Net.NetworkInformation.NetworkChange` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetworkChange { public static event System.Net.NetworkInformation.NetworkAddressChangedEventHandler NetworkAddressChanged; @@ -323,7 +303,6 @@ namespace System public static void RegisterNetworkChange(System.Net.NetworkInformation.NetworkChange nc) => throw null; } - // Generated from `System.Net.NetworkInformation.NetworkInformationException` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetworkInformationException : System.ComponentModel.Win32Exception { public override int ErrorCode { get => throw null; } @@ -332,7 +311,6 @@ namespace System public NetworkInformationException(int errorCode) => throw null; } - // Generated from `System.Net.NetworkInformation.NetworkInterface` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class NetworkInterface { public virtual string Description { get => throw null; } @@ -355,14 +333,12 @@ namespace System public virtual bool SupportsMulticast { get => throw null; } } - // Generated from `System.Net.NetworkInformation.NetworkInterfaceComponent` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NetworkInterfaceComponent : int { IPv4 = 0, IPv6 = 1, } - // Generated from `System.Net.NetworkInformation.NetworkInterfaceType` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NetworkInterfaceType : int { AsymmetricDsl = 94, @@ -395,7 +371,6 @@ namespace System Wwanpp2 = 244, } - // Generated from `System.Net.NetworkInformation.OperationalStatus` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OperationalStatus : int { Dormant = 5, @@ -407,7 +382,6 @@ namespace System Up = 1, } - // Generated from `System.Net.NetworkInformation.PhysicalAddress` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PhysicalAddress { public override bool Equals(object comparand) => throw null; @@ -422,7 +396,6 @@ namespace System public static bool TryParse(string address, out System.Net.NetworkInformation.PhysicalAddress value) => throw null; } - // Generated from `System.Net.NetworkInformation.PrefixOrigin` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PrefixOrigin : int { Dhcp = 3, @@ -432,7 +405,6 @@ namespace System WellKnown = 2, } - // Generated from `System.Net.NetworkInformation.ScopeLevel` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ScopeLevel : int { Admin = 4, @@ -445,7 +417,6 @@ namespace System Subnet = 3, } - // Generated from `System.Net.NetworkInformation.SuffixOrigin` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SuffixOrigin : int { LinkLayerAddress = 4, @@ -456,7 +427,6 @@ namespace System WellKnown = 2, } - // Generated from `System.Net.NetworkInformation.TcpConnectionInformation` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TcpConnectionInformation { public abstract System.Net.IPEndPoint LocalEndPoint { get; } @@ -465,7 +435,6 @@ namespace System protected TcpConnectionInformation() => throw null; } - // Generated from `System.Net.NetworkInformation.TcpState` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TcpState : int { CloseWait = 8, @@ -483,7 +452,6 @@ namespace System Unknown = 0, } - // Generated from `System.Net.NetworkInformation.TcpStatistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TcpStatistics { public abstract System.Int64 ConnectionsAccepted { get; } @@ -503,7 +471,6 @@ namespace System protected TcpStatistics() => throw null; } - // Generated from `System.Net.NetworkInformation.UdpStatistics` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class UdpStatistics { public abstract System.Int64 DatagramsReceived { get; } @@ -514,7 +481,6 @@ namespace System protected UdpStatistics() => throw null; } - // Generated from `System.Net.NetworkInformation.UnicastIPAddressInformation` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class UnicastIPAddressInformation : System.Net.NetworkInformation.IPAddressInformation { public abstract System.Int64 AddressPreferredLifetime { get; } @@ -528,7 +494,6 @@ namespace System protected UnicastIPAddressInformation() => throw null; } - // Generated from `System.Net.NetworkInformation.UnicastIPAddressInformationCollection` in `System.Net.NetworkInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnicastIPAddressInformationCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.NetworkInformation.UnicastIPAddressInformation address) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Ping.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Ping.cs index 6452d156200..264f76a3b3a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Ping.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Ping.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Ping, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace NetworkInformation { - // Generated from `System.Net.NetworkInformation.IPStatus` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum IPStatus : int { BadDestination = 11018, @@ -35,7 +35,6 @@ namespace System UnrecognizedNextHeader = 11043, } - // Generated from `System.Net.NetworkInformation.Ping` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Ping : System.ComponentModel.Component { protected override void Dispose(bool disposing) => throw null; @@ -43,10 +42,12 @@ namespace System public Ping() => throw null; public event System.Net.NetworkInformation.PingCompletedEventHandler PingCompleted; public System.Net.NetworkInformation.PingReply Send(System.Net.IPAddress address) => throw null; + public System.Net.NetworkInformation.PingReply Send(System.Net.IPAddress address, System.TimeSpan timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) => throw null; public System.Net.NetworkInformation.PingReply Send(System.Net.IPAddress address, int timeout) => throw null; public System.Net.NetworkInformation.PingReply Send(System.Net.IPAddress address, int timeout, System.Byte[] buffer) => throw null; public System.Net.NetworkInformation.PingReply Send(System.Net.IPAddress address, int timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) => throw null; public System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress) => throw null; + public System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, System.TimeSpan timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) => throw null; public System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, int timeout) => throw null; public System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, int timeout, System.Byte[] buffer) => throw null; public System.Net.NetworkInformation.PingReply Send(string hostNameOrAddress, int timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) => throw null; @@ -69,17 +70,14 @@ namespace System public System.Threading.Tasks.Task SendPingAsync(string hostNameOrAddress, int timeout, System.Byte[] buffer, System.Net.NetworkInformation.PingOptions options) => throw null; } - // Generated from `System.Net.NetworkInformation.PingCompletedEventArgs` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PingCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { internal PingCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; public System.Net.NetworkInformation.PingReply Reply { get => throw null; } } - // Generated from `System.Net.NetworkInformation.PingCompletedEventHandler` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void PingCompletedEventHandler(object sender, System.Net.NetworkInformation.PingCompletedEventArgs e); - // Generated from `System.Net.NetworkInformation.PingException` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PingException : System.InvalidOperationException { protected PingException(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -87,7 +85,6 @@ namespace System public PingException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Net.NetworkInformation.PingOptions` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PingOptions { public bool DontFragment { get => throw null; set => throw null; } @@ -96,7 +93,6 @@ namespace System public int Ttl { get => throw null; set => throw null; } } - // Generated from `System.Net.NetworkInformation.PingReply` in `System.Net.Ping, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PingReply { public System.Net.IPAddress Address { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Primitives.cs index 8cb4c49a179..33e2c3fb7ea 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Primitives.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Net.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Net { - // Generated from `System.Net.AuthenticationSchemes` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AuthenticationSchemes : int { @@ -17,7 +17,6 @@ namespace System Ntlm = 4, } - // Generated from `System.Net.Cookie` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Cookie { public string Comment { get => throw null; set => throw null; } @@ -43,7 +42,6 @@ namespace System public int Version { get => throw null; set => throw null; } } - // Generated from `System.Net.CookieCollection` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CookieCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable { public void Add(System.Net.Cookie cookie) => throw null; @@ -64,7 +62,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Net.CookieContainer` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CookieContainer { public void Add(System.Net.Cookie cookie) => throw null; @@ -87,7 +84,6 @@ namespace System public void SetCookies(System.Uri uri, string cookieHeader) => throw null; } - // Generated from `System.Net.CookieException` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CookieException : System.FormatException, System.Runtime.Serialization.ISerializable { public CookieException() => throw null; @@ -96,7 +92,6 @@ namespace System void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; } - // Generated from `System.Net.CredentialCache` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CredentialCache : System.Collections.IEnumerable, System.Net.ICredentials, System.Net.ICredentialsByHost { public void Add(System.Uri uriPrefix, string authType, System.Net.NetworkCredential cred) => throw null; @@ -111,7 +106,6 @@ namespace System public void Remove(string host, int port, string authenticationType) => throw null; } - // Generated from `System.Net.DecompressionMethods` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DecompressionMethods : int { @@ -122,7 +116,6 @@ namespace System None = 0, } - // Generated from `System.Net.DnsEndPoint` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DnsEndPoint : System.Net.EndPoint { public override System.Net.Sockets.AddressFamily AddressFamily { get => throw null; } @@ -135,7 +128,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.EndPoint` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EndPoint { public virtual System.Net.Sockets.AddressFamily AddressFamily { get => throw null; } @@ -144,7 +136,6 @@ namespace System public virtual System.Net.SocketAddress Serialize() => throw null; } - // Generated from `System.Net.HttpStatusCode` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpStatusCode : int { Accepted = 202, @@ -215,7 +206,6 @@ namespace System VariantAlsoNegotiates = 506, } - // Generated from `System.Net.HttpVersion` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class HttpVersion { public static System.Version Unknown; @@ -225,19 +215,16 @@ namespace System public static System.Version Version30; } - // Generated from `System.Net.ICredentials` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICredentials { System.Net.NetworkCredential GetCredential(System.Uri uri, string authType); } - // Generated from `System.Net.ICredentialsByHost` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICredentialsByHost { System.Net.NetworkCredential GetCredential(string host, int port, string authenticationType); } - // Generated from `System.Net.IPAddress` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPAddress { public System.Int64 Address { get => throw null; set => throw null; } @@ -282,7 +269,6 @@ namespace System public bool TryWriteBytes(System.Span destination, out int bytesWritten) => throw null; } - // Generated from `System.Net.IPEndPoint` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPEndPoint : System.Net.EndPoint { public System.Net.IPAddress Address { get => throw null; set => throw null; } @@ -303,7 +289,6 @@ namespace System public static bool TryParse(string s, out System.Net.IPEndPoint result) => throw null; } - // Generated from `System.Net.IWebProxy` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IWebProxy { System.Net.ICredentials Credentials { get; set; } @@ -311,7 +296,6 @@ namespace System bool IsBypassed(System.Uri host); } - // Generated from `System.Net.NetworkCredential` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetworkCredential : System.Net.ICredentials, System.Net.ICredentialsByHost { public string Domain { get => throw null; set => throw null; } @@ -327,7 +311,6 @@ namespace System public string UserName { get => throw null; set => throw null; } } - // Generated from `System.Net.SocketAddress` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketAddress { public override bool Equals(object comparand) => throw null; @@ -340,7 +323,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.TransportContext` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TransportContext { public abstract System.Security.Authentication.ExtendedProtection.ChannelBinding GetChannelBinding(System.Security.Authentication.ExtendedProtection.ChannelBindingKind kind); @@ -349,7 +331,6 @@ namespace System namespace Cache { - // Generated from `System.Net.Cache.RequestCacheLevel` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RequestCacheLevel : int { BypassCache = 1, @@ -361,7 +342,6 @@ namespace System Revalidate = 4, } - // Generated from `System.Net.Cache.RequestCachePolicy` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RequestCachePolicy { public System.Net.Cache.RequestCacheLevel Level { get => throw null; } @@ -373,7 +353,6 @@ namespace System } namespace NetworkInformation { - // Generated from `System.Net.NetworkInformation.IPAddressCollection` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPAddressCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public virtual void Add(System.Net.IPAddress address) => throw null; @@ -392,7 +371,6 @@ namespace System } namespace Security { - // Generated from `System.Net.Security.AuthenticationLevel` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AuthenticationLevel : int { MutualAuthRequested = 1, @@ -400,7 +378,6 @@ namespace System None = 0, } - // Generated from `System.Net.Security.SslPolicyErrors` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SslPolicyErrors : int { @@ -413,7 +390,6 @@ namespace System } namespace Sockets { - // Generated from `System.Net.Sockets.AddressFamily` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AddressFamily : int { AppleTalk = 16, @@ -451,7 +427,6 @@ namespace System VoiceView = 18, } - // Generated from `System.Net.Sockets.SocketError` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketError : int { AccessDenied = 10013, @@ -503,7 +478,6 @@ namespace System WouldBlock = 10035, } - // Generated from `System.Net.Sockets.SocketException` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketException : System.ComponentModel.Win32Exception { public override int ErrorCode { get => throw null; } @@ -520,7 +494,6 @@ namespace System { namespace Authentication { - // Generated from `System.Security.Authentication.CipherAlgorithmType` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CipherAlgorithmType : int { Aes = 26129, @@ -535,7 +508,6 @@ namespace System TripleDes = 26115, } - // Generated from `System.Security.Authentication.ExchangeAlgorithmType` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ExchangeAlgorithmType : int { DiffieHellman = 43522, @@ -544,7 +516,6 @@ namespace System RsaSign = 9216, } - // Generated from `System.Security.Authentication.HashAlgorithmType` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HashAlgorithmType : int { Md5 = 32771, @@ -555,7 +526,6 @@ namespace System Sha512 = 32782, } - // Generated from `System.Security.Authentication.SslProtocols` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SslProtocols : int { @@ -571,7 +541,6 @@ namespace System namespace ExtendedProtection { - // Generated from `System.Security.Authentication.ExtendedProtection.ChannelBinding` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ChannelBinding : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { protected ChannelBinding() : base(default(bool)) => throw null; @@ -579,7 +548,6 @@ namespace System public abstract int Size { get; } } - // Generated from `System.Security.Authentication.ExtendedProtection.ChannelBindingKind` in `System.Net.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ChannelBindingKind : int { Endpoint = 26, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Quic.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Quic.cs new file mode 100644 index 00000000000..50defa4c18d --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Quic.cs @@ -0,0 +1,147 @@ +// This file contains auto-generated code. +// Generated from `System.Net.Quic, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. + +namespace System +{ + namespace Net + { + namespace Quic + { + [System.Flags] + public enum QuicAbortDirection : int + { + Both = 3, + Read = 1, + Write = 2, + } + + public class QuicClientConnectionOptions : System.Net.Quic.QuicConnectionOptions + { + public System.Net.Security.SslClientAuthenticationOptions ClientAuthenticationOptions { get => throw null; set => throw null; } + public System.Net.IPEndPoint LocalEndPoint { get => throw null; set => throw null; } + public QuicClientConnectionOptions() => throw null; + public System.Net.EndPoint RemoteEndPoint { get => throw null; set => throw null; } + } + + public class QuicConnection : System.IAsyncDisposable + { + public System.Threading.Tasks.ValueTask AcceptInboundStreamAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.ValueTask CloseAsync(System.Int64 errorCode, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask ConnectAsync(System.Net.Quic.QuicClientConnectionOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public static bool IsSupported { get => throw null; } + public System.Net.IPEndPoint LocalEndPoint { get => throw null; } + public System.Net.Security.SslApplicationProtocol NegotiatedApplicationProtocol { get => throw null; } + public System.Threading.Tasks.ValueTask OpenOutboundStreamAsync(System.Net.Quic.QuicStreamType type, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate RemoteCertificate { get => throw null; } + public System.Net.IPEndPoint RemoteEndPoint { get => throw null; } + public override string ToString() => throw null; + } + + public abstract class QuicConnectionOptions + { + public System.Int64 DefaultCloseErrorCode { get => throw null; set => throw null; } + public System.Int64 DefaultStreamErrorCode { get => throw null; set => throw null; } + public System.TimeSpan IdleTimeout { get => throw null; set => throw null; } + public int MaxInboundBidirectionalStreams { get => throw null; set => throw null; } + public int MaxInboundUnidirectionalStreams { get => throw null; set => throw null; } + internal QuicConnectionOptions() => throw null; + } + + public enum QuicError : int + { + AddressInUse = 4, + ConnectionAborted = 2, + ConnectionIdle = 10, + ConnectionRefused = 8, + ConnectionTimeout = 6, + HostUnreachable = 7, + InternalError = 1, + InvalidAddress = 5, + OperationAborted = 12, + ProtocolError = 11, + StreamAborted = 3, + Success = 0, + VersionNegotiationError = 9, + } + + public class QuicException : System.IO.IOException + { + public System.Int64? ApplicationErrorCode { get => throw null; } + public System.Net.Quic.QuicError QuicError { get => throw null; } + public QuicException(System.Net.Quic.QuicError error, System.Int64? applicationErrorCode, string message) => throw null; + } + + public class QuicListener : System.IAsyncDisposable + { + public System.Threading.Tasks.ValueTask AcceptConnectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public static bool IsSupported { get => throw null; } + public static System.Threading.Tasks.ValueTask ListenAsync(System.Net.Quic.QuicListenerOptions options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Net.IPEndPoint LocalEndPoint { get => throw null; } + public override string ToString() => throw null; + } + + public class QuicListenerOptions + { + public System.Collections.Generic.List ApplicationProtocols { get => throw null; set => throw null; } + public System.Func> ConnectionOptionsCallback { get => throw null; set => throw null; } + public int ListenBacklog { get => throw null; set => throw null; } + public System.Net.IPEndPoint ListenEndPoint { get => throw null; set => throw null; } + public QuicListenerOptions() => throw null; + } + + public class QuicServerConnectionOptions : System.Net.Quic.QuicConnectionOptions + { + public QuicServerConnectionOptions() => throw null; + public System.Net.Security.SslServerAuthenticationOptions ServerAuthenticationOptions { get => throw null; set => throw null; } + } + + public class QuicStream : System.IO.Stream + { + public void Abort(System.Net.Quic.QuicAbortDirection abortDirection, System.Int64 errorCode) => throw null; + public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; + public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; + public override bool CanRead { get => throw null; } + public override bool CanSeek { get => throw null; } + public override bool CanTimeout { get => throw null; } + public override bool CanWrite { get => throw null; } + public void CompleteWrites() => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public override int EndRead(System.IAsyncResult asyncResult) => throw null; + public override void EndWrite(System.IAsyncResult asyncResult) => throw null; + public override void Flush() => throw null; + public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Int64 Id { get => throw null; } + public override System.Int64 Length { get => throw null; } + public override System.Int64 Position { get => throw null; set => throw null; } + public override int Read(System.Byte[] buffer, int offset, int count) => throw null; + public override int Read(System.Span buffer) => throw null; + public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override int ReadByte() => throw null; + public override int ReadTimeout { get => throw null; set => throw null; } + public System.Threading.Tasks.Task ReadsClosed { get => throw null; } + public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null; + public override void SetLength(System.Int64 value) => throw null; + public System.Net.Quic.QuicStreamType Type { get => throw null; } + public override void Write(System.Byte[] buffer, int offset, int count) => throw null; + public override void Write(System.ReadOnlySpan buffer) => throw null; + public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, bool completeWrites, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override void WriteByte(System.Byte value) => throw null; + public override int WriteTimeout { get => throw null; set => throw null; } + public System.Threading.Tasks.Task WritesClosed { get => throw null; } + } + + public enum QuicStreamType : int + { + Bidirectional = 1, + Unidirectional = 0, + } + + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Requests.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Requests.cs index 8d80ebcfaee..6e9d1c2ecad 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Requests.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Requests.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Net.Requests, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Net { - // Generated from `System.Net.AuthenticationManager` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AuthenticationManager { public static System.Net.Authorization Authenticate(string challenge, System.Net.WebRequest request, System.Net.ICredentials credentials) => throw null; @@ -17,7 +17,6 @@ namespace System public static void Unregister(string authenticationScheme) => throw null; } - // Generated from `System.Net.Authorization` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Authorization { public Authorization(string token) => throw null; @@ -30,7 +29,6 @@ namespace System public string[] ProtectionRealm { get => throw null; set => throw null; } } - // Generated from `System.Net.FileWebRequest` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileWebRequest : System.Net.WebRequest, System.Runtime.Serialization.ISerializable { public override void Abort() => throw null; @@ -58,7 +56,6 @@ namespace System public override bool UseDefaultCredentials { get => throw null; set => throw null; } } - // Generated from `System.Net.FileWebResponse` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileWebResponse : System.Net.WebResponse, System.Runtime.Serialization.ISerializable { public override void Close() => throw null; @@ -73,7 +70,6 @@ namespace System public override bool SupportsHeaders { get => throw null; } } - // Generated from `System.Net.FtpStatusCode` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FtpStatusCode : int { AccountNeeded = 532, @@ -115,7 +111,6 @@ namespace System Undefined = 0, } - // Generated from `System.Net.FtpWebRequest` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FtpWebRequest : System.Net.WebRequest { public override void Abort() => throw null; @@ -148,7 +143,6 @@ namespace System public bool UsePassive { get => throw null; set => throw null; } } - // Generated from `System.Net.FtpWebResponse` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FtpWebResponse : System.Net.WebResponse, System.IDisposable { public string BannerMessage { get => throw null; } @@ -165,7 +159,6 @@ namespace System public string WelcomeMessage { get => throw null; } } - // Generated from `System.Net.GlobalProxySelection` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GlobalProxySelection { public static System.Net.IWebProxy GetEmptyWebProxy() => throw null; @@ -173,10 +166,8 @@ namespace System public static System.Net.IWebProxy Select { get => throw null; set => throw null; } } - // Generated from `System.Net.HttpContinueDelegate` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void HttpContinueDelegate(int StatusCode, System.Net.WebHeaderCollection httpHeaders); - // Generated from `System.Net.HttpWebRequest` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpWebRequest : System.Net.WebRequest, System.Runtime.Serialization.ISerializable { public override void Abort() => throw null; @@ -246,7 +237,6 @@ namespace System public string UserAgent { get => throw null; set => throw null; } } - // Generated from `System.Net.HttpWebResponse` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpWebResponse : System.Net.WebResponse, System.Runtime.Serialization.ISerializable { public string CharacterSet { get => throw null; } @@ -274,7 +264,6 @@ namespace System public override bool SupportsHeaders { get => throw null; } } - // Generated from `System.Net.IAuthenticationModule` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAuthenticationModule { System.Net.Authorization Authenticate(string challenge, System.Net.WebRequest request, System.Net.ICredentials credentials); @@ -283,19 +272,16 @@ namespace System System.Net.Authorization PreAuthenticate(System.Net.WebRequest request, System.Net.ICredentials credentials); } - // Generated from `System.Net.ICredentialPolicy` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICredentialPolicy { bool ShouldSendCredential(System.Uri challengeUri, System.Net.WebRequest request, System.Net.NetworkCredential credential, System.Net.IAuthenticationModule authenticationModule); } - // Generated from `System.Net.IWebRequestCreate` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IWebRequestCreate { System.Net.WebRequest Create(System.Uri uri); } - // Generated from `System.Net.ProtocolViolationException` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProtocolViolationException : System.InvalidOperationException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -305,7 +291,6 @@ namespace System public ProtocolViolationException(string message) => throw null; } - // Generated from `System.Net.WebException` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebException : System.InvalidOperationException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -320,7 +305,6 @@ namespace System public WebException(string message, System.Net.WebExceptionStatus status) => throw null; } - // Generated from `System.Net.WebExceptionStatus` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WebExceptionStatus : int { CacheEntryNotFound = 18, @@ -346,7 +330,6 @@ namespace System UnknownError = 16, } - // Generated from `System.Net.WebRequest` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class WebRequest : System.MarshalByRefObject, System.Runtime.Serialization.ISerializable { public virtual void Abort() => throw null; @@ -387,10 +370,8 @@ namespace System protected WebRequest(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; } - // Generated from `System.Net.WebRequestMethods` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class WebRequestMethods { - // Generated from `System.Net.WebRequestMethods+File` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class File { public const string DownloadFile = default; @@ -398,7 +379,6 @@ namespace System } - // Generated from `System.Net.WebRequestMethods+Ftp` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Ftp { public const string AppendFile = default; @@ -417,7 +397,6 @@ namespace System } - // Generated from `System.Net.WebRequestMethods+Http` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Http { public const string Connect = default; @@ -431,7 +410,6 @@ namespace System } - // Generated from `System.Net.WebResponse` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class WebResponse : System.MarshalByRefObject, System.IDisposable, System.Runtime.Serialization.ISerializable { public virtual void Close() => throw null; @@ -453,7 +431,6 @@ namespace System namespace Cache { - // Generated from `System.Net.Cache.HttpCacheAgeControl` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpCacheAgeControl : int { MaxAge = 2, @@ -464,7 +441,6 @@ namespace System None = 0, } - // Generated from `System.Net.Cache.HttpRequestCacheLevel` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpRequestCacheLevel : int { BypassCache = 1, @@ -478,7 +454,6 @@ namespace System Revalidate = 4, } - // Generated from `System.Net.Cache.HttpRequestCachePolicy` in `System.Net.Requests, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpRequestCachePolicy : System.Net.Cache.RequestCachePolicy { public System.DateTime CacheSyncDate { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Security.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Security.cs index 11af687997c..120e83ce903 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Security.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Security.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Security, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Security { - // Generated from `System.Net.Security.AuthenticatedStream` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class AuthenticatedStream : System.IO.Stream { protected AuthenticatedStream(System.IO.Stream innerStream, bool leaveInnerStreamOpen) => throw null; @@ -21,14 +21,12 @@ namespace System public bool LeaveInnerStreamOpen { get => throw null; } } - // Generated from `System.Net.Security.CipherSuitesPolicy` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CipherSuitesPolicy { public System.Collections.Generic.IEnumerable AllowedCipherSuites { get => throw null; } public CipherSuitesPolicy(System.Collections.Generic.IEnumerable allowedCipherSuites) => throw null; } - // Generated from `System.Net.Security.EncryptionPolicy` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EncryptionPolicy : int { AllowNoEncryption = 1, @@ -36,10 +34,73 @@ namespace System RequireEncryption = 0, } - // Generated from `System.Net.Security.LocalCertificateSelectionCallback` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Security.Cryptography.X509Certificates.X509Certificate LocalCertificateSelectionCallback(object sender, string targetHost, System.Security.Cryptography.X509Certificates.X509CertificateCollection localCertificates, System.Security.Cryptography.X509Certificates.X509Certificate remoteCertificate, string[] acceptableIssuers); - // Generated from `System.Net.Security.NegotiateStream` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class NegotiateAuthentication : System.IDisposable + { + public void Dispose() => throw null; + public System.Byte[] GetOutgoingBlob(System.ReadOnlySpan incomingBlob, out System.Net.Security.NegotiateAuthenticationStatusCode statusCode) => throw null; + public string GetOutgoingBlob(string incomingBlob, out System.Net.Security.NegotiateAuthenticationStatusCode statusCode) => throw null; + public System.Security.Principal.TokenImpersonationLevel ImpersonationLevel { get => throw null; } + public bool IsAuthenticated { get => throw null; } + public bool IsEncrypted { get => throw null; } + public bool IsMutuallyAuthenticated { get => throw null; } + public bool IsServer { get => throw null; } + public bool IsSigned { get => throw null; } + public NegotiateAuthentication(System.Net.Security.NegotiateAuthenticationClientOptions clientOptions) => throw null; + public NegotiateAuthentication(System.Net.Security.NegotiateAuthenticationServerOptions serverOptions) => throw null; + public string Package { get => throw null; } + public System.Net.Security.ProtectionLevel ProtectionLevel { get => throw null; } + public System.Security.Principal.IIdentity RemoteIdentity { get => throw null; } + public string TargetName { get => throw null; } + public System.Net.Security.NegotiateAuthenticationStatusCode Unwrap(System.ReadOnlySpan input, System.Buffers.IBufferWriter outputWriter, out bool wasEncrypted) => throw null; + public System.Net.Security.NegotiateAuthenticationStatusCode UnwrapInPlace(System.Span input, out int unwrappedOffset, out int unwrappedLength, out bool wasEncrypted) => throw null; + public System.Net.Security.NegotiateAuthenticationStatusCode Wrap(System.ReadOnlySpan input, System.Buffers.IBufferWriter outputWriter, bool requestEncryption, out bool isEncrypted) => throw null; + } + + public class NegotiateAuthenticationClientOptions + { + public System.Security.Principal.TokenImpersonationLevel AllowedImpersonationLevel { get => throw null; set => throw null; } + public System.Security.Authentication.ExtendedProtection.ChannelBinding Binding { get => throw null; set => throw null; } + public System.Net.NetworkCredential Credential { get => throw null; set => throw null; } + public NegotiateAuthenticationClientOptions() => throw null; + public string Package { get => throw null; set => throw null; } + public bool RequireMutualAuthentication { get => throw null; set => throw null; } + public System.Net.Security.ProtectionLevel RequiredProtectionLevel { get => throw null; set => throw null; } + public string TargetName { get => throw null; set => throw null; } + } + + public class NegotiateAuthenticationServerOptions + { + public System.Security.Authentication.ExtendedProtection.ChannelBinding Binding { get => throw null; set => throw null; } + public System.Net.NetworkCredential Credential { get => throw null; set => throw null; } + public NegotiateAuthenticationServerOptions() => throw null; + public string Package { get => throw null; set => throw null; } + public System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy Policy { get => throw null; set => throw null; } + public System.Security.Principal.TokenImpersonationLevel RequiredImpersonationLevel { get => throw null; set => throw null; } + public System.Net.Security.ProtectionLevel RequiredProtectionLevel { get => throw null; set => throw null; } + } + + public enum NegotiateAuthenticationStatusCode : int + { + BadBinding = 3, + Completed = 0, + ContextExpired = 6, + ContinueNeeded = 1, + CredentialsExpired = 7, + GenericFailure = 2, + ImpersonationValidationFailed = 15, + InvalidCredentials = 8, + InvalidToken = 9, + MessageAltered = 5, + OutOfSequence = 12, + QopNotSupported = 11, + SecurityQosFailed = 13, + TargetUnknown = 14, + UnknownCredentials = 10, + Unsupported = 4, + } + public class NegotiateStream : System.Net.Security.AuthenticatedStream { public virtual void AuthenticateAsClient() => throw null; @@ -106,7 +167,6 @@ namespace System public override int WriteTimeout { get => throw null; set => throw null; } } - // Generated from `System.Net.Security.ProtectionLevel` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProtectionLevel : int { EncryptAndSign = 2, @@ -114,16 +174,12 @@ namespace System Sign = 1, } - // Generated from `System.Net.Security.RemoteCertificateValidationCallback` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate bool RemoteCertificateValidationCallback(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors); - // Generated from `System.Net.Security.ServerCertificateSelectionCallback` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Security.Cryptography.X509Certificates.X509Certificate ServerCertificateSelectionCallback(object sender, string hostName); - // Generated from `System.Net.Security.ServerOptionsSelectionCallback` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Threading.Tasks.ValueTask ServerOptionsSelectionCallback(System.Net.Security.SslStream stream, System.Net.Security.SslClientHelloInfo clientHelloInfo, object state, System.Threading.CancellationToken cancellationToken); - // Generated from `System.Net.Security.SslApplicationProtocol` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SslApplicationProtocol : System.IEquatable { public static bool operator !=(System.Net.Security.SslApplicationProtocol left, System.Net.Security.SslApplicationProtocol right) => throw null; @@ -141,18 +197,17 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Net.Security.SslCertificateTrust` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SslCertificateTrust { public static System.Net.Security.SslCertificateTrust CreateForX509Collection(System.Security.Cryptography.X509Certificates.X509Certificate2Collection trustList, bool sendTrustInHandshake = default(bool)) => throw null; public static System.Net.Security.SslCertificateTrust CreateForX509Store(System.Security.Cryptography.X509Certificates.X509Store store, bool sendTrustInHandshake = default(bool)) => throw null; } - // Generated from `System.Net.Security.SslClientAuthenticationOptions` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SslClientAuthenticationOptions { public bool AllowRenegotiation { get => throw null; set => throw null; } public System.Collections.Generic.List ApplicationProtocols { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainPolicy CertificateChainPolicy { get => throw null; set => throw null; } public System.Security.Cryptography.X509Certificates.X509RevocationMode CertificateRevocationCheckMode { get => throw null; set => throw null; } public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get => throw null; set => throw null; } public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get => throw null; set => throw null; } @@ -164,7 +219,6 @@ namespace System public string TargetHost { get => throw null; set => throw null; } } - // Generated from `System.Net.Security.SslClientHelloInfo` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SslClientHelloInfo { public string ServerName { get => throw null; } @@ -172,11 +226,11 @@ namespace System public System.Security.Authentication.SslProtocols SslProtocols { get => throw null; } } - // Generated from `System.Net.Security.SslServerAuthenticationOptions` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SslServerAuthenticationOptions { public bool AllowRenegotiation { get => throw null; set => throw null; } public System.Collections.Generic.List ApplicationProtocols { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainPolicy CertificateChainPolicy { get => throw null; set => throw null; } public System.Security.Cryptography.X509Certificates.X509RevocationMode CertificateRevocationCheckMode { get => throw null; set => throw null; } public System.Net.Security.CipherSuitesPolicy CipherSuitesPolicy { get => throw null; set => throw null; } public bool ClientCertificateRequired { get => throw null; set => throw null; } @@ -189,7 +243,6 @@ namespace System public SslServerAuthenticationOptions() => throw null; } - // Generated from `System.Net.Security.SslStream` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SslStream : System.Net.Security.AuthenticatedStream { public void AuthenticateAsClient(System.Net.Security.SslClientAuthenticationOptions sslClientAuthenticationOptions) => throw null; @@ -272,14 +325,12 @@ namespace System // ERR: Stub generator didn't handle member: ~SslStream } - // Generated from `System.Net.Security.SslStreamCertificateContext` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SslStreamCertificateContext { public static System.Net.Security.SslStreamCertificateContext Create(System.Security.Cryptography.X509Certificates.X509Certificate2 target, System.Security.Cryptography.X509Certificates.X509Certificate2Collection additionalCertificates, bool offline) => throw null; public static System.Net.Security.SslStreamCertificateContext Create(System.Security.Cryptography.X509Certificates.X509Certificate2 target, System.Security.Cryptography.X509Certificates.X509Certificate2Collection additionalCertificates, bool offline = default(bool), System.Net.Security.SslCertificateTrust trust = default(System.Net.Security.SslCertificateTrust)) => throw null; } - // Generated from `System.Net.Security.TlsCipherSuite` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TlsCipherSuite : ushort { TLS_AES_128_CCM_8_SHA256 = 4869, @@ -627,7 +678,6 @@ namespace System { namespace Authentication { - // Generated from `System.Security.Authentication.AuthenticationException` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AuthenticationException : System.SystemException { public AuthenticationException() => throw null; @@ -636,7 +686,6 @@ namespace System public AuthenticationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Security.Authentication.InvalidCredentialException` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidCredentialException : System.Security.Authentication.AuthenticationException { public InvalidCredentialException() => throw null; @@ -647,7 +696,6 @@ namespace System namespace ExtendedProtection { - // Generated from `System.Security.Authentication.ExtendedProtection.ExtendedProtectionPolicy` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExtendedProtectionPolicy : System.Runtime.Serialization.ISerializable { public System.Security.Authentication.ExtendedProtection.ChannelBinding CustomChannelBinding { get => throw null; } @@ -664,7 +712,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Security.Authentication.ExtendedProtection.PolicyEnforcement` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PolicyEnforcement : int { Always = 2, @@ -672,14 +719,12 @@ namespace System WhenSupported = 1, } - // Generated from `System.Security.Authentication.ExtendedProtection.ProtectionScenario` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProtectionScenario : int { TransportSelected = 0, TrustedProxy = 1, } - // Generated from `System.Security.Authentication.ExtendedProtection.ServiceNameCollection` in `System.Net.Security, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ServiceNameCollection : System.Collections.ReadOnlyCollectionBase { public bool Contains(string searchServiceName) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.ServicePoint.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.ServicePoint.cs index 68edda2ada3..650ae555c90 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.ServicePoint.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.ServicePoint.cs @@ -1,13 +1,12 @@ // This file contains auto-generated code. +// Generated from `System.Net.ServicePoint, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Net { - // Generated from `System.Net.BindIPEndPoint` in `System.Net.ServicePoint, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate System.Net.IPEndPoint BindIPEndPoint(System.Net.ServicePoint servicePoint, System.Net.IPEndPoint remoteEndPoint, int retryCount); - // Generated from `System.Net.SecurityProtocolType` in `System.Net.ServicePoint, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum SecurityProtocolType : int { @@ -19,7 +18,6 @@ namespace System Tls13 = 12288, } - // Generated from `System.Net.ServicePoint` in `System.Net.ServicePoint, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ServicePoint { public System.Uri Address { get => throw null; } @@ -41,7 +39,6 @@ namespace System public bool UseNagleAlgorithm { get => throw null; set => throw null; } } - // Generated from `System.Net.ServicePointManager` in `System.Net.ServicePoint, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ServicePointManager { public static bool CheckCertificateRevocationList { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Sockets.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Sockets.cs index 21bd2e0b278..9efd737ad71 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Sockets.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.Sockets.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.Sockets, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Sockets { - // Generated from `System.Net.Sockets.IOControlCode` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum IOControlCode : long { AbsorbRouterAlert = 2550136837, @@ -45,19 +45,18 @@ namespace System UnicastInterface = 2550136838, } - // Generated from `System.Net.Sockets.IPPacketInformation` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct IPPacketInformation + public struct IPPacketInformation : System.IEquatable { public static bool operator !=(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) => throw null; public static bool operator ==(System.Net.Sockets.IPPacketInformation packetInformation1, System.Net.Sockets.IPPacketInformation packetInformation2) => throw null; public System.Net.IPAddress Address { get => throw null; } + public bool Equals(System.Net.Sockets.IPPacketInformation other) => throw null; public override bool Equals(object comparand) => throw null; public override int GetHashCode() => throw null; // Stub generator skipped constructor public int Interface { get => throw null; } } - // Generated from `System.Net.Sockets.IPProtectionLevel` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum IPProtectionLevel : int { EdgeRestricted = 20, @@ -66,7 +65,6 @@ namespace System Unspecified = -1, } - // Generated from `System.Net.Sockets.IPv6MulticastOption` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IPv6MulticastOption { public System.Net.IPAddress Group { get => throw null; set => throw null; } @@ -75,7 +73,6 @@ namespace System public System.Int64 InterfaceIndex { get => throw null; set => throw null; } } - // Generated from `System.Net.Sockets.LingerOption` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LingerOption { public bool Enabled { get => throw null; set => throw null; } @@ -83,7 +80,6 @@ namespace System public int LingerTime { get => throw null; set => throw null; } } - // Generated from `System.Net.Sockets.MulticastOption` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MulticastOption { public System.Net.IPAddress Group { get => throw null; set => throw null; } @@ -94,7 +90,6 @@ namespace System public MulticastOption(System.Net.IPAddress group, int interfaceIndex) => throw null; } - // Generated from `System.Net.Sockets.NetworkStream` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetworkStream : System.IO.Stream { public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -103,6 +98,7 @@ namespace System public override bool CanSeek { get => throw null; } public override bool CanTimeout { get => throw null; } public override bool CanWrite { get => throw null; } + public void Close(System.TimeSpan timeout) => throw null; public void Close(int timeout) => throw null; public virtual bool DataAvailable { get => throw null; } protected override void Dispose(bool disposing) => throw null; @@ -136,7 +132,6 @@ namespace System // ERR: Stub generator didn't handle member: ~NetworkStream } - // Generated from `System.Net.Sockets.ProtocolFamily` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProtocolFamily : int { AppleTalk = 16, @@ -174,7 +169,6 @@ namespace System VoiceView = 18, } - // Generated from `System.Net.Sockets.ProtocolType` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProtocolType : int { Ggp = 3, @@ -204,15 +198,14 @@ namespace System Unspecified = 0, } - // Generated from `System.Net.Sockets.SafeSocketHandle` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeSocketHandle : Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid { + public override bool IsInvalid { get => throw null; } protected override bool ReleaseHandle() => throw null; public SafeSocketHandle() : base(default(bool)) => throw null; public SafeSocketHandle(System.IntPtr preexistingHandle, bool ownsHandle) : base(default(bool)) => throw null; } - // Generated from `System.Net.Sockets.SelectMode` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SelectMode : int { SelectError = 2, @@ -220,7 +213,6 @@ namespace System SelectWrite = 1, } - // Generated from `System.Net.Sockets.SendPacketsElement` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SendPacketsElement { public System.Byte[] Buffer { get => throw null; } @@ -246,7 +238,6 @@ namespace System public SendPacketsElement(string filepath, System.Int64 offset, int count, bool endOfPacket) => throw null; } - // Generated from `System.Net.Sockets.Socket` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Socket : System.IDisposable { public System.Net.Sockets.Socket Accept() => throw null; @@ -338,6 +329,7 @@ namespace System public static bool OSSupportsIPv4 { get => throw null; } public static bool OSSupportsIPv6 { get => throw null; } public static bool OSSupportsUnixDomainSockets { get => throw null; } + public bool Poll(System.TimeSpan timeout, System.Net.Sockets.SelectMode mode) => throw null; public bool Poll(int microSeconds, System.Net.Sockets.SelectMode mode) => throw null; public System.Net.Sockets.ProtocolType ProtocolType { get => throw null; } public int Receive(System.Byte[] buffer) => throw null; @@ -351,8 +343,11 @@ namespace System public int Receive(System.Span buffer) => throw null; public int Receive(System.Span buffer, System.Net.Sockets.SocketFlags socketFlags) => throw null; public int Receive(System.Span buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) => throw null; + public System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer) => throw null; public System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) => throw null; + public System.Threading.Tasks.Task ReceiveAsync(System.Collections.Generic.IList> buffers) => throw null; public System.Threading.Tasks.Task ReceiveAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) => throw null; + public System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool ReceiveAsync(System.Net.Sockets.SocketAsyncEventArgs e) => throw null; public int ReceiveBufferSize { get => throw null; set => throw null; } @@ -362,17 +357,22 @@ namespace System public int ReceiveFrom(System.Byte[] buffer, ref System.Net.EndPoint remoteEP) => throw null; public int ReceiveFrom(System.Span buffer, System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP) => throw null; public int ReceiveFrom(System.Span buffer, ref System.Net.EndPoint remoteEP) => throw null; + public System.Threading.Tasks.Task ReceiveFromAsync(System.ArraySegment buffer, System.Net.EndPoint remoteEndPoint) => throw null; public System.Threading.Tasks.Task ReceiveFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) => throw null; + public System.Threading.Tasks.ValueTask ReceiveFromAsync(System.Memory buffer, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.ValueTask ReceiveFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool ReceiveFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) => throw null; public int ReceiveMessageFrom(System.Byte[] buffer, int offset, int size, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) => throw null; public int ReceiveMessageFrom(System.Span buffer, ref System.Net.Sockets.SocketFlags socketFlags, ref System.Net.EndPoint remoteEP, out System.Net.Sockets.IPPacketInformation ipPacketInformation) => throw null; + public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.EndPoint remoteEndPoint) => throw null; public System.Threading.Tasks.Task ReceiveMessageFromAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint) => throw null; + public System.Threading.Tasks.ValueTask ReceiveMessageFromAsync(System.Memory buffer, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.ValueTask ReceiveMessageFromAsync(System.Memory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEndPoint, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool ReceiveMessageFromAsync(System.Net.Sockets.SocketAsyncEventArgs e) => throw null; public int ReceiveTimeout { get => throw null; set => throw null; } public System.Net.EndPoint RemoteEndPoint { get => throw null; } public System.Net.Sockets.SafeSocketHandle SafeHandle { get => throw null; } + public static void Select(System.Collections.IList checkRead, System.Collections.IList checkWrite, System.Collections.IList checkError, System.TimeSpan timeout) => throw null; public static void Select(System.Collections.IList checkRead, System.Collections.IList checkWrite, System.Collections.IList checkError, int microSeconds) => throw null; public int Send(System.Byte[] buffer) => throw null; public int Send(System.Byte[] buffer, System.Net.Sockets.SocketFlags socketFlags) => throw null; @@ -385,8 +385,11 @@ namespace System public int Send(System.ReadOnlySpan buffer) => throw null; public int Send(System.ReadOnlySpan buffer, System.Net.Sockets.SocketFlags socketFlags) => throw null; public int Send(System.ReadOnlySpan buffer, System.Net.Sockets.SocketFlags socketFlags, out System.Net.Sockets.SocketError errorCode) => throw null; + public System.Threading.Tasks.Task SendAsync(System.ArraySegment buffer) => throw null; public System.Threading.Tasks.Task SendAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags) => throw null; + public System.Threading.Tasks.Task SendAsync(System.Collections.Generic.IList> buffers) => throw null; public System.Threading.Tasks.Task SendAsync(System.Collections.Generic.IList> buffers, System.Net.Sockets.SocketFlags socketFlags) => throw null; + public System.Threading.Tasks.ValueTask SendAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.ValueTask SendAsync(System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool SendAsync(System.Net.Sockets.SocketAsyncEventArgs e) => throw null; public int SendBufferSize { get => throw null; set => throw null; } @@ -403,7 +406,9 @@ namespace System public int SendTo(System.Byte[] buffer, int offset, int size, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) => throw null; public int SendTo(System.ReadOnlySpan buffer, System.Net.EndPoint remoteEP) => throw null; public int SendTo(System.ReadOnlySpan buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) => throw null; + public System.Threading.Tasks.Task SendToAsync(System.ArraySegment buffer, System.Net.EndPoint remoteEP) => throw null; public System.Threading.Tasks.Task SendToAsync(System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) => throw null; + public System.Threading.Tasks.ValueTask SendToAsync(System.ReadOnlyMemory buffer, System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public System.Threading.Tasks.ValueTask SendToAsync(System.ReadOnlyMemory buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public bool SendToAsync(System.Net.Sockets.SocketAsyncEventArgs e) => throw null; public void SetIPProtectionLevel(System.Net.Sockets.IPProtectionLevel level) => throw null; @@ -425,7 +430,6 @@ namespace System // ERR: Stub generator didn't handle member: ~Socket } - // Generated from `System.Net.Sockets.SocketAsyncEventArgs` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SocketAsyncEventArgs : System.EventArgs, System.IDisposable { public System.Net.Sockets.Socket AcceptSocket { get => throw null; set => throw null; } @@ -458,7 +462,6 @@ namespace System // ERR: Stub generator didn't handle member: ~SocketAsyncEventArgs } - // Generated from `System.Net.Sockets.SocketAsyncOperation` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketAsyncOperation : int { Accept = 1, @@ -473,7 +476,6 @@ namespace System SendTo = 9, } - // Generated from `System.Net.Sockets.SocketFlags` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SocketFlags : int { @@ -488,7 +490,6 @@ namespace System Truncated = 256, } - // Generated from `System.Net.Sockets.SocketInformation` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SocketInformation { public System.Net.Sockets.SocketInformationOptions Options { get => throw null; set => throw null; } @@ -496,7 +497,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Net.Sockets.SocketInformationOptions` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SocketInformationOptions : int { @@ -506,7 +506,6 @@ namespace System UseOnlyOverlappedIO = 8, } - // Generated from `System.Net.Sockets.SocketOptionLevel` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketOptionLevel : int { IP = 0, @@ -516,7 +515,6 @@ namespace System Udp = 17, } - // Generated from `System.Net.Sockets.SocketOptionName` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketOptionName : int { AcceptConnection = 2, @@ -570,7 +568,6 @@ namespace System UseLoopback = 64, } - // Generated from `System.Net.Sockets.SocketReceiveFromResult` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SocketReceiveFromResult { public int ReceivedBytes; @@ -578,7 +575,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Net.Sockets.SocketReceiveMessageFromResult` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SocketReceiveMessageFromResult { public System.Net.Sockets.IPPacketInformation PacketInformation; @@ -588,7 +584,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Net.Sockets.SocketShutdown` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketShutdown : int { Both = 2, @@ -596,7 +591,6 @@ namespace System Send = 1, } - // Generated from `System.Net.Sockets.SocketTaskExtensions` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SocketTaskExtensions { public static System.Threading.Tasks.Task AcceptAsync(this System.Net.Sockets.Socket socket) => throw null; @@ -620,7 +614,6 @@ namespace System public static System.Threading.Tasks.Task SendToAsync(this System.Net.Sockets.Socket socket, System.ArraySegment buffer, System.Net.Sockets.SocketFlags socketFlags, System.Net.EndPoint remoteEP) => throw null; } - // Generated from `System.Net.Sockets.SocketType` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SocketType : int { Dgram = 2, @@ -631,7 +624,6 @@ namespace System Unknown = -1, } - // Generated from `System.Net.Sockets.TcpClient` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TcpClient : System.IDisposable { protected bool Active { get => throw null; set => throw null; } @@ -672,7 +664,6 @@ namespace System // ERR: Stub generator didn't handle member: ~TcpClient } - // Generated from `System.Net.Sockets.TcpListener` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TcpListener { public System.Net.Sockets.Socket AcceptSocket() => throw null; @@ -700,7 +691,6 @@ namespace System public TcpListener(int port) => throw null; } - // Generated from `System.Net.Sockets.TransmitFileOptions` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TransmitFileOptions : int { @@ -712,7 +702,6 @@ namespace System WriteBehind = 4, } - // Generated from `System.Net.Sockets.UdpClient` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UdpClient : System.IDisposable { protected bool Active { get => throw null; set => throw null; } @@ -765,7 +754,6 @@ namespace System public UdpClient(string hostname, int port) => throw null; } - // Generated from `System.Net.Sockets.UdpReceiveResult` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct UdpReceiveResult : System.IEquatable { public static bool operator !=(System.Net.Sockets.UdpReceiveResult left, System.Net.Sockets.UdpReceiveResult right) => throw null; @@ -779,9 +767,12 @@ namespace System public UdpReceiveResult(System.Byte[] buffer, System.Net.IPEndPoint remoteEndPoint) => throw null; } - // Generated from `System.Net.Sockets.UnixDomainSocketEndPoint` in `System.Net.Sockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnixDomainSocketEndPoint : System.Net.EndPoint { + public override System.Net.Sockets.AddressFamily AddressFamily { get => throw null; } + public override System.Net.EndPoint Create(System.Net.SocketAddress socketAddress) => throw null; + public override System.Net.SocketAddress Serialize() => throw null; + public override string ToString() => throw null; public UnixDomainSocketEndPoint(string path) => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebClient.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebClient.cs index d0e1d3f02d2..729b6fe0355 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebClient.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebClient.cs @@ -1,20 +1,18 @@ // This file contains auto-generated code. +// Generated from `System.Net.WebClient, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Net { - // Generated from `System.Net.DownloadDataCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DownloadDataCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { internal DownloadDataCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; public System.Byte[] Result { get => throw null; } } - // Generated from `System.Net.DownloadDataCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void DownloadDataCompletedEventHandler(object sender, System.Net.DownloadDataCompletedEventArgs e); - // Generated from `System.Net.DownloadProgressChangedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DownloadProgressChangedEventArgs : System.ComponentModel.ProgressChangedEventArgs { public System.Int64 BytesReceived { get => throw null; } @@ -22,60 +20,48 @@ namespace System public System.Int64 TotalBytesToReceive { get => throw null; } } - // Generated from `System.Net.DownloadProgressChangedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void DownloadProgressChangedEventHandler(object sender, System.Net.DownloadProgressChangedEventArgs e); - // Generated from `System.Net.DownloadStringCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DownloadStringCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { internal DownloadStringCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; public string Result { get => throw null; } } - // Generated from `System.Net.DownloadStringCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void DownloadStringCompletedEventHandler(object sender, System.Net.DownloadStringCompletedEventArgs e); - // Generated from `System.Net.OpenReadCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class OpenReadCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { internal OpenReadCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; public System.IO.Stream Result { get => throw null; } } - // Generated from `System.Net.OpenReadCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void OpenReadCompletedEventHandler(object sender, System.Net.OpenReadCompletedEventArgs e); - // Generated from `System.Net.OpenWriteCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class OpenWriteCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { internal OpenWriteCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; public System.IO.Stream Result { get => throw null; } } - // Generated from `System.Net.OpenWriteCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void OpenWriteCompletedEventHandler(object sender, System.Net.OpenWriteCompletedEventArgs e); - // Generated from `System.Net.UploadDataCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UploadDataCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public System.Byte[] Result { get => throw null; } internal UploadDataCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; } - // Generated from `System.Net.UploadDataCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void UploadDataCompletedEventHandler(object sender, System.Net.UploadDataCompletedEventArgs e); - // Generated from `System.Net.UploadFileCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UploadFileCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public System.Byte[] Result { get => throw null; } internal UploadFileCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; } - // Generated from `System.Net.UploadFileCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void UploadFileCompletedEventHandler(object sender, System.Net.UploadFileCompletedEventArgs e); - // Generated from `System.Net.UploadProgressChangedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UploadProgressChangedEventArgs : System.ComponentModel.ProgressChangedEventArgs { public System.Int64 BytesReceived { get => throw null; } @@ -85,30 +71,24 @@ namespace System internal UploadProgressChangedEventArgs() : base(default(int), default(object)) => throw null; } - // Generated from `System.Net.UploadProgressChangedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void UploadProgressChangedEventHandler(object sender, System.Net.UploadProgressChangedEventArgs e); - // Generated from `System.Net.UploadStringCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UploadStringCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public string Result { get => throw null; } internal UploadStringCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; } - // Generated from `System.Net.UploadStringCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void UploadStringCompletedEventHandler(object sender, System.Net.UploadStringCompletedEventArgs e); - // Generated from `System.Net.UploadValuesCompletedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UploadValuesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { public System.Byte[] Result { get => throw null; } internal UploadValuesCompletedEventArgs() : base(default(System.Exception), default(bool), default(object)) => throw null; } - // Generated from `System.Net.UploadValuesCompletedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void UploadValuesCompletedEventHandler(object sender, System.Net.UploadValuesCompletedEventArgs e); - // Generated from `System.Net.WebClient` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class WebClient : System.ComponentModel.Component { public bool AllowReadStreamBuffering { get => throw null; set => throw null; } @@ -233,14 +213,12 @@ namespace System public event System.Net.WriteStreamClosedEventHandler WriteStreamClosed; } - // Generated from `System.Net.WriteStreamClosedEventArgs` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class WriteStreamClosedEventArgs : System.EventArgs { public System.Exception Error { get => throw null; } public WriteStreamClosedEventArgs() => throw null; } - // Generated from `System.Net.WriteStreamClosedEventHandler` in `System.Net.WebClient, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void WriteStreamClosedEventHandler(object sender, System.Net.WriteStreamClosedEventArgs e); } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebHeaderCollection.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebHeaderCollection.cs index 1eccbd9c0e3..be08fd414a2 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebHeaderCollection.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebHeaderCollection.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Net.WebHeaderCollection, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Net { - // Generated from `System.Net.HttpRequestHeader` in `System.Net.WebHeaderCollection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpRequestHeader : int { Accept = 20, @@ -50,7 +50,6 @@ namespace System Warning = 9, } - // Generated from `System.Net.HttpResponseHeader` in `System.Net.WebHeaderCollection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HttpResponseHeader : int { AcceptRanges = 20, @@ -85,7 +84,6 @@ namespace System WwwAuthenticate = 29, } - // Generated from `System.Net.WebHeaderCollection` in `System.Net.WebHeaderCollection, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebHeaderCollection : System.Collections.Specialized.NameValueCollection, System.Collections.IEnumerable, System.Runtime.Serialization.ISerializable { public void Add(System.Net.HttpRequestHeader header, string value) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebProxy.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebProxy.cs index c271011f461..f5a422f5129 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebProxy.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebProxy.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Net.WebProxy, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Net { - // Generated from `System.Net.IWebProxyScript` in `System.Net.WebProxy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IWebProxyScript { void Close(); @@ -12,7 +12,6 @@ namespace System string Run(string url, string host); } - // Generated from `System.Net.WebProxy` in `System.Net.WebProxy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class WebProxy : System.Net.IWebProxy, System.Runtime.Serialization.ISerializable { public System.Uri Address { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.Client.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.Client.cs index 773f0951c18..486479ac3a5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.Client.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.Client.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.WebSockets.Client, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace WebSockets { - // Generated from `System.Net.WebSockets.ClientWebSocket` in `System.Net.WebSockets.Client, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ClientWebSocket : System.Net.WebSockets.WebSocket { public override void Abort() => throw null; @@ -16,7 +16,10 @@ namespace System public override System.Net.WebSockets.WebSocketCloseStatus? CloseStatus { get => throw null; } public override string CloseStatusDescription { get => throw null; } public System.Threading.Tasks.Task ConnectAsync(System.Uri uri, System.Threading.CancellationToken cancellationToken) => throw null; + public System.Threading.Tasks.Task ConnectAsync(System.Uri uri, System.Net.Http.HttpMessageInvoker invoker, System.Threading.CancellationToken cancellationToken) => throw null; public override void Dispose() => throw null; + public System.Collections.Generic.IReadOnlyDictionary> HttpResponseHeaders { get => throw null; set => throw null; } + public System.Net.HttpStatusCode HttpStatusCode { get => throw null; } public System.Net.WebSockets.ClientWebSocketOptions Options { get => throw null; } public override System.Threading.Tasks.Task ReceiveAsync(System.ArraySegment buffer, System.Threading.CancellationToken cancellationToken) => throw null; public override System.Threading.Tasks.ValueTask ReceiveAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken) => throw null; @@ -26,14 +29,16 @@ namespace System public override string SubProtocol { get => throw null; } } - // Generated from `System.Net.WebSockets.ClientWebSocketOptions` in `System.Net.WebSockets.Client, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ClientWebSocketOptions { public void AddSubProtocol(string subProtocol) => throw null; public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get => throw null; set => throw null; } + public bool CollectHttpResponseDetails { get => throw null; set => throw null; } public System.Net.CookieContainer Cookies { get => throw null; set => throw null; } public System.Net.ICredentials Credentials { get => throw null; set => throw null; } public System.Net.WebSockets.WebSocketDeflateOptions DangerousDeflateOptions { get => throw null; set => throw null; } + public System.Version HttpVersion { get => throw null; set => throw null; } + public System.Net.Http.HttpVersionPolicy HttpVersionPolicy { get => throw null; set => throw null; } public System.TimeSpan KeepAliveInterval { get => throw null; set => throw null; } public System.Net.IWebProxy Proxy { get => throw null; set => throw null; } public System.Net.Security.RemoteCertificateValidationCallback RemoteCertificateValidationCallback { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.cs index f2fb33af811..ba6ea1f8d3b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Net.WebSockets.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Net.WebSockets, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace WebSockets { - // Generated from `System.Net.WebSockets.ValueWebSocketReceiveResult` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueWebSocketReceiveResult { public int Count { get => throw null; } @@ -16,7 +16,6 @@ namespace System public ValueWebSocketReceiveResult(int count, System.Net.WebSockets.WebSocketMessageType messageType, bool endOfMessage) => throw null; } - // Generated from `System.Net.WebSockets.WebSocket` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class WebSocket : System.IDisposable { public abstract void Abort(); @@ -45,7 +44,6 @@ namespace System protected WebSocket() => throw null; } - // Generated from `System.Net.WebSockets.WebSocketCloseStatus` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WebSocketCloseStatus : int { Empty = 1005, @@ -60,7 +58,6 @@ namespace System ProtocolError = 1002, } - // Generated from `System.Net.WebSockets.WebSocketContext` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class WebSocketContext { public abstract System.Net.CookieCollection CookieCollection { get; } @@ -78,7 +75,6 @@ namespace System protected WebSocketContext() => throw null; } - // Generated from `System.Net.WebSockets.WebSocketCreationOptions` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebSocketCreationOptions { public System.Net.WebSockets.WebSocketDeflateOptions DangerousDeflateOptions { get => throw null; set => throw null; } @@ -88,7 +84,6 @@ namespace System public WebSocketCreationOptions() => throw null; } - // Generated from `System.Net.WebSockets.WebSocketDeflateOptions` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebSocketDeflateOptions { public bool ClientContextTakeover { get => throw null; set => throw null; } @@ -98,7 +93,6 @@ namespace System public WebSocketDeflateOptions() => throw null; } - // Generated from `System.Net.WebSockets.WebSocketError` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WebSocketError : int { ConnectionClosedPrematurely = 8, @@ -113,7 +107,6 @@ namespace System UnsupportedVersion = 5, } - // Generated from `System.Net.WebSockets.WebSocketException` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebSocketException : System.ComponentModel.Win32Exception { public override int ErrorCode { get => throw null; } @@ -135,7 +128,6 @@ namespace System public WebSocketException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Net.WebSockets.WebSocketMessageFlags` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum WebSocketMessageFlags : int { @@ -144,7 +136,6 @@ namespace System None = 0, } - // Generated from `System.Net.WebSockets.WebSocketMessageType` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WebSocketMessageType : int { Binary = 1, @@ -152,7 +143,6 @@ namespace System Text = 0, } - // Generated from `System.Net.WebSockets.WebSocketReceiveResult` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WebSocketReceiveResult { public System.Net.WebSockets.WebSocketCloseStatus? CloseStatus { get => throw null; } @@ -164,7 +154,6 @@ namespace System public WebSocketReceiveResult(int count, System.Net.WebSockets.WebSocketMessageType messageType, bool endOfMessage, System.Net.WebSockets.WebSocketCloseStatus? closeStatus, string closeStatusDescription) => throw null; } - // Generated from `System.Net.WebSockets.WebSocketState` in `System.Net.WebSockets, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WebSocketState : int { Aborted = 6, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Numerics.Vectors.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Numerics.Vectors.cs index 471b9950d40..f4f9d830a0b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Numerics.Vectors.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Numerics.Vectors.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Numerics.Vectors, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Numerics { - // Generated from `System.Numerics.Matrix3x2` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Matrix3x2 : System.IEquatable { public static bool operator !=(System.Numerics.Matrix3x2 value1, System.Numerics.Matrix3x2 value2) => throw null; @@ -34,6 +34,7 @@ namespace System public static System.Numerics.Matrix3x2 Identity { get => throw null; } public static bool Invert(System.Numerics.Matrix3x2 matrix, out System.Numerics.Matrix3x2 result) => throw null; public bool IsIdentity { get => throw null; } + public float this[int row, int column] { get => throw null; set => throw null; } public static System.Numerics.Matrix3x2 Lerp(System.Numerics.Matrix3x2 matrix1, System.Numerics.Matrix3x2 matrix2, float amount) => throw null; public float M11; public float M12; @@ -51,7 +52,6 @@ namespace System public System.Numerics.Vector2 Translation { get => throw null; set => throw null; } } - // Generated from `System.Numerics.Matrix4x4` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Matrix4x4 : System.IEquatable { public static bool operator !=(System.Numerics.Matrix4x4 value1, System.Numerics.Matrix4x4 value2) => throw null; @@ -98,6 +98,7 @@ namespace System public static System.Numerics.Matrix4x4 Identity { get => throw null; } public static bool Invert(System.Numerics.Matrix4x4 matrix, out System.Numerics.Matrix4x4 result) => throw null; public bool IsIdentity { get => throw null; } + public float this[int row, int column] { get => throw null; set => throw null; } public static System.Numerics.Matrix4x4 Lerp(System.Numerics.Matrix4x4 matrix1, System.Numerics.Matrix4x4 matrix2, float amount) => throw null; public float M11; public float M12; @@ -128,7 +129,6 @@ namespace System public static System.Numerics.Matrix4x4 Transpose(System.Numerics.Matrix4x4 matrix) => throw null; } - // Generated from `System.Numerics.Plane` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Plane : System.IEquatable { public static bool operator !=(System.Numerics.Plane value1, System.Numerics.Plane value2) => throw null; @@ -152,7 +152,6 @@ namespace System public static System.Numerics.Plane Transform(System.Numerics.Plane plane, System.Numerics.Quaternion rotation) => throw null; } - // Generated from `System.Numerics.Quaternion` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Quaternion : System.IEquatable { public static bool operator !=(System.Numerics.Quaternion value1, System.Numerics.Quaternion value2) => throw null; @@ -177,6 +176,7 @@ namespace System public static System.Numerics.Quaternion Identity { get => throw null; } public static System.Numerics.Quaternion Inverse(System.Numerics.Quaternion value) => throw null; public bool IsIdentity { get => throw null; } + public float this[int index] { get => throw null; set => throw null; } public float Length() => throw null; public float LengthSquared() => throw null; public static System.Numerics.Quaternion Lerp(System.Numerics.Quaternion quaternion1, System.Numerics.Quaternion quaternion2, float amount) => throw null; @@ -194,9 +194,9 @@ namespace System public float X; public float Y; public float Z; + public static System.Numerics.Quaternion Zero { get => throw null; } } - // Generated from `System.Numerics.Vector` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Vector { public static System.Numerics.Vector Abs(System.Numerics.Vector value) where T : struct => throw null; @@ -284,6 +284,31 @@ namespace System public static System.Numerics.Vector Narrow(System.Numerics.Vector low, System.Numerics.Vector high) => throw null; public static System.Numerics.Vector Negate(System.Numerics.Vector value) where T : struct => throw null; public static System.Numerics.Vector OnesComplement(System.Numerics.Vector value) where T : struct => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftLeft(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightArithmetic(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; + public static System.Numerics.Vector ShiftRightLogical(System.Numerics.Vector value, int shiftCount) => throw null; public static System.Numerics.Vector SquareRoot(System.Numerics.Vector value) where T : struct => throw null; public static System.Numerics.Vector Subtract(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct => throw null; public static T Sum(System.Numerics.Vector value) where T : struct => throw null; @@ -297,7 +322,6 @@ namespace System public static System.Numerics.Vector Xor(System.Numerics.Vector left, System.Numerics.Vector right) where T : struct => throw null; } - // Generated from `System.Numerics.Vector2` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Vector2 : System.IEquatable, System.IFormattable { public static bool operator !=(System.Numerics.Vector2 left, System.Numerics.Vector2 right) => throw null; @@ -324,6 +348,7 @@ namespace System public bool Equals(System.Numerics.Vector2 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public float this[int index] { get => throw null; set => throw null; } public float Length() => throw null; public float LengthSquared() => throw null; public static System.Numerics.Vector2 Lerp(System.Numerics.Vector2 value1, System.Numerics.Vector2 value2, float amount) => throw null; @@ -358,7 +383,6 @@ namespace System public static System.Numerics.Vector2 Zero { get => throw null; } } - // Generated from `System.Numerics.Vector3` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Vector3 : System.IEquatable, System.IFormattable { public static bool operator !=(System.Numerics.Vector3 left, System.Numerics.Vector3 right) => throw null; @@ -386,6 +410,7 @@ namespace System public bool Equals(System.Numerics.Vector3 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public float this[int index] { get => throw null; set => throw null; } public float Length() => throw null; public float LengthSquared() => throw null; public static System.Numerics.Vector3 Lerp(System.Numerics.Vector3 value1, System.Numerics.Vector3 value2, float amount) => throw null; @@ -421,7 +446,6 @@ namespace System public static System.Numerics.Vector3 Zero { get => throw null; } } - // Generated from `System.Numerics.Vector4` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Vector4 : System.IEquatable, System.IFormattable { public static bool operator !=(System.Numerics.Vector4 left, System.Numerics.Vector4 right) => throw null; @@ -448,6 +472,7 @@ namespace System public bool Equals(System.Numerics.Vector4 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public float this[int index] { get => throw null; set => throw null; } public float Length() => throw null; public float LengthSquared() => throw null; public static System.Numerics.Vector4 Lerp(System.Numerics.Vector4 value1, System.Numerics.Vector4 value2, float amount) => throw null; @@ -488,7 +513,6 @@ namespace System public static System.Numerics.Vector4 Zero { get => throw null; } } - // Generated from `System.Numerics.Vector<>` in `System.Numerics.Vectors, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Vector : System.IEquatable>, System.IFormattable where T : struct { public static bool operator !=(System.Numerics.Vector left, System.Numerics.Vector right) => throw null; @@ -509,6 +533,7 @@ namespace System public bool Equals(System.Numerics.Vector other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public static bool IsSupported { get => throw null; } public T this[int index] { get => throw null; } public static System.Numerics.Vector One { get => throw null; } public override string ToString() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ObjectModel.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ObjectModel.cs index 72da9bbf4c0..1bad4e4e0dc 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ObjectModel.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.ObjectModel.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.ObjectModel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace ObjectModel { - // Generated from `System.Collections.ObjectModel.KeyedCollection<,>` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class KeyedCollection : System.Collections.ObjectModel.Collection { protected void ChangeItemKey(TItem item, TKey newKey) => throw null; @@ -26,7 +26,6 @@ namespace System public bool TryGetValue(TKey key, out TItem item) => throw null; } - // Generated from `System.Collections.ObjectModel.ObservableCollection<>` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObservableCollection : System.Collections.ObjectModel.Collection, System.Collections.Specialized.INotifyCollectionChanged, System.ComponentModel.INotifyPropertyChanged { protected System.IDisposable BlockReentrancy() => throw null; @@ -47,84 +46,6 @@ namespace System protected override void SetItem(int index, T item) => throw null; } - // Generated from `System.Collections.ObjectModel.ReadOnlyDictionary<,>` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ReadOnlyDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable - { - // Generated from `System.Collections.ObjectModel.ReadOnlyDictionary<,>+KeyCollection` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class KeyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable - { - void System.Collections.Generic.ICollection.Add(TKey item) => throw null; - void System.Collections.Generic.ICollection.Clear() => throw null; - bool System.Collections.Generic.ICollection.Contains(TKey item) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(TKey[] array, int arrayIndex) => throw null; - public int Count { get => throw null; } - public System.Collections.Generic.IEnumerator GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } - bool System.Collections.ICollection.IsSynchronized { get => throw null; } - bool System.Collections.Generic.ICollection.Remove(TKey item) => throw null; - object System.Collections.ICollection.SyncRoot { get => throw null; } - } - - - // Generated from `System.Collections.ObjectModel.ReadOnlyDictionary<,>+ValueCollection` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ValueCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable - { - void System.Collections.Generic.ICollection.Add(TValue item) => throw null; - void System.Collections.Generic.ICollection.Clear() => throw null; - bool System.Collections.Generic.ICollection.Contains(TValue item) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(TValue[] array, int arrayIndex) => throw null; - public int Count { get => throw null; } - public System.Collections.Generic.IEnumerator GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } - bool System.Collections.ICollection.IsSynchronized { get => throw null; } - bool System.Collections.Generic.ICollection.Remove(TValue item) => throw null; - object System.Collections.ICollection.SyncRoot { get => throw null; } - } - - - void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null; - void System.Collections.Generic.IDictionary.Add(TKey key, TValue value) => throw null; - void System.Collections.IDictionary.Add(object key, object value) => throw null; - void System.Collections.Generic.ICollection>.Clear() => throw null; - void System.Collections.IDictionary.Clear() => throw null; - bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair item) => throw null; - bool System.Collections.IDictionary.Contains(object key) => throw null; - public bool ContainsKey(TKey key) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; - public int Count { get => throw null; } - protected System.Collections.Generic.IDictionary Dictionary { get => throw null; } - public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; - System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - bool System.Collections.IDictionary.IsFixedSize { get => throw null; } - bool System.Collections.Generic.ICollection>.IsReadOnly { get => throw null; } - bool System.Collections.IDictionary.IsReadOnly { get => throw null; } - bool System.Collections.ICollection.IsSynchronized { get => throw null; } - public TValue this[TKey key] { get => throw null; } - TValue System.Collections.Generic.IDictionary.this[TKey key] { get => throw null; set => throw null; } - object System.Collections.IDictionary.this[object key] { get => throw null; set => throw null; } - public System.Collections.ObjectModel.ReadOnlyDictionary.KeyCollection Keys { get => throw null; } - System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Keys { get => throw null; } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get => throw null; } - System.Collections.ICollection System.Collections.IDictionary.Keys { get => throw null; } - public ReadOnlyDictionary(System.Collections.Generic.IDictionary dictionary) => throw null; - bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair item) => throw null; - bool System.Collections.Generic.IDictionary.Remove(TKey key) => throw null; - void System.Collections.IDictionary.Remove(object key) => throw null; - object System.Collections.ICollection.SyncRoot { get => throw null; } - public bool TryGetValue(TKey key, out TValue value) => throw null; - public System.Collections.ObjectModel.ReadOnlyDictionary.ValueCollection Values { get => throw null; } - System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; } - System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } - System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } - } - - // Generated from `System.Collections.ObjectModel.ReadOnlyObservableCollection<>` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyObservableCollection : System.Collections.ObjectModel.ReadOnlyCollection, System.Collections.Specialized.INotifyCollectionChanged, System.ComponentModel.INotifyPropertyChanged { protected virtual event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged; @@ -139,13 +60,11 @@ namespace System } namespace Specialized { - // Generated from `System.Collections.Specialized.INotifyCollectionChanged` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INotifyCollectionChanged { event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged; } - // Generated from `System.Collections.Specialized.NotifyCollectionChangedAction` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NotifyCollectionChangedAction : int { Add = 0, @@ -155,7 +74,6 @@ namespace System Reset = 4, } - // Generated from `System.Collections.Specialized.NotifyCollectionChangedEventArgs` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotifyCollectionChangedEventArgs : System.EventArgs { public System.Collections.Specialized.NotifyCollectionChangedAction Action { get => throw null; } @@ -176,21 +94,18 @@ namespace System public int OldStartingIndex { get => throw null; } } - // Generated from `System.Collections.Specialized.NotifyCollectionChangedEventHandler` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void NotifyCollectionChangedEventHandler(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e); } } namespace ComponentModel { - // Generated from `System.ComponentModel.DataErrorsChangedEventArgs` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataErrorsChangedEventArgs : System.EventArgs { public DataErrorsChangedEventArgs(string propertyName) => throw null; public virtual string PropertyName { get => throw null; } } - // Generated from `System.ComponentModel.INotifyDataErrorInfo` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INotifyDataErrorInfo { event System.EventHandler ErrorsChanged; @@ -198,39 +113,32 @@ namespace System bool HasErrors { get; } } - // Generated from `System.ComponentModel.INotifyPropertyChanged` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INotifyPropertyChanged { event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; } - // Generated from `System.ComponentModel.INotifyPropertyChanging` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INotifyPropertyChanging { event System.ComponentModel.PropertyChangingEventHandler PropertyChanging; } - // Generated from `System.ComponentModel.PropertyChangedEventArgs` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyChangedEventArgs : System.EventArgs { public PropertyChangedEventArgs(string propertyName) => throw null; public virtual string PropertyName { get => throw null; } } - // Generated from `System.ComponentModel.PropertyChangedEventHandler` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e); - // Generated from `System.ComponentModel.PropertyChangingEventArgs` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyChangingEventArgs : System.EventArgs { public PropertyChangingEventArgs(string propertyName) => throw null; public virtual string PropertyName { get => throw null; } } - // Generated from `System.ComponentModel.PropertyChangingEventHandler` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void PropertyChangingEventHandler(object sender, System.ComponentModel.PropertyChangingEventArgs e); - // Generated from `System.ComponentModel.TypeConverterAttribute` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeConverterAttribute : System.Attribute { public string ConverterTypeName { get => throw null; } @@ -242,7 +150,6 @@ namespace System public TypeConverterAttribute(string typeName) => throw null; } - // Generated from `System.ComponentModel.TypeDescriptionProviderAttribute` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeDescriptionProviderAttribute : System.Attribute { public TypeDescriptionProviderAttribute(System.Type type) => throw null; @@ -253,7 +160,6 @@ namespace System } namespace Reflection { - // Generated from `System.Reflection.ICustomTypeProvider` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomTypeProvider { System.Type GetCustomType(); @@ -264,7 +170,6 @@ namespace System { namespace Input { - // Generated from `System.Windows.Input.ICommand` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICommand { bool CanExecute(object parameter); @@ -275,7 +180,6 @@ namespace System } namespace Markup { - // Generated from `System.Windows.Markup.ValueSerializerAttribute` in `System.ObjectModel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValueSerializerAttribute : System.Attribute { public ValueSerializerAttribute(System.Type valueSerializerType) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.DispatchProxy.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.DispatchProxy.cs index f4c2140fe5d..e22c1633dc8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.DispatchProxy.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.DispatchProxy.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.DispatchProxy, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Reflection { - // Generated from `System.Reflection.DispatchProxy` in `System.Reflection.DispatchProxy, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DispatchProxy { public static T Create() where TProxy : System.Reflection.DispatchProxy => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.ILGeneration.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.ILGeneration.cs index d6812f924d0..dc68bdfcac8 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.ILGeneration.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.ILGeneration.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.Emit.ILGeneration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Emit { - // Generated from `System.Reflection.Emit.CustomAttributeBuilder` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CustomAttributeBuilder { public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs) => throw null; @@ -15,7 +15,6 @@ namespace System public CustomAttributeBuilder(System.Reflection.ConstructorInfo con, object[] constructorArgs, System.Reflection.PropertyInfo[] namedProperties, object[] propertyValues, System.Reflection.FieldInfo[] namedFields, object[] fieldValues) => throw null; } - // Generated from `System.Reflection.Emit.ILGenerator` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ILGenerator { public virtual void BeginCatchBlock(System.Type exceptionType) => throw null; @@ -58,7 +57,6 @@ namespace System public virtual void UsingNamespace(string usingNamespace) => throw null; } - // Generated from `System.Reflection.Emit.Label` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Label : System.IEquatable { public static bool operator !=(System.Reflection.Emit.Label a, System.Reflection.Emit.Label b) => throw null; @@ -69,7 +67,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Emit.LocalBuilder` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LocalBuilder : System.Reflection.LocalVariableInfo { public override bool IsPinned { get => throw null; } @@ -77,7 +74,6 @@ namespace System public override System.Type LocalType { get => throw null; } } - // Generated from `System.Reflection.Emit.ParameterBuilder` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParameterBuilder { public virtual int Attributes { get => throw null; } @@ -91,7 +87,6 @@ namespace System public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) => throw null; } - // Generated from `System.Reflection.Emit.SignatureHelper` in `System.Reflection.Emit.ILGeneration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SignatureHelper { public void AddArgument(System.Type clsArgument) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.Lightweight.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.Lightweight.cs index e696e84576d..0664619a85e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.Lightweight.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.Lightweight.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.Emit.Lightweight, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Emit { - // Generated from `System.Reflection.Emit.DynamicILInfo` in `System.Reflection.Emit.Lightweight, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicILInfo { public System.Reflection.Emit.DynamicMethod DynamicMethod { get => throw null; } @@ -26,7 +26,6 @@ namespace System unsafe public void SetLocalSignature(System.Byte* localSignature, int signatureSize) => throw null; } - // Generated from `System.Reflection.Emit.DynamicMethod` in `System.Reflection.Emit.Lightweight, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicMethod : System.Reflection.MethodInfo { public override System.Reflection.MethodAttributes Attributes { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.cs index 7849ca4750f..abf531b9ec5 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Emit.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.Emit, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Emit { - // Generated from `System.Reflection.Emit.AssemblyBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyBuilder : System.Reflection.Assembly { public override string CodeBase { get => throw null; } @@ -47,7 +47,6 @@ namespace System public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) => throw null; } - // Generated from `System.Reflection.Emit.AssemblyBuilderAccess` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AssemblyBuilderAccess : int { @@ -55,7 +54,6 @@ namespace System RunAndCollect = 9, } - // Generated from `System.Reflection.Emit.ConstructorBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConstructorBuilder : System.Reflection.ConstructorInfo { public override System.Reflection.MethodAttributes Attributes { get => throw null; } @@ -83,7 +81,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.Emit.EnumBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumBuilder : System.Reflection.TypeInfo { public override System.Reflection.Assembly Assembly { get => throw null; } @@ -147,7 +144,6 @@ namespace System public override System.Type UnderlyingSystemType { get => throw null; } } - // Generated from `System.Reflection.Emit.EventBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventBuilder { public void AddOtherMethod(System.Reflection.Emit.MethodBuilder mdBuilder) => throw null; @@ -158,7 +154,6 @@ namespace System public void SetRemoveOnMethod(System.Reflection.Emit.MethodBuilder mdBuilder) => throw null; } - // Generated from `System.Reflection.Emit.FieldBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FieldBuilder : System.Reflection.FieldInfo { public override System.Reflection.FieldAttributes Attributes { get => throw null; } @@ -180,7 +175,6 @@ namespace System public override void SetValue(object obj, object val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Globalization.CultureInfo culture) => throw null; } - // Generated from `System.Reflection.Emit.GenericTypeParameterBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GenericTypeParameterBuilder : System.Reflection.TypeInfo { public override System.Reflection.Assembly Assembly { get => throw null; } @@ -258,7 +252,6 @@ namespace System public override System.Type UnderlyingSystemType { get => throw null; } } - // Generated from `System.Reflection.Emit.MethodBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodBuilder : System.Reflection.MethodInfo { public override System.Reflection.MethodAttributes Attributes { get => throw null; } @@ -304,7 +297,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.Emit.ModuleBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ModuleBuilder : System.Reflection.Module { public override System.Reflection.Assembly Assembly { get => throw null; } @@ -357,7 +349,6 @@ namespace System public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) => throw null; } - // Generated from `System.Reflection.Emit.PropertyBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PropertyBuilder : System.Reflection.PropertyInfo { public void AddOtherMethod(System.Reflection.Emit.MethodBuilder mdBuilder) => throw null; @@ -387,7 +378,6 @@ namespace System public override void SetValue(object obj, object value, object[] index) => throw null; } - // Generated from `System.Reflection.Emit.TypeBuilder` in `System.Reflection.Emit, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeBuilder : System.Reflection.TypeInfo { public void AddInterfaceImplementation(System.Type interfaceType) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Metadata.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Metadata.cs index 6f33defb3ab..7b3a400c18d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Metadata.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Metadata.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.Metadata, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Reflection { - // Generated from `System.Reflection.AssemblyFlags` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AssemblyFlags : int { @@ -16,7 +16,6 @@ namespace System WindowsRuntime = 512, } - // Generated from `System.Reflection.AssemblyHashAlgorithm` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AssemblyHashAlgorithm : int { MD5 = 32771, @@ -27,7 +26,6 @@ namespace System Sha512 = 32782, } - // Generated from `System.Reflection.DeclarativeSecurityAction` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DeclarativeSecurityAction : short { Assert = 3, @@ -42,7 +40,6 @@ namespace System RequestRefuse = 10, } - // Generated from `System.Reflection.ManifestResourceAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ManifestResourceAttributes : int { @@ -51,7 +48,6 @@ namespace System VisibilityMask = 7, } - // Generated from `System.Reflection.MethodImportAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MethodImportAttributes : short { @@ -76,7 +72,6 @@ namespace System ThrowOnUnmappableCharMask = 12288, } - // Generated from `System.Reflection.MethodSemanticsAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MethodSemanticsAttributes : int { @@ -90,7 +85,6 @@ namespace System namespace Metadata { - // Generated from `System.Reflection.Metadata.ArrayShape` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ArrayShape { // Stub generator skipped constructor @@ -100,7 +94,6 @@ namespace System public System.Collections.Immutable.ImmutableArray Sizes { get => throw null; } } - // Generated from `System.Reflection.Metadata.AssemblyDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyDefinition { // Stub generator skipped constructor @@ -115,7 +108,6 @@ namespace System public System.Version Version { get => throw null; } } - // Generated from `System.Reflection.Metadata.AssemblyDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.AssemblyDefinitionHandle left, System.Reflection.Metadata.AssemblyDefinitionHandle right) => throw null; @@ -131,7 +123,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.AssemblyDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.AssemblyFile` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyFile { // Stub generator skipped constructor @@ -141,7 +132,6 @@ namespace System public System.Reflection.Metadata.StringHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.AssemblyFileHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyFileHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.AssemblyFileHandle left, System.Reflection.Metadata.AssemblyFileHandle right) => throw null; @@ -157,10 +147,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.AssemblyFileHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.AssemblyFileHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyFileHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.AssemblyFileHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.AssemblyFileHandle Current { get => throw null; } @@ -179,7 +167,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.AssemblyReference` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyReference { // Stub generator skipped constructor @@ -193,7 +180,6 @@ namespace System public System.Version Version { get => throw null; } } - // Generated from `System.Reflection.Metadata.AssemblyReferenceHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyReferenceHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.AssemblyReferenceHandle left, System.Reflection.Metadata.AssemblyReferenceHandle right) => throw null; @@ -209,10 +195,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.AssemblyReferenceHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.AssemblyReferenceHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssemblyReferenceHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.AssemblyReferenceHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.AssemblyReferenceHandle Current { get => throw null; } @@ -231,7 +215,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.Blob` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Blob { // Stub generator skipped constructor @@ -240,10 +223,8 @@ namespace System public int Length { get => throw null; } } - // Generated from `System.Reflection.Metadata.BlobBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BlobBuilder { - // Generated from `System.Reflection.Metadata.BlobBuilder+Blobs` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Blobs : System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerator, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable { // Stub generator skipped constructor @@ -316,7 +297,6 @@ namespace System public void WriteUserString(string value) => throw null; } - // Generated from `System.Reflection.Metadata.BlobContentId` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BlobContentId : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.BlobContentId left, System.Reflection.Metadata.BlobContentId right) => throw null; @@ -336,7 +316,6 @@ namespace System public System.UInt32 Stamp { get => throw null; } } - // Generated from `System.Reflection.Metadata.BlobHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BlobHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.BlobHandle left, System.Reflection.Metadata.BlobHandle right) => throw null; @@ -350,7 +329,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.BlobHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.BlobReader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BlobReader { public void Align(System.Byte alignment) => throw null; @@ -395,7 +373,6 @@ namespace System public bool TryReadCompressedSignedInteger(out int value) => throw null; } - // Generated from `System.Reflection.Metadata.BlobWriter` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BlobWriter { public void Align(int alignment) => throw null; @@ -452,7 +429,6 @@ namespace System public void WriteUserString(string value) => throw null; } - // Generated from `System.Reflection.Metadata.Constant` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Constant { // Stub generator skipped constructor @@ -461,7 +437,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Value { get => throw null; } } - // Generated from `System.Reflection.Metadata.ConstantHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConstantHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ConstantHandle left, System.Reflection.Metadata.ConstantHandle right) => throw null; @@ -477,7 +452,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ConstantHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ConstantTypeCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConstantTypeCode : byte { Boolean = 2, @@ -497,7 +471,6 @@ namespace System UInt64 = 11, } - // Generated from `System.Reflection.Metadata.CustomAttribute` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttribute { public System.Reflection.Metadata.EntityHandle Constructor { get => throw null; } @@ -507,7 +480,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Value { get => throw null; } } - // Generated from `System.Reflection.Metadata.CustomAttributeHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.CustomAttributeHandle left, System.Reflection.Metadata.CustomAttributeHandle right) => throw null; @@ -523,10 +495,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.CustomAttributeHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.CustomAttributeHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.CustomAttributeHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.CustomAttributeHandle Current { get => throw null; } @@ -545,7 +515,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.CustomAttributeNamedArgument<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeNamedArgument { // Stub generator skipped constructor @@ -556,14 +525,12 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Reflection.Metadata.CustomAttributeNamedArgumentKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CustomAttributeNamedArgumentKind : byte { Field = 83, Property = 84, } - // Generated from `System.Reflection.Metadata.CustomAttributeTypedArgument<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeTypedArgument { // Stub generator skipped constructor @@ -572,7 +539,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Reflection.Metadata.CustomAttributeValue<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeValue { // Stub generator skipped constructor @@ -581,7 +547,6 @@ namespace System public System.Collections.Immutable.ImmutableArray> NamedArguments { get => throw null; } } - // Generated from `System.Reflection.Metadata.CustomDebugInformation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomDebugInformation { // Stub generator skipped constructor @@ -590,7 +555,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Value { get => throw null; } } - // Generated from `System.Reflection.Metadata.CustomDebugInformationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomDebugInformationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.CustomDebugInformationHandle left, System.Reflection.Metadata.CustomDebugInformationHandle right) => throw null; @@ -606,10 +570,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.CustomDebugInformationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.CustomDebugInformationHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomDebugInformationHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.CustomDebugInformationHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.CustomDebugInformationHandle Current { get => throw null; } @@ -628,7 +590,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.DebugMetadataHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebugMetadataHeader { public System.Reflection.Metadata.MethodDefinitionHandle EntryPoint { get => throw null; } @@ -636,7 +597,6 @@ namespace System public int IdStartOffset { get => throw null; } } - // Generated from `System.Reflection.Metadata.DeclarativeSecurityAttribute` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DeclarativeSecurityAttribute { public System.Reflection.DeclarativeSecurityAction Action { get => throw null; } @@ -645,7 +605,6 @@ namespace System public System.Reflection.Metadata.BlobHandle PermissionSet { get => throw null; } } - // Generated from `System.Reflection.Metadata.DeclarativeSecurityAttributeHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DeclarativeSecurityAttributeHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.DeclarativeSecurityAttributeHandle left, System.Reflection.Metadata.DeclarativeSecurityAttributeHandle right) => throw null; @@ -661,10 +620,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.DeclarativeSecurityAttributeHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.DeclarativeSecurityAttributeHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DeclarativeSecurityAttributeHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.DeclarativeSecurityAttributeHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.DeclarativeSecurityAttributeHandle Current { get => throw null; } @@ -683,7 +640,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.Document` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Document { // Stub generator skipped constructor @@ -693,7 +649,6 @@ namespace System public System.Reflection.Metadata.DocumentNameBlobHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.DocumentHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DocumentHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.DocumentHandle left, System.Reflection.Metadata.DocumentHandle right) => throw null; @@ -709,10 +664,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.DocumentHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.DocumentHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DocumentHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.DocumentHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.DocumentHandle Current { get => throw null; } @@ -731,7 +684,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.DocumentNameBlobHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DocumentNameBlobHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.DocumentNameBlobHandle left, System.Reflection.Metadata.DocumentNameBlobHandle right) => throw null; @@ -745,7 +697,6 @@ namespace System public static implicit operator System.Reflection.Metadata.BlobHandle(System.Reflection.Metadata.DocumentNameBlobHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.EntityHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EntityHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.EntityHandle left, System.Reflection.Metadata.EntityHandle right) => throw null; @@ -762,7 +713,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.EntityHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.EventAccessors` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EventAccessors { public System.Reflection.Metadata.MethodDefinitionHandle Adder { get => throw null; } @@ -772,7 +722,6 @@ namespace System public System.Reflection.Metadata.MethodDefinitionHandle Remover { get => throw null; } } - // Generated from `System.Reflection.Metadata.EventDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EventDefinition { public System.Reflection.EventAttributes Attributes { get => throw null; } @@ -783,7 +732,6 @@ namespace System public System.Reflection.Metadata.EntityHandle Type { get => throw null; } } - // Generated from `System.Reflection.Metadata.EventDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EventDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.EventDefinitionHandle left, System.Reflection.Metadata.EventDefinitionHandle right) => throw null; @@ -799,10 +747,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.EventDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.EventDefinitionHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EventDefinitionHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.EventDefinitionHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.EventDefinitionHandle Current { get => throw null; } @@ -821,7 +767,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.ExceptionRegion` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ExceptionRegion { public System.Reflection.Metadata.EntityHandle CatchType { get => throw null; } @@ -834,7 +779,6 @@ namespace System public int TryOffset { get => throw null; } } - // Generated from `System.Reflection.Metadata.ExceptionRegionKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ExceptionRegionKind : ushort { Catch = 0, @@ -843,7 +787,6 @@ namespace System Finally = 2, } - // Generated from `System.Reflection.Metadata.ExportedType` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ExportedType { public System.Reflection.TypeAttributes Attributes { get => throw null; } @@ -856,7 +799,6 @@ namespace System public System.Reflection.Metadata.NamespaceDefinitionHandle NamespaceDefinition { get => throw null; } } - // Generated from `System.Reflection.Metadata.ExportedTypeHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ExportedTypeHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ExportedTypeHandle left, System.Reflection.Metadata.ExportedTypeHandle right) => throw null; @@ -872,10 +814,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ExportedTypeHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ExportedTypeHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ExportedTypeHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.ExportedTypeHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.ExportedTypeHandle Current { get => throw null; } @@ -894,7 +834,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.FieldDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FieldDefinition { public System.Reflection.FieldAttributes Attributes { get => throw null; } @@ -910,7 +849,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.FieldDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FieldDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.FieldDefinitionHandle left, System.Reflection.Metadata.FieldDefinitionHandle right) => throw null; @@ -926,10 +864,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.FieldDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.FieldDefinitionHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FieldDefinitionHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.FieldDefinitionHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.FieldDefinitionHandle Current { get => throw null; } @@ -948,7 +884,6 @@ namespace System System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; } - // Generated from `System.Reflection.Metadata.GenericParameter` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameter { public System.Reflection.GenericParameterAttributes Attributes { get => throw null; } @@ -960,7 +895,6 @@ namespace System public System.Reflection.Metadata.EntityHandle Parent { get => throw null; } } - // Generated from `System.Reflection.Metadata.GenericParameterConstraint` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameterConstraint { // Stub generator skipped constructor @@ -969,7 +903,6 @@ namespace System public System.Reflection.Metadata.EntityHandle Type { get => throw null; } } - // Generated from `System.Reflection.Metadata.GenericParameterConstraintHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameterConstraintHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.GenericParameterConstraintHandle left, System.Reflection.Metadata.GenericParameterConstraintHandle right) => throw null; @@ -985,10 +918,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.GenericParameterConstraintHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.GenericParameterConstraintHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameterConstraintHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.GenericParameterConstraintHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.GenericParameterConstraintHandle Current { get => throw null; } @@ -1008,7 +939,6 @@ namespace System public System.Reflection.Metadata.GenericParameterConstraintHandle this[int index] { get => throw null; } } - // Generated from `System.Reflection.Metadata.GenericParameterHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameterHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.GenericParameterHandle left, System.Reflection.Metadata.GenericParameterHandle right) => throw null; @@ -1024,10 +954,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.GenericParameterHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.GenericParameterHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericParameterHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.GenericParameterHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.GenericParameterHandle Current { get => throw null; } @@ -1047,7 +975,6 @@ namespace System public System.Reflection.Metadata.GenericParameterHandle this[int index] { get => throw null; } } - // Generated from `System.Reflection.Metadata.GuidHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GuidHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.GuidHandle left, System.Reflection.Metadata.GuidHandle right) => throw null; @@ -1061,7 +988,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.GuidHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.Handle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Handle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.Handle left, System.Reflection.Metadata.Handle right) => throw null; @@ -1076,7 +1002,6 @@ namespace System public static System.Reflection.Metadata.ModuleDefinitionHandle ModuleDefinition; } - // Generated from `System.Reflection.Metadata.HandleComparer` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HandleComparer : System.Collections.Generic.IComparer, System.Collections.Generic.IComparer, System.Collections.Generic.IEqualityComparer, System.Collections.Generic.IEqualityComparer { public int Compare(System.Reflection.Metadata.EntityHandle x, System.Reflection.Metadata.EntityHandle y) => throw null; @@ -1088,7 +1013,6 @@ namespace System public int GetHashCode(System.Reflection.Metadata.Handle obj) => throw null; } - // Generated from `System.Reflection.Metadata.HandleKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HandleKind : byte { AssemblyDefinition = 32, @@ -1130,7 +1054,6 @@ namespace System UserString = 112, } - // Generated from `System.Reflection.Metadata.IConstructedTypeProvider<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IConstructedTypeProvider : System.Reflection.Metadata.ISZArrayTypeProvider { TType GetArrayType(TType elementType, System.Reflection.Metadata.ArrayShape shape); @@ -1139,7 +1062,6 @@ namespace System TType GetPointerType(TType elementType); } - // Generated from `System.Reflection.Metadata.ICustomAttributeTypeProvider<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomAttributeTypeProvider : System.Reflection.Metadata.ISZArrayTypeProvider, System.Reflection.Metadata.ISimpleTypeProvider { TType GetSystemType(); @@ -1148,7 +1070,6 @@ namespace System bool IsSystemType(TType type); } - // Generated from `System.Reflection.Metadata.ILOpCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ILOpCode : ushort { Add = 88, @@ -1371,7 +1292,6 @@ namespace System Xor = 97, } - // Generated from `System.Reflection.Metadata.ILOpCodeExtensions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ILOpCodeExtensions { public static int GetBranchOperandSize(this System.Reflection.Metadata.ILOpCode opCode) => throw null; @@ -1380,13 +1300,11 @@ namespace System public static bool IsBranch(this System.Reflection.Metadata.ILOpCode opCode) => throw null; } - // Generated from `System.Reflection.Metadata.ISZArrayTypeProvider<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISZArrayTypeProvider { TType GetSZArrayType(TType elementType); } - // Generated from `System.Reflection.Metadata.ISignatureTypeProvider<,>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISignatureTypeProvider : System.Reflection.Metadata.IConstructedTypeProvider, System.Reflection.Metadata.ISZArrayTypeProvider, System.Reflection.Metadata.ISimpleTypeProvider { TType GetFunctionPointerType(System.Reflection.Metadata.MethodSignature signature); @@ -1397,7 +1315,6 @@ namespace System TType GetTypeFromSpecification(System.Reflection.Metadata.MetadataReader reader, TGenericContext genericContext, System.Reflection.Metadata.TypeSpecificationHandle handle, System.Byte rawTypeKind); } - // Generated from `System.Reflection.Metadata.ISimpleTypeProvider<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISimpleTypeProvider { TType GetPrimitiveType(System.Reflection.Metadata.PrimitiveTypeCode typeCode); @@ -1405,7 +1322,6 @@ namespace System TType GetTypeFromReference(System.Reflection.Metadata.MetadataReader reader, System.Reflection.Metadata.TypeReferenceHandle handle, System.Byte rawTypeKind); } - // Generated from `System.Reflection.Metadata.ImageFormatLimitationException` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImageFormatLimitationException : System.Exception { public ImageFormatLimitationException() => throw null; @@ -1414,7 +1330,6 @@ namespace System public ImageFormatLimitationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Reflection.Metadata.ImportDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImportDefinition { public System.Reflection.Metadata.BlobHandle Alias { get => throw null; } @@ -1425,10 +1340,8 @@ namespace System public System.Reflection.Metadata.EntityHandle TargetType { get => throw null; } } - // Generated from `System.Reflection.Metadata.ImportDefinitionCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImportDefinitionCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.ImportDefinitionCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.ImportDefinition Current { get => throw null; } @@ -1446,7 +1359,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.ImportDefinitionKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ImportDefinitionKind : int { AliasAssemblyNamespace = 8, @@ -1460,7 +1372,6 @@ namespace System ImportXmlNamespace = 4, } - // Generated from `System.Reflection.Metadata.ImportScope` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImportScope { public System.Reflection.Metadata.ImportDefinitionCollection GetImports() => throw null; @@ -1469,10 +1380,8 @@ namespace System public System.Reflection.Metadata.ImportScopeHandle Parent { get => throw null; } } - // Generated from `System.Reflection.Metadata.ImportScopeCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImportScopeCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.ImportScopeCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.ImportScopeHandle Current { get => throw null; } @@ -1491,7 +1400,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.ImportScopeHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ImportScopeHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ImportScopeHandle left, System.Reflection.Metadata.ImportScopeHandle right) => throw null; @@ -1507,7 +1415,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ImportScopeHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.InterfaceImplementation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct InterfaceImplementation { public System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes() => throw null; @@ -1515,7 +1422,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.InterfaceImplementationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct InterfaceImplementationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.InterfaceImplementationHandle left, System.Reflection.Metadata.InterfaceImplementationHandle right) => throw null; @@ -1531,10 +1437,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.InterfaceImplementationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.InterfaceImplementationHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct InterfaceImplementationHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.InterfaceImplementationHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.InterfaceImplementationHandle Current { get => throw null; } @@ -1553,7 +1457,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.LocalConstant` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalConstant { // Stub generator skipped constructor @@ -1561,7 +1464,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.LocalConstantHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalConstantHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.LocalConstantHandle left, System.Reflection.Metadata.LocalConstantHandle right) => throw null; @@ -1577,10 +1479,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.LocalConstantHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.LocalConstantHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalConstantHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.LocalConstantHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.LocalConstantHandle Current { get => throw null; } @@ -1599,7 +1499,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.LocalScope` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalScope { public int EndOffset { get => throw null; } @@ -1613,7 +1512,6 @@ namespace System public int StartOffset { get => throw null; } } - // Generated from `System.Reflection.Metadata.LocalScopeHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalScopeHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.LocalScopeHandle left, System.Reflection.Metadata.LocalScopeHandle right) => throw null; @@ -1629,10 +1527,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.LocalScopeHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.LocalScopeHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalScopeHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.LocalScopeHandleCollection+ChildrenEnumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ChildrenEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { // Stub generator skipped constructor @@ -1644,7 +1540,6 @@ namespace System } - // Generated from `System.Reflection.Metadata.LocalScopeHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.LocalScopeHandle Current { get => throw null; } @@ -1663,7 +1558,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.LocalVariable` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalVariable { public System.Reflection.Metadata.LocalVariableAttributes Attributes { get => throw null; } @@ -1672,7 +1566,6 @@ namespace System public System.Reflection.Metadata.StringHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.LocalVariableAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum LocalVariableAttributes : int { @@ -1680,7 +1573,6 @@ namespace System None = 0, } - // Generated from `System.Reflection.Metadata.LocalVariableHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalVariableHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.LocalVariableHandle left, System.Reflection.Metadata.LocalVariableHandle right) => throw null; @@ -1696,10 +1588,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.LocalVariableHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.LocalVariableHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalVariableHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.LocalVariableHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.LocalVariableHandle Current { get => throw null; } @@ -1718,7 +1608,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.ManifestResource` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ManifestResource { public System.Reflection.ManifestResourceAttributes Attributes { get => throw null; } @@ -1729,7 +1618,6 @@ namespace System public System.Int64 Offset { get => throw null; } } - // Generated from `System.Reflection.Metadata.ManifestResourceHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ManifestResourceHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ManifestResourceHandle left, System.Reflection.Metadata.ManifestResourceHandle right) => throw null; @@ -1745,10 +1633,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ManifestResourceHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ManifestResourceHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ManifestResourceHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.ManifestResourceHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.ManifestResourceHandle Current { get => throw null; } @@ -1767,7 +1653,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.MemberReference` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MemberReference { public TType DecodeFieldSignature(System.Reflection.Metadata.ISignatureTypeProvider provider, TGenericContext genericContext) => throw null; @@ -1780,7 +1665,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.MemberReferenceHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MemberReferenceHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.MemberReferenceHandle left, System.Reflection.Metadata.MemberReferenceHandle right) => throw null; @@ -1796,10 +1680,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.MemberReferenceHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.MemberReferenceHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MemberReferenceHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.MemberReferenceHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.MemberReferenceHandle Current { get => throw null; } @@ -1818,14 +1700,12 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.MemberReferenceKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MemberReferenceKind : int { Field = 1, Method = 0, } - // Generated from `System.Reflection.Metadata.MetadataKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MetadataKind : int { Ecma335 = 0, @@ -1833,7 +1713,6 @@ namespace System WindowsMetadata = 1, } - // Generated from `System.Reflection.Metadata.MetadataReader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataReader { public System.Reflection.Metadata.AssemblyFileHandleCollection AssemblyFiles { get => throw null; } @@ -1848,6 +1727,7 @@ namespace System public System.Reflection.Metadata.FieldDefinitionHandleCollection FieldDefinitions { get => throw null; } public System.Reflection.Metadata.AssemblyDefinition GetAssemblyDefinition() => throw null; public System.Reflection.Metadata.AssemblyFile GetAssemblyFile(System.Reflection.Metadata.AssemblyFileHandle handle) => throw null; + public static System.Reflection.AssemblyName GetAssemblyName(string assemblyFile) => throw null; public System.Reflection.Metadata.AssemblyReference GetAssemblyReference(System.Reflection.Metadata.AssemblyReferenceHandle handle) => throw null; public System.Byte[] GetBlobBytes(System.Reflection.Metadata.BlobHandle handle) => throw null; public System.Collections.Immutable.ImmutableArray GetBlobContent(System.Reflection.Metadata.BlobHandle handle) => throw null; @@ -1918,7 +1798,6 @@ namespace System public System.Reflection.Metadata.MetadataStringDecoder UTF8Decoder { get => throw null; } } - // Generated from `System.Reflection.Metadata.MetadataReaderOptions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MetadataReaderOptions : int { @@ -1927,7 +1806,6 @@ namespace System None = 0, } - // Generated from `System.Reflection.Metadata.MetadataReaderProvider` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataReaderProvider : System.IDisposable { public void Dispose() => throw null; @@ -1940,7 +1818,6 @@ namespace System public System.Reflection.Metadata.MetadataReader GetMetadataReader(System.Reflection.Metadata.MetadataReaderOptions options = default(System.Reflection.Metadata.MetadataReaderOptions), System.Reflection.Metadata.MetadataStringDecoder utf8Decoder = default(System.Reflection.Metadata.MetadataStringDecoder)) => throw null; } - // Generated from `System.Reflection.Metadata.MetadataStreamOptions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MetadataStreamOptions : int { @@ -1949,7 +1826,6 @@ namespace System PrefetchMetadata = 2, } - // Generated from `System.Reflection.Metadata.MetadataStringComparer` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MetadataStringComparer { public bool Equals(System.Reflection.Metadata.DocumentNameBlobHandle handle, string value) => throw null; @@ -1963,7 +1839,6 @@ namespace System public bool StartsWith(System.Reflection.Metadata.StringHandle handle, string value, bool ignoreCase) => throw null; } - // Generated from `System.Reflection.Metadata.MetadataStringDecoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataStringDecoder { public static System.Reflection.Metadata.MetadataStringDecoder DefaultUTF8 { get => throw null; } @@ -1972,7 +1847,6 @@ namespace System public MetadataStringDecoder(System.Text.Encoding encoding) => throw null; } - // Generated from `System.Reflection.Metadata.MethodBodyBlock` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodBodyBlock { public static System.Reflection.Metadata.MethodBodyBlock Create(System.Reflection.Metadata.BlobReader reader) => throw null; @@ -1986,7 +1860,6 @@ namespace System public int Size { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodDebugInformation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDebugInformation { public System.Reflection.Metadata.DocumentHandle Document { get => throw null; } @@ -1997,7 +1870,6 @@ namespace System public System.Reflection.Metadata.BlobHandle SequencePointsBlob { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodDebugInformationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDebugInformationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.MethodDebugInformationHandle left, System.Reflection.Metadata.MethodDebugInformationHandle right) => throw null; @@ -2014,10 +1886,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.MethodDebugInformationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.MethodDebugInformationHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDebugInformationHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.MethodDebugInformationHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.MethodDebugInformationHandle Current { get => throw null; } @@ -2036,7 +1906,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.MethodDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDefinition { public System.Reflection.MethodAttributes Attributes { get => throw null; } @@ -2054,7 +1923,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.MethodDefinitionHandle left, System.Reflection.Metadata.MethodDefinitionHandle right) => throw null; @@ -2071,10 +1939,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.MethodDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.MethodDefinitionHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodDefinitionHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.MethodDefinitionHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.MethodDefinitionHandle Current { get => throw null; } @@ -2093,7 +1959,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.MethodImplementation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodImplementation { public System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes() => throw null; @@ -2103,7 +1968,6 @@ namespace System public System.Reflection.Metadata.TypeDefinitionHandle Type { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodImplementationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodImplementationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.MethodImplementationHandle left, System.Reflection.Metadata.MethodImplementationHandle right) => throw null; @@ -2119,10 +1983,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.MethodImplementationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.MethodImplementationHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodImplementationHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.MethodImplementationHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.MethodImplementationHandle Current { get => throw null; } @@ -2141,7 +2003,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.MethodImport` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodImport { public System.Reflection.MethodImportAttributes Attributes { get => throw null; } @@ -2150,7 +2011,6 @@ namespace System public System.Reflection.Metadata.StringHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodSignature<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodSignature { public int GenericParameterCount { get => throw null; } @@ -2162,7 +2022,6 @@ namespace System public TType ReturnType { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodSpecification` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodSpecification { public System.Collections.Immutable.ImmutableArray DecodeSignature(System.Reflection.Metadata.ISignatureTypeProvider provider, TGenericContext genericContext) => throw null; @@ -2172,7 +2031,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.MethodSpecificationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodSpecificationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.MethodSpecificationHandle left, System.Reflection.Metadata.MethodSpecificationHandle right) => throw null; @@ -2188,7 +2046,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.MethodSpecificationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ModuleDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ModuleDefinition { public System.Reflection.Metadata.GuidHandle BaseGenerationId { get => throw null; } @@ -2200,7 +2057,6 @@ namespace System public System.Reflection.Metadata.StringHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.ModuleDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ModuleDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ModuleDefinitionHandle left, System.Reflection.Metadata.ModuleDefinitionHandle right) => throw null; @@ -2216,7 +2072,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ModuleDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ModuleReference` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ModuleReference { public System.Reflection.Metadata.CustomAttributeHandleCollection GetCustomAttributes() => throw null; @@ -2224,7 +2079,6 @@ namespace System public System.Reflection.Metadata.StringHandle Name { get => throw null; } } - // Generated from `System.Reflection.Metadata.ModuleReferenceHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ModuleReferenceHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ModuleReferenceHandle left, System.Reflection.Metadata.ModuleReferenceHandle right) => throw null; @@ -2240,7 +2094,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ModuleReferenceHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.NamespaceDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NamespaceDefinition { public System.Collections.Immutable.ImmutableArray ExportedTypes { get => throw null; } @@ -2251,7 +2104,6 @@ namespace System public System.Collections.Immutable.ImmutableArray TypeDefinitions { get => throw null; } } - // Generated from `System.Reflection.Metadata.NamespaceDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NamespaceDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.NamespaceDefinitionHandle left, System.Reflection.Metadata.NamespaceDefinitionHandle right) => throw null; @@ -2265,7 +2117,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.NamespaceDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.PEReaderExtensions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class PEReaderExtensions { public static System.Reflection.Metadata.MetadataReader GetMetadataReader(this System.Reflection.PortableExecutable.PEReader peReader) => throw null; @@ -2274,7 +2125,6 @@ namespace System public static System.Reflection.Metadata.MethodBodyBlock GetMethodBody(this System.Reflection.PortableExecutable.PEReader peReader, int relativeVirtualAddress) => throw null; } - // Generated from `System.Reflection.Metadata.Parameter` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Parameter { public System.Reflection.ParameterAttributes Attributes { get => throw null; } @@ -2286,7 +2136,6 @@ namespace System public int SequenceNumber { get => throw null; } } - // Generated from `System.Reflection.Metadata.ParameterHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParameterHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.ParameterHandle left, System.Reflection.Metadata.ParameterHandle right) => throw null; @@ -2302,10 +2151,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.ParameterHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.ParameterHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParameterHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.ParameterHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.ParameterHandle Current { get => throw null; } @@ -2324,7 +2171,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.PrimitiveSerializationTypeCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PrimitiveSerializationTypeCode : byte { Boolean = 2, @@ -2342,7 +2188,6 @@ namespace System UInt64 = 11, } - // Generated from `System.Reflection.Metadata.PrimitiveTypeCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PrimitiveTypeCode : byte { Boolean = 2, @@ -2365,7 +2210,6 @@ namespace System Void = 1, } - // Generated from `System.Reflection.Metadata.PropertyAccessors` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PropertyAccessors { public System.Reflection.Metadata.MethodDefinitionHandle Getter { get => throw null; } @@ -2374,7 +2218,6 @@ namespace System public System.Reflection.Metadata.MethodDefinitionHandle Setter { get => throw null; } } - // Generated from `System.Reflection.Metadata.PropertyDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PropertyDefinition { public System.Reflection.PropertyAttributes Attributes { get => throw null; } @@ -2387,7 +2230,6 @@ namespace System public System.Reflection.Metadata.BlobHandle Signature { get => throw null; } } - // Generated from `System.Reflection.Metadata.PropertyDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PropertyDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.PropertyDefinitionHandle left, System.Reflection.Metadata.PropertyDefinitionHandle right) => throw null; @@ -2403,10 +2245,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.PropertyDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.PropertyDefinitionHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PropertyDefinitionHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.PropertyDefinitionHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.PropertyDefinitionHandle Current { get => throw null; } @@ -2425,7 +2265,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.ReservedBlob<>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ReservedBlob where THandle : struct { public System.Reflection.Metadata.Blob Content { get => throw null; } @@ -2434,7 +2273,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.SequencePoint` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SequencePoint : System.IEquatable { public System.Reflection.Metadata.DocumentHandle Document { get => throw null; } @@ -2451,10 +2289,8 @@ namespace System public int StartLine { get => throw null; } } - // Generated from `System.Reflection.Metadata.SequencePointCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SequencePointCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.SequencePointCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.SequencePoint Current { get => throw null; } @@ -2472,7 +2308,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.SerializationTypeCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SerializationTypeCode : byte { Boolean = 2, @@ -2495,7 +2330,6 @@ namespace System UInt64 = 11, } - // Generated from `System.Reflection.Metadata.SignatureAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SignatureAttributes : byte { @@ -2505,7 +2339,6 @@ namespace System None = 0, } - // Generated from `System.Reflection.Metadata.SignatureCallingConvention` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SignatureCallingConvention : byte { CDecl = 1, @@ -2517,7 +2350,6 @@ namespace System VarArgs = 5, } - // Generated from `System.Reflection.Metadata.SignatureHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SignatureHeader : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.SignatureHeader left, System.Reflection.Metadata.SignatureHeader right) => throw null; @@ -2539,7 +2371,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.Metadata.SignatureKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SignatureKind : byte { Field = 6, @@ -2549,7 +2380,6 @@ namespace System Property = 8, } - // Generated from `System.Reflection.Metadata.SignatureTypeCode` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SignatureTypeCode : byte { Array = 20, @@ -2586,7 +2416,6 @@ namespace System Void = 1, } - // Generated from `System.Reflection.Metadata.SignatureTypeKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SignatureTypeKind : byte { Class = 18, @@ -2594,7 +2423,6 @@ namespace System ValueType = 17, } - // Generated from `System.Reflection.Metadata.StandaloneSignature` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct StandaloneSignature { public System.Collections.Immutable.ImmutableArray DecodeLocalSignature(System.Reflection.Metadata.ISignatureTypeProvider provider, TGenericContext genericContext) => throw null; @@ -2605,7 +2433,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.StandaloneSignatureHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct StandaloneSignatureHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.StandaloneSignatureHandle left, System.Reflection.Metadata.StandaloneSignatureHandle right) => throw null; @@ -2621,14 +2448,12 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.StandaloneSignatureHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.StandaloneSignatureKind` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum StandaloneSignatureKind : int { LocalVariables = 1, Method = 0, } - // Generated from `System.Reflection.Metadata.StringHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct StringHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.StringHandle left, System.Reflection.Metadata.StringHandle right) => throw null; @@ -2642,7 +2467,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.StringHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.TypeDefinition` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeDefinition { public System.Reflection.TypeAttributes Attributes { get => throw null; } @@ -2666,7 +2490,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.TypeDefinitionHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeDefinitionHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.TypeDefinitionHandle left, System.Reflection.Metadata.TypeDefinitionHandle right) => throw null; @@ -2682,10 +2505,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.TypeDefinitionHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.TypeDefinitionHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeDefinitionHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.TypeDefinitionHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.TypeDefinitionHandle Current { get => throw null; } @@ -2704,7 +2525,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.TypeLayout` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeLayout { public bool IsDefault { get => throw null; } @@ -2714,7 +2534,6 @@ namespace System public TypeLayout(int size, int packingSize) => throw null; } - // Generated from `System.Reflection.Metadata.TypeReference` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeReference { public System.Reflection.Metadata.StringHandle Name { get => throw null; } @@ -2723,7 +2542,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.TypeReferenceHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeReferenceHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.TypeReferenceHandle left, System.Reflection.Metadata.TypeReferenceHandle right) => throw null; @@ -2739,10 +2557,8 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.TypeReferenceHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.TypeReferenceHandleCollection` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeReferenceHandleCollection : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { - // Generated from `System.Reflection.Metadata.TypeReferenceHandleCollection+Enumerator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Reflection.Metadata.TypeReferenceHandle Current { get => throw null; } @@ -2761,7 +2577,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.TypeSpecification` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeSpecification { public TType DecodeSignature(System.Reflection.Metadata.ISignatureTypeProvider provider, TGenericContext genericContext) => throw null; @@ -2770,7 +2585,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.TypeSpecificationHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypeSpecificationHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.TypeSpecificationHandle left, System.Reflection.Metadata.TypeSpecificationHandle right) => throw null; @@ -2786,7 +2600,6 @@ namespace System public static implicit operator System.Reflection.Metadata.Handle(System.Reflection.Metadata.TypeSpecificationHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.UserStringHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct UserStringHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.UserStringHandle left, System.Reflection.Metadata.UserStringHandle right) => throw null; @@ -2802,7 +2615,6 @@ namespace System namespace Ecma335 { - // Generated from `System.Reflection.Metadata.Ecma335.ArrayShapeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ArrayShapeEncoder { // Stub generator skipped constructor @@ -2811,7 +2623,6 @@ namespace System public void Shape(int rank, System.Collections.Immutable.ImmutableArray sizes, System.Collections.Immutable.ImmutableArray lowerBounds) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.BlobEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BlobEncoder { // Stub generator skipped constructor @@ -2819,6 +2630,7 @@ namespace System public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } public void CustomAttributeSignature(System.Action fixedArguments, System.Action namedArguments) => throw null; public void CustomAttributeSignature(out System.Reflection.Metadata.Ecma335.FixedArgumentsEncoder fixedArguments, out System.Reflection.Metadata.Ecma335.CustomAttributeNamedArgumentsEncoder namedArguments) => throw null; + public System.Reflection.Metadata.Ecma335.FieldTypeEncoder Field() => throw null; public System.Reflection.Metadata.Ecma335.SignatureTypeEncoder FieldSignature() => throw null; public System.Reflection.Metadata.Ecma335.LocalVariablesEncoder LocalVariableSignature(int variableCount) => throw null; public System.Reflection.Metadata.Ecma335.MethodSignatureEncoder MethodSignature(System.Reflection.Metadata.SignatureCallingConvention convention = default(System.Reflection.Metadata.SignatureCallingConvention), int genericParameterCount = default(int), bool isInstanceMethod = default(bool)) => throw null; @@ -2829,7 +2641,6 @@ namespace System public System.Reflection.Metadata.Ecma335.SignatureTypeEncoder TypeSpecificationSignature() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.CodedIndex` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CodedIndex { public static int CustomAttributeType(System.Reflection.Metadata.EntityHandle handle) => throw null; @@ -2849,17 +2660,16 @@ namespace System public static int TypeOrMethodDef(System.Reflection.Metadata.EntityHandle handle) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ControlFlowBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ControlFlowBuilder { public void AddCatchRegion(System.Reflection.Metadata.Ecma335.LabelHandle tryStart, System.Reflection.Metadata.Ecma335.LabelHandle tryEnd, System.Reflection.Metadata.Ecma335.LabelHandle handlerStart, System.Reflection.Metadata.Ecma335.LabelHandle handlerEnd, System.Reflection.Metadata.EntityHandle catchType) => throw null; public void AddFaultRegion(System.Reflection.Metadata.Ecma335.LabelHandle tryStart, System.Reflection.Metadata.Ecma335.LabelHandle tryEnd, System.Reflection.Metadata.Ecma335.LabelHandle handlerStart, System.Reflection.Metadata.Ecma335.LabelHandle handlerEnd) => throw null; public void AddFilterRegion(System.Reflection.Metadata.Ecma335.LabelHandle tryStart, System.Reflection.Metadata.Ecma335.LabelHandle tryEnd, System.Reflection.Metadata.Ecma335.LabelHandle handlerStart, System.Reflection.Metadata.Ecma335.LabelHandle handlerEnd, System.Reflection.Metadata.Ecma335.LabelHandle filterStart) => throw null; public void AddFinallyRegion(System.Reflection.Metadata.Ecma335.LabelHandle tryStart, System.Reflection.Metadata.Ecma335.LabelHandle tryEnd, System.Reflection.Metadata.Ecma335.LabelHandle handlerStart, System.Reflection.Metadata.Ecma335.LabelHandle handlerEnd) => throw null; + public void Clear() => throw null; public ControlFlowBuilder() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.CustomAttributeArrayTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeArrayTypeEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -2869,7 +2679,6 @@ namespace System public void ObjectArray() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.CustomAttributeElementTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeElementTypeEncoder { public void Boolean() => throw null; @@ -2893,7 +2702,6 @@ namespace System public void UInt64() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.CustomAttributeNamedArgumentsEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomAttributeNamedArgumentsEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -2902,7 +2710,6 @@ namespace System public CustomAttributeNamedArgumentsEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.CustomModifiersEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CustomModifiersEncoder { public System.Reflection.Metadata.Ecma335.CustomModifiersEncoder AddModifier(System.Reflection.Metadata.EntityHandle type, bool isOptional) => throw null; @@ -2911,7 +2718,6 @@ namespace System public CustomModifiersEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.EditAndContinueLogEntry` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EditAndContinueLogEntry : System.IEquatable { // Stub generator skipped constructor @@ -2923,7 +2729,6 @@ namespace System public System.Reflection.Metadata.Ecma335.EditAndContinueOperation Operation { get => throw null; } } - // Generated from `System.Reflection.Metadata.Ecma335.EditAndContinueOperation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EditAndContinueOperation : int { AddEvent = 5, @@ -2934,7 +2739,6 @@ namespace System Default = 0, } - // Generated from `System.Reflection.Metadata.Ecma335.ExceptionRegionEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ExceptionRegionEncoder { public System.Reflection.Metadata.Ecma335.ExceptionRegionEncoder Add(System.Reflection.Metadata.ExceptionRegionKind kind, int tryOffset, int tryLength, int handlerOffset, int handlerLength, System.Reflection.Metadata.EntityHandle catchType = default(System.Reflection.Metadata.EntityHandle), int filterOffset = default(int)) => throw null; @@ -2949,13 +2753,21 @@ namespace System public static bool IsSmallRegionCount(int exceptionRegionCount) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ExportedTypeExtensions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ExportedTypeExtensions { public static int GetTypeDefinitionId(this System.Reflection.Metadata.ExportedType exportedType) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.FixedArgumentsEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public struct FieldTypeEncoder + { + public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } + public System.Reflection.Metadata.Ecma335.CustomModifiersEncoder CustomModifiers() => throw null; + // Stub generator skipped constructor + public FieldTypeEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; + public System.Reflection.Metadata.Ecma335.SignatureTypeEncoder Type(bool isByRef = default(bool)) => throw null; + public void TypedReference() => throw null; + } + public struct FixedArgumentsEncoder { public System.Reflection.Metadata.Ecma335.LiteralEncoder AddArgument() => throw null; @@ -2964,7 +2776,6 @@ namespace System public FixedArgumentsEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.FunctionPointerAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FunctionPointerAttributes : int { HasExplicitThis = 96, @@ -2972,7 +2783,6 @@ namespace System None = 0, } - // Generated from `System.Reflection.Metadata.Ecma335.GenericTypeArgumentsEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GenericTypeArgumentsEncoder { public System.Reflection.Metadata.Ecma335.SignatureTypeEncoder AddArgument() => throw null; @@ -2981,7 +2791,6 @@ namespace System public GenericTypeArgumentsEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.HeapIndex` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HeapIndex : int { Blob = 2, @@ -2990,7 +2799,6 @@ namespace System UserString = 0, } - // Generated from `System.Reflection.Metadata.Ecma335.InstructionEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct InstructionEncoder { public void Branch(System.Reflection.Metadata.ILOpCode code, System.Reflection.Metadata.Ecma335.LabelHandle label) => throw null; @@ -3022,7 +2830,6 @@ namespace System public void Token(int token) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.LabelHandle` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LabelHandle : System.IEquatable { public static bool operator !=(System.Reflection.Metadata.Ecma335.LabelHandle left, System.Reflection.Metadata.Ecma335.LabelHandle right) => throw null; @@ -3035,7 +2842,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.Metadata.Ecma335.LiteralEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LiteralEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3049,7 +2855,6 @@ namespace System public System.Reflection.Metadata.Ecma335.VectorEncoder Vector() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.LiteralsEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LiteralsEncoder { public System.Reflection.Metadata.Ecma335.LiteralEncoder AddLiteral() => throw null; @@ -3058,7 +2863,6 @@ namespace System public LiteralsEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.LocalVariableTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalVariableTypeEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3069,7 +2873,6 @@ namespace System public void TypedReference() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.LocalVariablesEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct LocalVariablesEncoder { public System.Reflection.Metadata.Ecma335.LocalVariableTypeEncoder AddVariable() => throw null; @@ -3078,7 +2881,6 @@ namespace System public LocalVariablesEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataAggregator` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataAggregator { public System.Reflection.Metadata.Handle GetGenerationHandle(System.Reflection.Metadata.Handle handle, out int generation) => throw null; @@ -3086,7 +2888,6 @@ namespace System public MetadataAggregator(System.Reflection.Metadata.MetadataReader baseReader, System.Collections.Generic.IReadOnlyList deltaReaders) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataBuilder { public System.Reflection.Metadata.AssemblyDefinitionHandle AddAssembly(System.Reflection.Metadata.StringHandle name, System.Version version, System.Reflection.Metadata.StringHandle culture, System.Reflection.Metadata.BlobHandle publicKey, System.Reflection.AssemblyFlags flags, System.Reflection.AssemblyHashAlgorithm hashAlgorithm) => throw null; @@ -3152,7 +2953,6 @@ namespace System public void SetCapacity(System.Reflection.Metadata.Ecma335.TableIndex table, int rowCount) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataReaderExtensions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MetadataReaderExtensions { public static System.Collections.Generic.IEnumerable GetEditAndContinueLogEntries(this System.Reflection.Metadata.MetadataReader reader) => throw null; @@ -3170,7 +2970,6 @@ namespace System public static System.Reflection.Metadata.SignatureTypeKind ResolveSignatureTypeKind(this System.Reflection.Metadata.MetadataReader reader, System.Reflection.Metadata.EntityHandle typeHandle, System.Byte rawTypeKind) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataRootBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataRootBuilder { public MetadataRootBuilder(System.Reflection.Metadata.Ecma335.MetadataBuilder tablesAndHeaps, string metadataVersion = default(string), bool suppressValidation = default(bool)) => throw null; @@ -3180,7 +2979,6 @@ namespace System public bool SuppressValidation { get => throw null; } } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataSizes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataSizes { public System.Collections.Immutable.ImmutableArray ExternalRowCounts { get => throw null; } @@ -3189,7 +2987,6 @@ namespace System public System.Collections.Immutable.ImmutableArray RowCounts { get => throw null; } } - // Generated from `System.Reflection.Metadata.Ecma335.MetadataTokens` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MetadataTokens { public static System.Reflection.Metadata.AssemblyFileHandle AssemblyFileHandle(int rowNumber) => throw null; @@ -3249,7 +3046,6 @@ namespace System public static System.Reflection.Metadata.UserStringHandle UserStringHandle(int offset) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MethodBodyAttributes` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MethodBodyAttributes : int { @@ -3257,10 +3053,8 @@ namespace System None = 0, } - // Generated from `System.Reflection.Metadata.Ecma335.MethodBodyStreamEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodBodyStreamEncoder { - // Generated from `System.Reflection.Metadata.Ecma335.MethodBodyStreamEncoder+MethodBody` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodBody { public System.Reflection.Metadata.Ecma335.ExceptionRegionEncoder ExceptionRegions { get => throw null; } @@ -3279,7 +3073,6 @@ namespace System public MethodBodyStreamEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.MethodSignatureEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MethodSignatureEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3290,7 +3083,6 @@ namespace System public void Parameters(int parameterCount, out System.Reflection.Metadata.Ecma335.ReturnTypeEncoder returnType, out System.Reflection.Metadata.Ecma335.ParametersEncoder parameters) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.NameEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NameEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3299,7 +3091,6 @@ namespace System public NameEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.NamedArgumentTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NamedArgumentTypeEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3310,7 +3101,6 @@ namespace System public System.Reflection.Metadata.Ecma335.CustomAttributeElementTypeEncoder ScalarType() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.NamedArgumentsEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NamedArgumentsEncoder { public void AddArgument(bool isField, System.Action type, System.Action name, System.Action literal) => throw null; @@ -3320,7 +3110,6 @@ namespace System public NamedArgumentsEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ParameterTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParameterTypeEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3331,7 +3120,6 @@ namespace System public void TypedReference() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ParametersEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParametersEncoder { public System.Reflection.Metadata.Ecma335.ParameterTypeEncoder AddParameter() => throw null; @@ -3342,7 +3130,6 @@ namespace System public System.Reflection.Metadata.Ecma335.ParametersEncoder StartVarArgs() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.PermissionSetEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PermissionSetEncoder { public System.Reflection.Metadata.Ecma335.PermissionSetEncoder AddPermission(string typeName, System.Reflection.Metadata.BlobBuilder encodedArguments) => throw null; @@ -3352,7 +3139,6 @@ namespace System public PermissionSetEncoder(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.PortablePdbBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PortablePdbBuilder { public System.UInt16 FormatVersion { get => throw null; } @@ -3362,7 +3148,6 @@ namespace System public System.Reflection.Metadata.BlobContentId Serialize(System.Reflection.Metadata.BlobBuilder builder) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ReturnTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ReturnTypeEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3374,7 +3159,6 @@ namespace System public void Void() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.ScalarEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ScalarEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3385,7 +3169,6 @@ namespace System public void SystemType(string serializedTypeName) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.SignatureDecoder<,>` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SignatureDecoder { public TType DecodeFieldSignature(ref System.Reflection.Metadata.BlobReader blobReader) => throw null; @@ -3397,7 +3180,6 @@ namespace System public SignatureDecoder(System.Reflection.Metadata.ISignatureTypeProvider provider, System.Reflection.Metadata.MetadataReader metadataReader, TGenericContext genericContext) => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.SignatureTypeEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SignatureTypeEncoder { public void Array(System.Action elementType, System.Action arrayShape) => throw null; @@ -3433,7 +3215,6 @@ namespace System public void VoidPointer() => throw null; } - // Generated from `System.Reflection.Metadata.Ecma335.TableIndex` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TableIndex : byte { Assembly = 32, @@ -3491,7 +3272,6 @@ namespace System TypeSpec = 27, } - // Generated from `System.Reflection.Metadata.Ecma335.VectorEncoder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct VectorEncoder { public System.Reflection.Metadata.BlobBuilder Builder { get => throw null; } @@ -3504,7 +3284,6 @@ namespace System } namespace PortableExecutable { - // Generated from `System.Reflection.PortableExecutable.Characteristics` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum Characteristics : ushort { @@ -3525,7 +3304,6 @@ namespace System UpSystemOnly = 16384, } - // Generated from `System.Reflection.PortableExecutable.CodeViewDebugDirectoryData` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CodeViewDebugDirectoryData { public int Age { get => throw null; } @@ -3534,7 +3312,6 @@ namespace System public string Path { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.CoffHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CoffHeader { public System.Reflection.PortableExecutable.Characteristics Characteristics { get => throw null; } @@ -3546,7 +3323,6 @@ namespace System public int TimeDateStamp { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.CorFlags` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CorFlags : int { @@ -3559,7 +3335,6 @@ namespace System TrackDebugData = 65536, } - // Generated from `System.Reflection.PortableExecutable.CorHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CorHeader { public System.Reflection.PortableExecutable.DirectoryEntry CodeManagerTableDirectory { get => throw null; } @@ -3575,7 +3350,6 @@ namespace System public System.Reflection.PortableExecutable.DirectoryEntry VtableFixupsDirectory { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.DebugDirectoryBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebugDirectoryBuilder { public void AddCodeViewEntry(string pdbPath, System.Reflection.Metadata.BlobContentId pdbContentId, System.UInt16 portablePdbVersion) => throw null; @@ -3588,7 +3362,6 @@ namespace System public DebugDirectoryBuilder() => throw null; } - // Generated from `System.Reflection.PortableExecutable.DebugDirectoryEntry` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DebugDirectoryEntry { public int DataPointer { get => throw null; } @@ -3603,7 +3376,6 @@ namespace System public System.Reflection.PortableExecutable.DebugDirectoryEntryType Type { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.DebugDirectoryEntryType` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DebugDirectoryEntryType : int { CodeView = 2, @@ -3614,7 +3386,6 @@ namespace System Unknown = 0, } - // Generated from `System.Reflection.PortableExecutable.DirectoryEntry` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DirectoryEntry { // Stub generator skipped constructor @@ -3623,7 +3394,6 @@ namespace System public int Size; } - // Generated from `System.Reflection.PortableExecutable.DllCharacteristics` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DllCharacteristics : ushort { @@ -3642,7 +3412,6 @@ namespace System WdmDriver = 8192, } - // Generated from `System.Reflection.PortableExecutable.Machine` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Machine : ushort { AM33 = 467, @@ -3655,6 +3424,8 @@ namespace System Ebc = 3772, I386 = 332, IA64 = 512, + LoongArch32 = 25138, + LoongArch64 = 25188, M32R = 36929, MIPS16 = 614, MipsFpu = 870, @@ -3672,7 +3443,6 @@ namespace System WceMipsV2 = 361, } - // Generated from `System.Reflection.PortableExecutable.ManagedPEBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ManagedPEBuilder : System.Reflection.PortableExecutable.PEBuilder { protected override System.Collections.Immutable.ImmutableArray CreateSections() => throw null; @@ -3684,10 +3454,8 @@ namespace System public void Sign(System.Reflection.Metadata.BlobBuilder peImage, System.Func, System.Byte[]> signatureProvider) => throw null; } - // Generated from `System.Reflection.PortableExecutable.PEBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class PEBuilder { - // Generated from `System.Reflection.PortableExecutable.PEBuilder+Section` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected struct Section { public System.Reflection.PortableExecutable.SectionCharacteristics Characteristics; @@ -3708,7 +3476,6 @@ namespace System protected abstract System.Reflection.Metadata.BlobBuilder SerializeSection(string name, System.Reflection.PortableExecutable.SectionLocation location); } - // Generated from `System.Reflection.PortableExecutable.PEDirectoriesBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PEDirectoriesBuilder { public int AddressOfEntryPoint { get => throw null; set => throw null; } @@ -3729,7 +3496,6 @@ namespace System public System.Reflection.PortableExecutable.DirectoryEntry ThreadLocalStorageTable { get => throw null; set => throw null; } } - // Generated from `System.Reflection.PortableExecutable.PEHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PEHeader { public int AddressOfEntryPoint { get => throw null; } @@ -3777,7 +3543,6 @@ namespace System public System.Reflection.PortableExecutable.DirectoryEntry ThreadLocalStorageTableDirectory { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.PEHeaderBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PEHeaderBuilder { public static System.Reflection.PortableExecutable.PEHeaderBuilder CreateExecutableHeader() => throw null; @@ -3804,7 +3569,6 @@ namespace System public System.Reflection.PortableExecutable.Subsystem Subsystem { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.PEHeaders` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PEHeaders { public System.Reflection.PortableExecutable.CoffHeader CoffHeader { get => throw null; } @@ -3827,14 +3591,12 @@ namespace System public bool TryGetDirectoryOffset(System.Reflection.PortableExecutable.DirectoryEntry directory, out int offset) => throw null; } - // Generated from `System.Reflection.PortableExecutable.PEMagic` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PEMagic : ushort { PE32 = 267, PE32Plus = 523, } - // Generated from `System.Reflection.PortableExecutable.PEMemoryBlock` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PEMemoryBlock { public System.Collections.Immutable.ImmutableArray GetContent() => throw null; @@ -3846,7 +3608,6 @@ namespace System unsafe public System.Byte* Pointer { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.PEReader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PEReader : System.IDisposable { public void Dispose() => throw null; @@ -3871,7 +3632,6 @@ namespace System public bool TryOpenAssociatedPortablePdb(string peImagePath, System.Func pdbFileStreamProvider, out System.Reflection.Metadata.MetadataReaderProvider pdbReaderProvider, out string pdbPath) => throw null; } - // Generated from `System.Reflection.PortableExecutable.PEStreamOptions` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PEStreamOptions : int { @@ -3882,7 +3642,6 @@ namespace System PrefetchMetadata = 2, } - // Generated from `System.Reflection.PortableExecutable.PdbChecksumDebugDirectoryData` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PdbChecksumDebugDirectoryData { public string AlgorithmName { get => throw null; } @@ -3890,14 +3649,12 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Reflection.PortableExecutable.ResourceSectionBuilder` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ResourceSectionBuilder { protected ResourceSectionBuilder() => throw null; protected internal abstract void Serialize(System.Reflection.Metadata.BlobBuilder builder, System.Reflection.PortableExecutable.SectionLocation location); } - // Generated from `System.Reflection.PortableExecutable.SectionCharacteristics` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SectionCharacteristics : uint { @@ -3949,7 +3706,6 @@ namespace System TypeReg = 0, } - // Generated from `System.Reflection.PortableExecutable.SectionHeader` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SectionHeader { public string Name { get => throw null; } @@ -3965,7 +3721,6 @@ namespace System public int VirtualSize { get => throw null; } } - // Generated from `System.Reflection.PortableExecutable.SectionLocation` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SectionLocation { public int PointerToRawData { get => throw null; } @@ -3974,7 +3729,6 @@ namespace System public SectionLocation(int relativeVirtualAddress, int pointerToRawData) => throw null; } - // Generated from `System.Reflection.PortableExecutable.Subsystem` in `System.Reflection.Metadata, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Subsystem : ushort { EfiApplication = 10, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Primitives.cs index b2015a66eb6..f8302f96b9c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.Primitives.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Emit { - // Generated from `System.Reflection.Emit.FlowControl` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FlowControl : int { Branch = 0, @@ -20,7 +20,6 @@ namespace System Throw = 8, } - // Generated from `System.Reflection.Emit.OpCode` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct OpCode : System.IEquatable { public static bool operator !=(System.Reflection.Emit.OpCode a, System.Reflection.Emit.OpCode b) => throw null; @@ -40,7 +39,6 @@ namespace System public System.Int16 Value { get => throw null; } } - // Generated from `System.Reflection.Emit.OpCodeType` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OpCodeType : int { Annotation = 0, @@ -51,7 +49,6 @@ namespace System Primitive = 5, } - // Generated from `System.Reflection.Emit.OpCodes` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OpCodes { public static System.Reflection.Emit.OpCode Add; @@ -283,7 +280,6 @@ namespace System public static System.Reflection.Emit.OpCode Xor; } - // Generated from `System.Reflection.Emit.OperandType` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OperandType : int { InlineBrTarget = 0, @@ -306,7 +302,6 @@ namespace System ShortInlineVar = 18, } - // Generated from `System.Reflection.Emit.PackingSize` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PackingSize : int { Size1 = 1, @@ -320,7 +315,6 @@ namespace System Unspecified = 0, } - // Generated from `System.Reflection.Emit.StackBehaviour` in `System.Reflection.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum StackBehaviour : int { Pop0 = 0, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.TypeExtensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.TypeExtensions.cs index 189c23a12d2..30f03313c7a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.TypeExtensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Reflection.TypeExtensions.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Reflection.TypeExtensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Reflection { - // Generated from `System.Reflection.AssemblyExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class AssemblyExtensions { public static System.Type[] GetExportedTypes(this System.Reflection.Assembly assembly) => throw null; @@ -12,7 +12,6 @@ namespace System public static System.Type[] GetTypes(this System.Reflection.Assembly assembly) => throw null; } - // Generated from `System.Reflection.EventInfoExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class EventInfoExtensions { public static System.Reflection.MethodInfo GetAddMethod(this System.Reflection.EventInfo eventInfo) => throw null; @@ -23,27 +22,23 @@ namespace System public static System.Reflection.MethodInfo GetRemoveMethod(this System.Reflection.EventInfo eventInfo, bool nonPublic) => throw null; } - // Generated from `System.Reflection.MemberInfoExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MemberInfoExtensions { public static int GetMetadataToken(this System.Reflection.MemberInfo member) => throw null; public static bool HasMetadataToken(this System.Reflection.MemberInfo member) => throw null; } - // Generated from `System.Reflection.MethodInfoExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MethodInfoExtensions { public static System.Reflection.MethodInfo GetBaseDefinition(this System.Reflection.MethodInfo method) => throw null; } - // Generated from `System.Reflection.ModuleExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ModuleExtensions { public static System.Guid GetModuleVersionId(this System.Reflection.Module module) => throw null; public static bool HasModuleVersionId(this System.Reflection.Module module) => throw null; } - // Generated from `System.Reflection.PropertyInfoExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class PropertyInfoExtensions { public static System.Reflection.MethodInfo[] GetAccessors(this System.Reflection.PropertyInfo property) => throw null; @@ -54,7 +49,6 @@ namespace System public static System.Reflection.MethodInfo GetSetMethod(this System.Reflection.PropertyInfo property, bool nonPublic) => throw null; } - // Generated from `System.Reflection.TypeExtensions` in `System.Reflection.TypeExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class TypeExtensions { public static System.Reflection.ConstructorInfo GetConstructor(this System.Type type, System.Type[] types) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Resources.Writer.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Resources.Writer.cs index de557c77d72..9e25b50b75d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Resources.Writer.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Resources.Writer.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Resources.Writer, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Resources { - // Generated from `System.Resources.IResourceWriter` in `System.Resources.Writer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IResourceWriter : System.IDisposable { void AddResource(string name, System.Byte[] value); @@ -14,7 +14,6 @@ namespace System void Generate(); } - // Generated from `System.Resources.ResourceWriter` in `System.Resources.Writer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceWriter : System.IDisposable, System.Resources.IResourceWriter { public void AddResource(string name, System.Byte[] value) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.Unsafe.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.Unsafe.cs deleted file mode 100644 index c49f38162ed..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.Unsafe.cs +++ /dev/null @@ -1,58 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Runtime - { - namespace CompilerServices - { - // Generated from `System.Runtime.CompilerServices.Unsafe` in `System.Runtime.CompilerServices.Unsafe, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class Unsafe - { - unsafe public static void* Add(void* source, int elementOffset) => throw null; - public static T Add(ref T source, System.IntPtr elementOffset) => throw null; - public static T Add(ref T source, System.UIntPtr elementOffset) => throw null; - public static T Add(ref T source, int elementOffset) => throw null; - public static T AddByteOffset(ref T source, System.IntPtr byteOffset) => throw null; - public static T AddByteOffset(ref T source, System.UIntPtr byteOffset) => throw null; - public static bool AreSame(ref T left, ref T right) => throw null; - public static T As(object o) where T : class => throw null; - public static TTo As(ref TFrom source) => throw null; - unsafe public static void* AsPointer(ref T value) => throw null; - public static T AsRef(T source) => throw null; - unsafe public static T AsRef(void* source) => throw null; - public static System.IntPtr ByteOffset(ref T origin, ref T target) => throw null; - unsafe public static void Copy(void* destination, ref T source) => throw null; - unsafe public static void Copy(ref T destination, void* source) => throw null; - unsafe public static void CopyBlock(void* destination, void* source, System.UInt32 byteCount) => throw null; - public static void CopyBlock(ref System.Byte destination, ref System.Byte source, System.UInt32 byteCount) => throw null; - unsafe public static void CopyBlockUnaligned(void* destination, void* source, System.UInt32 byteCount) => throw null; - public static void CopyBlockUnaligned(ref System.Byte destination, ref System.Byte source, System.UInt32 byteCount) => throw null; - unsafe public static void InitBlock(void* startAddress, System.Byte value, System.UInt32 byteCount) => throw null; - public static void InitBlock(ref System.Byte startAddress, System.Byte value, System.UInt32 byteCount) => throw null; - unsafe public static void InitBlockUnaligned(void* startAddress, System.Byte value, System.UInt32 byteCount) => throw null; - public static void InitBlockUnaligned(ref System.Byte startAddress, System.Byte value, System.UInt32 byteCount) => throw null; - public static bool IsAddressGreaterThan(ref T left, ref T right) => throw null; - public static bool IsAddressLessThan(ref T left, ref T right) => throw null; - public static bool IsNullRef(ref T source) => throw null; - public static T NullRef() => throw null; - unsafe public static T Read(void* source) => throw null; - unsafe public static T ReadUnaligned(void* source) => throw null; - public static T ReadUnaligned(ref System.Byte source) => throw null; - public static int SizeOf() => throw null; - public static void SkipInit(out T value) => throw null; - unsafe public static void* Subtract(void* source, int elementOffset) => throw null; - public static T Subtract(ref T source, System.IntPtr elementOffset) => throw null; - public static T Subtract(ref T source, System.UIntPtr elementOffset) => throw null; - public static T Subtract(ref T source, int elementOffset) => throw null; - public static T SubtractByteOffset(ref T source, System.IntPtr byteOffset) => throw null; - public static T SubtractByteOffset(ref T source, System.UIntPtr byteOffset) => throw null; - public static T Unbox(object box) where T : struct => throw null; - unsafe public static void Write(void* destination, T value) => throw null; - unsafe public static void WriteUnaligned(void* destination, T value) => throw null; - public static void WriteUnaligned(ref System.Byte destination, T value) => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.VisualC.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.VisualC.cs index 6a1548143be..66b9322cc5a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.VisualC.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.CompilerServices.VisualC.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.CompilerServices.VisualC, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,87 +7,71 @@ namespace System { namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.CompilerMarshalOverride` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CompilerMarshalOverride { } - // Generated from `System.Runtime.CompilerServices.CppInlineNamespaceAttribute` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CppInlineNamespaceAttribute : System.Attribute { public CppInlineNamespaceAttribute(string dottedName) => throw null; } - // Generated from `System.Runtime.CompilerServices.HasCopySemanticsAttribute` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HasCopySemanticsAttribute : System.Attribute { public HasCopySemanticsAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.IsBoxed` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsBoxed { } - // Generated from `System.Runtime.CompilerServices.IsByValue` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsByValue { } - // Generated from `System.Runtime.CompilerServices.IsCopyConstructed` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsCopyConstructed { } - // Generated from `System.Runtime.CompilerServices.IsExplicitlyDereferenced` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsExplicitlyDereferenced { } - // Generated from `System.Runtime.CompilerServices.IsImplicitlyDereferenced` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsImplicitlyDereferenced { } - // Generated from `System.Runtime.CompilerServices.IsJitIntrinsic` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsJitIntrinsic { } - // Generated from `System.Runtime.CompilerServices.IsLong` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsLong { } - // Generated from `System.Runtime.CompilerServices.IsPinned` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsPinned { } - // Generated from `System.Runtime.CompilerServices.IsSignUnspecifiedByte` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsSignUnspecifiedByte { } - // Generated from `System.Runtime.CompilerServices.IsUdtReturn` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsUdtReturn { } - // Generated from `System.Runtime.CompilerServices.NativeCppClassAttribute` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NativeCppClassAttribute : System.Attribute { public NativeCppClassAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.RequiredAttributeAttribute` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RequiredAttributeAttribute : System.Attribute { public RequiredAttributeAttribute(System.Type requiredContract) => throw null; public System.Type RequiredContract { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.ScopelessEnumAttribute` in `System.Runtime.CompilerServices.VisualC, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ScopelessEnumAttribute : System.Attribute { public ScopelessEnumAttribute() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.JavaScript.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.JavaScript.cs new file mode 100644 index 00000000000..1298bedf792 --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.JavaScript.cs @@ -0,0 +1,318 @@ +// This file contains auto-generated code. +// Generated from `System.Runtime.InteropServices.JavaScript, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. + +namespace System +{ + namespace Runtime + { + namespace InteropServices + { + namespace JavaScript + { + public class JSException : System.Exception + { + public JSException(string msg) => throw null; + } + + public class JSExportAttribute : System.Attribute + { + public JSExportAttribute() => throw null; + } + + public class JSFunctionBinding + { + public static System.Runtime.InteropServices.JavaScript.JSFunctionBinding BindJSFunction(string functionName, string moduleName, System.ReadOnlySpan signatures) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSFunctionBinding BindManagedFunction(string fullyQualifiedName, int signatureHash, System.ReadOnlySpan signatures) => throw null; + public static void InvokeJS(System.Runtime.InteropServices.JavaScript.JSFunctionBinding signature, System.Span arguments) => throw null; + public JSFunctionBinding() => throw null; + } + + public static class JSHost + { + public static System.Runtime.InteropServices.JavaScript.JSObject DotnetInstance { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSObject GlobalThis { get => throw null; } + public static System.Threading.Tasks.Task ImportAsync(string moduleName, string moduleUrl, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + } + + public class JSImportAttribute : System.Attribute + { + public string FunctionName { get => throw null; } + public JSImportAttribute(string functionName) => throw null; + public JSImportAttribute(string functionName, string moduleName) => throw null; + public string ModuleName { get => throw null; } + } + + public class JSMarshalAsAttribute : System.Attribute where T : System.Runtime.InteropServices.JavaScript.JSType + { + public JSMarshalAsAttribute() => throw null; + } + + public struct JSMarshalerArgument + { + public delegate void ArgumentToJSCallback(ref System.Runtime.InteropServices.JavaScript.JSMarshalerArgument arg, T value); + + + public delegate void ArgumentToManagedCallback(ref System.Runtime.InteropServices.JavaScript.JSMarshalerArgument arg, out T value); + + + public void Initialize() => throw null; + // Stub generator skipped constructor + public void ToJS(System.Action value) => throw null; + public void ToJS(System.ArraySegment value) => throw null; + public void ToJS(System.ArraySegment value) => throw null; + public void ToJS(System.ArraySegment value) => throw null; + public void ToJS(System.Byte[] value) => throw null; + public void ToJS(System.DateTime value) => throw null; + public void ToJS(System.DateTime? value) => throw null; + public void ToJS(System.DateTimeOffset value) => throw null; + public void ToJS(System.DateTimeOffset? value) => throw null; + public void ToJS(double[] value) => throw null; + public void ToJS(System.Exception value) => throw null; + public void ToJS(int[] value) => throw null; + public void ToJS(System.IntPtr value) => throw null; + public void ToJS(System.IntPtr? value) => throw null; + public void ToJS(System.Runtime.InteropServices.JavaScript.JSObject value) => throw null; + public void ToJS(System.Runtime.InteropServices.JavaScript.JSObject[] value) => throw null; + public void ToJS(object[] value) => throw null; + public void ToJS(System.Span value) => throw null; + public void ToJS(System.Span value) => throw null; + public void ToJS(System.Span value) => throw null; + public void ToJS(string[] value) => throw null; + public void ToJS(System.Threading.Tasks.Task value) => throw null; + unsafe public void ToJS(void* value) => throw null; + public void ToJS(bool value) => throw null; + public void ToJS(bool? value) => throw null; + public void ToJS(System.Byte value) => throw null; + public void ToJS(System.Byte? value) => throw null; + public void ToJS(System.Char value) => throw null; + public void ToJS(System.Char? value) => throw null; + public void ToJS(double value) => throw null; + public void ToJS(double? value) => throw null; + public void ToJS(float value) => throw null; + public void ToJS(float? value) => throw null; + public void ToJS(int value) => throw null; + public void ToJS(int? value) => throw null; + public void ToJS(System.Int64 value) => throw null; + public void ToJS(System.Int64? value) => throw null; + public void ToJS(object value) => throw null; + public void ToJS(System.Int16 value) => throw null; + public void ToJS(System.Int16? value) => throw null; + public void ToJS(string value) => throw null; + public void ToJS(System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback resMarshaler) => throw null; + public void ToJS(System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg3Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback resMarshaler) => throw null; + public void ToJS(System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg3Marshaler) => throw null; + public void ToJS(System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback resMarshaler) => throw null; + public void ToJS(System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg2Marshaler) => throw null; + public void ToJS(System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback arg1Marshaler) => throw null; + public void ToJS(System.Threading.Tasks.Task value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback marshaler) => throw null; + public void ToJS(System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback resMarshaler) => throw null; + public void ToJSBig(System.Int64 value) => throw null; + public void ToJSBig(System.Int64? value) => throw null; + public void ToManaged(out System.Action value) => throw null; + public void ToManaged(out System.ArraySegment value) => throw null; + public void ToManaged(out System.ArraySegment value) => throw null; + public void ToManaged(out System.ArraySegment value) => throw null; + public void ToManaged(out System.Byte[] value) => throw null; + public void ToManaged(out System.DateTime value) => throw null; + public void ToManaged(out System.DateTime? value) => throw null; + public void ToManaged(out System.DateTimeOffset value) => throw null; + public void ToManaged(out System.DateTimeOffset? value) => throw null; + public void ToManaged(out double[] value) => throw null; + public void ToManaged(out System.Exception value) => throw null; + public void ToManaged(out int[] value) => throw null; + public void ToManaged(out System.IntPtr value) => throw null; + public void ToManaged(out System.IntPtr? value) => throw null; + public void ToManaged(out System.Runtime.InteropServices.JavaScript.JSObject value) => throw null; + public void ToManaged(out System.Runtime.InteropServices.JavaScript.JSObject[] value) => throw null; + public void ToManaged(out object[] value) => throw null; + public void ToManaged(out System.Span value) => throw null; + public void ToManaged(out System.Span value) => throw null; + public void ToManaged(out System.Span value) => throw null; + public void ToManaged(out string[] value) => throw null; + public void ToManaged(out System.Threading.Tasks.Task value) => throw null; + unsafe public void ToManaged(out void* value) => throw null; + public void ToManaged(out bool value) => throw null; + public void ToManaged(out bool? value) => throw null; + public void ToManaged(out System.Byte value) => throw null; + public void ToManaged(out System.Byte? value) => throw null; + public void ToManaged(out System.Char value) => throw null; + public void ToManaged(out System.Char? value) => throw null; + public void ToManaged(out double value) => throw null; + public void ToManaged(out double? value) => throw null; + public void ToManaged(out float value) => throw null; + public void ToManaged(out float? value) => throw null; + public void ToManaged(out int value) => throw null; + public void ToManaged(out int? value) => throw null; + public void ToManaged(out System.Int64 value) => throw null; + public void ToManaged(out System.Int64? value) => throw null; + public void ToManaged(out object value) => throw null; + public void ToManaged(out System.Int16 value) => throw null; + public void ToManaged(out System.Int16? value) => throw null; + public void ToManaged(out string value) => throw null; + public void ToManaged(out System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback resMarshaler) => throw null; + public void ToManaged(out System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg3Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback resMarshaler) => throw null; + public void ToManaged(out System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg3Marshaler) => throw null; + public void ToManaged(out System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg2Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback resMarshaler) => throw null; + public void ToManaged(out System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg2Marshaler) => throw null; + public void ToManaged(out System.Action value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToJSCallback arg1Marshaler) => throw null; + public void ToManaged(out System.Threading.Tasks.Task value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback marshaler) => throw null; + public void ToManaged(out System.Func value, System.Runtime.InteropServices.JavaScript.JSMarshalerArgument.ArgumentToManagedCallback resMarshaler) => throw null; + public void ToManagedBig(out System.Int64 value) => throw null; + public void ToManagedBig(out System.Int64? value) => throw null; + } + + public class JSMarshalerType + { + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Action() => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Action(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Action(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg2) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Action(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg2, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg3) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Array(System.Runtime.InteropServices.JavaScript.JSMarshalerType element) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType ArraySegment(System.Runtime.InteropServices.JavaScript.JSMarshalerType element) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType BigInt64 { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Boolean { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Byte { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Char { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType DateTime { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType DateTimeOffset { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Discard { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Double { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Exception { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Function(System.Runtime.InteropServices.JavaScript.JSMarshalerType result) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Function(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1, System.Runtime.InteropServices.JavaScript.JSMarshalerType result) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Function(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg2, System.Runtime.InteropServices.JavaScript.JSMarshalerType result) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Function(System.Runtime.InteropServices.JavaScript.JSMarshalerType arg1, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg2, System.Runtime.InteropServices.JavaScript.JSMarshalerType arg3, System.Runtime.InteropServices.JavaScript.JSMarshalerType result) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Int16 { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Int32 { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Int52 { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType IntPtr { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType JSObject { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Nullable(System.Runtime.InteropServices.JavaScript.JSMarshalerType primitive) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Object { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Single { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Span(System.Runtime.InteropServices.JavaScript.JSMarshalerType element) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType String { get => throw null; } + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Task() => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Task(System.Runtime.InteropServices.JavaScript.JSMarshalerType result) => throw null; + public static System.Runtime.InteropServices.JavaScript.JSMarshalerType Void { get => throw null; } + } + + public class JSObject : System.IDisposable + { + public void Dispose() => throw null; + public bool GetPropertyAsBoolean(string propertyName) => throw null; + public System.Byte[] GetPropertyAsByteArray(string propertyName) => throw null; + public double GetPropertyAsDouble(string propertyName) => throw null; + public int GetPropertyAsInt32(string propertyName) => throw null; + public System.Runtime.InteropServices.JavaScript.JSObject GetPropertyAsJSObject(string propertyName) => throw null; + public string GetPropertyAsString(string propertyName) => throw null; + public string GetTypeOfProperty(string propertyName) => throw null; + public bool HasProperty(string propertyName) => throw null; + public bool IsDisposed { get => throw null; } + public void SetProperty(string propertyName, System.Byte[] value) => throw null; + public void SetProperty(string propertyName, System.Runtime.InteropServices.JavaScript.JSObject value) => throw null; + public void SetProperty(string propertyName, bool value) => throw null; + public void SetProperty(string propertyName, double value) => throw null; + public void SetProperty(string propertyName, int value) => throw null; + public void SetProperty(string propertyName, string value) => throw null; + } + + public abstract class JSType + { + public class Any : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Array : System.Runtime.InteropServices.JavaScript.JSType where T : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class BigInt : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Boolean : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Date : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Discard : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Error : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Function : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Function : System.Runtime.InteropServices.JavaScript.JSType where T1 : System.Runtime.InteropServices.JavaScript.JSType where T2 : System.Runtime.InteropServices.JavaScript.JSType where T3 : System.Runtime.InteropServices.JavaScript.JSType where T4 : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Function : System.Runtime.InteropServices.JavaScript.JSType where T1 : System.Runtime.InteropServices.JavaScript.JSType where T2 : System.Runtime.InteropServices.JavaScript.JSType where T3 : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Function : System.Runtime.InteropServices.JavaScript.JSType where T1 : System.Runtime.InteropServices.JavaScript.JSType where T2 : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Function : System.Runtime.InteropServices.JavaScript.JSType where T : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class MemoryView : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Number : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Object : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Promise : System.Runtime.InteropServices.JavaScript.JSType where T : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class String : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + public class Void : System.Runtime.InteropServices.JavaScript.JSType + { + } + + + internal JSType() => throw null; + } + + } + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.RuntimeInformation.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.RuntimeInformation.cs deleted file mode 100644 index 1e3c126f61b..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.RuntimeInformation.cs +++ /dev/null @@ -1,50 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Runtime - { - namespace InteropServices - { - // Generated from `System.Runtime.InteropServices.Architecture` in `System.Runtime.InteropServices.RuntimeInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum Architecture : int - { - Arm = 2, - Arm64 = 3, - S390x = 5, - Wasm = 4, - X64 = 1, - X86 = 0, - } - - // Generated from `System.Runtime.InteropServices.OSPlatform` in `System.Runtime.InteropServices.RuntimeInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct OSPlatform : System.IEquatable - { - public static bool operator !=(System.Runtime.InteropServices.OSPlatform left, System.Runtime.InteropServices.OSPlatform right) => throw null; - public static bool operator ==(System.Runtime.InteropServices.OSPlatform left, System.Runtime.InteropServices.OSPlatform right) => throw null; - public static System.Runtime.InteropServices.OSPlatform Create(string osPlatform) => throw null; - public bool Equals(System.Runtime.InteropServices.OSPlatform other) => throw null; - public override bool Equals(object obj) => throw null; - public static System.Runtime.InteropServices.OSPlatform FreeBSD { get => throw null; } - public override int GetHashCode() => throw null; - public static System.Runtime.InteropServices.OSPlatform Linux { get => throw null; } - // Stub generator skipped constructor - public static System.Runtime.InteropServices.OSPlatform OSX { get => throw null; } - public override string ToString() => throw null; - public static System.Runtime.InteropServices.OSPlatform Windows { get => throw null; } - } - - // Generated from `System.Runtime.InteropServices.RuntimeInformation` in `System.Runtime.InteropServices.RuntimeInformation, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class RuntimeInformation - { - public static string FrameworkDescription { get => throw null; } - public static bool IsOSPlatform(System.Runtime.InteropServices.OSPlatform osPlatform) => throw null; - public static System.Runtime.InteropServices.Architecture OSArchitecture { get => throw null; } - public static string OSDescription { get => throw null; } - public static System.Runtime.InteropServices.Architecture ProcessArchitecture { get => throw null; } - public static string RuntimeIdentifier { get => throw null; } - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.cs index 4ae5bc38e04..5dd7c8a64ba 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.InteropServices.cs @@ -1,8 +1,8 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.InteropServices, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { - // Generated from `System.DataMisalignedException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataMisalignedException : System.SystemException { public DataMisalignedException() => throw null; @@ -10,7 +10,6 @@ namespace System public DataMisalignedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.DllNotFoundException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DllNotFoundException : System.TypeLoadException { public DllNotFoundException() => throw null; @@ -21,7 +20,6 @@ namespace System namespace IO { - // Generated from `System.IO.UnmanagedMemoryAccessor` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnmanagedMemoryAccessor : System.IDisposable { public bool CanRead { get => throw null; } @@ -71,14 +69,12 @@ namespace System { namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.IDispatchConstantAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IDispatchConstantAttribute : System.Runtime.CompilerServices.CustomConstantAttribute { public IDispatchConstantAttribute() => throw null; public override object Value { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.IUnknownConstantAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IUnknownConstantAttribute : System.Runtime.CompilerServices.CustomConstantAttribute { public IUnknownConstantAttribute() => throw null; @@ -88,14 +84,12 @@ namespace System } namespace InteropServices { - // Generated from `System.Runtime.InteropServices.AllowReversePInvokeCallsAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AllowReversePInvokeCallsAttribute : System.Attribute { public AllowReversePInvokeCallsAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ArrayWithOffset` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct ArrayWithOffset + public struct ArrayWithOffset : System.IEquatable { public static bool operator !=(System.Runtime.InteropServices.ArrayWithOffset a, System.Runtime.InteropServices.ArrayWithOffset b) => throw null; public static bool operator ==(System.Runtime.InteropServices.ArrayWithOffset a, System.Runtime.InteropServices.ArrayWithOffset b) => throw null; @@ -108,14 +102,12 @@ namespace System public int GetOffset() => throw null; } - // Generated from `System.Runtime.InteropServices.AutomationProxyAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AutomationProxyAttribute : System.Attribute { public AutomationProxyAttribute(bool val) => throw null; public bool Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.BStrWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BStrWrapper { public BStrWrapper(object value) => throw null; @@ -123,7 +115,6 @@ namespace System public string WrappedObject { get => throw null; } } - // Generated from `System.Runtime.InteropServices.BestFitMappingAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BestFitMappingAttribute : System.Attribute { public bool BestFitMapping { get => throw null; } @@ -131,7 +122,6 @@ namespace System public bool ThrowOnUnmappableChar; } - // Generated from `System.Runtime.InteropServices.CLong` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CLong : System.IEquatable { // Stub generator skipped constructor @@ -144,7 +134,6 @@ namespace System public System.IntPtr Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.COMException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class COMException : System.Runtime.InteropServices.ExternalException { public COMException() => throw null; @@ -155,7 +144,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Runtime.InteropServices.CULong` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CULong : System.IEquatable { // Stub generator skipped constructor @@ -168,7 +156,6 @@ namespace System public System.UIntPtr Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.CallingConvention` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CallingConvention : int { Cdecl = 2, @@ -178,7 +165,6 @@ namespace System Winapi = 1, } - // Generated from `System.Runtime.InteropServices.ClassInterfaceAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ClassInterfaceAttribute : System.Attribute { public ClassInterfaceAttribute(System.Runtime.InteropServices.ClassInterfaceType classInterfaceType) => throw null; @@ -186,7 +172,6 @@ namespace System public System.Runtime.InteropServices.ClassInterfaceType Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ClassInterfaceType` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ClassInterfaceType : int { AutoDispatch = 1, @@ -194,14 +179,12 @@ namespace System None = 0, } - // Generated from `System.Runtime.InteropServices.CoClassAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CoClassAttribute : System.Attribute { public System.Type CoClass { get => throw null; } public CoClassAttribute(System.Type coClass) => throw null; } - // Generated from `System.Runtime.InteropServices.CollectionsMarshal` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CollectionsMarshal { public static System.Span AsSpan(System.Collections.Generic.List list) => throw null; @@ -209,14 +192,12 @@ namespace System public static TValue GetValueRefOrNullRef(System.Collections.Generic.Dictionary dictionary, TKey key) => throw null; } - // Generated from `System.Runtime.InteropServices.ComAliasNameAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComAliasNameAttribute : System.Attribute { public ComAliasNameAttribute(string alias) => throw null; public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ComAwareEventInfo` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComAwareEventInfo : System.Reflection.EventInfo { public override void AddEventHandler(object target, System.Delegate handler) => throw null; @@ -238,7 +219,6 @@ namespace System public override void RemoveEventHandler(object target, System.Delegate handler) => throw null; } - // Generated from `System.Runtime.InteropServices.ComCompatibleVersionAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComCompatibleVersionAttribute : System.Attribute { public int BuildNumber { get => throw null; } @@ -248,20 +228,17 @@ namespace System public int RevisionNumber { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ComConversionLossAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComConversionLossAttribute : System.Attribute { public ComConversionLossAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ComDefaultInterfaceAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComDefaultInterfaceAttribute : System.Attribute { public ComDefaultInterfaceAttribute(System.Type defaultInterface) => throw null; public System.Type Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ComEventInterfaceAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComEventInterfaceAttribute : System.Attribute { public ComEventInterfaceAttribute(System.Type SourceInterface, System.Type EventProvider) => throw null; @@ -269,20 +246,17 @@ namespace System public System.Type SourceInterface { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ComEventsHelper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ComEventsHelper { public static void Combine(object rcw, System.Guid iid, int dispid, System.Delegate d) => throw null; public static System.Delegate Remove(object rcw, System.Guid iid, int dispid, System.Delegate d) => throw null; } - // Generated from `System.Runtime.InteropServices.ComImportAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComImportAttribute : System.Attribute { public ComImportAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ComInterfaceType` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ComInterfaceType : int { InterfaceIsDual = 0, @@ -291,7 +265,6 @@ namespace System InterfaceIsIUnknown = 1, } - // Generated from `System.Runtime.InteropServices.ComMemberType` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ComMemberType : int { Method = 0, @@ -299,13 +272,11 @@ namespace System PropSet = 2, } - // Generated from `System.Runtime.InteropServices.ComRegisterFunctionAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComRegisterFunctionAttribute : System.Attribute { public ComRegisterFunctionAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ComSourceInterfacesAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComSourceInterfacesAttribute : System.Attribute { public ComSourceInterfacesAttribute(System.Type sourceInterface) => throw null; @@ -316,16 +287,13 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ComUnregisterFunctionAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComUnregisterFunctionAttribute : System.Attribute { public ComUnregisterFunctionAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ComWrappers` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ComWrappers { - // Generated from `System.Runtime.InteropServices.ComWrappers+ComInterfaceDispatch` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ComInterfaceDispatch { // Stub generator skipped constructor @@ -334,7 +302,6 @@ namespace System } - // Generated from `System.Runtime.InteropServices.ComWrappers+ComInterfaceEntry` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ComInterfaceEntry { // Stub generator skipped constructor @@ -356,7 +323,6 @@ namespace System protected abstract void ReleaseObjects(System.Collections.IEnumerable objects); } - // Generated from `System.Runtime.InteropServices.CreateComInterfaceFlags` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CreateComInterfaceFlags : int { @@ -365,7 +331,6 @@ namespace System TrackerSupport = 2, } - // Generated from `System.Runtime.InteropServices.CreateObjectFlags` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CreateObjectFlags : int { @@ -376,7 +341,6 @@ namespace System Unwrap = 8, } - // Generated from `System.Runtime.InteropServices.CurrencyWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CurrencyWrapper { public CurrencyWrapper(System.Decimal obj) => throw null; @@ -384,14 +348,12 @@ namespace System public System.Decimal WrappedObject { get => throw null; } } - // Generated from `System.Runtime.InteropServices.CustomQueryInterfaceMode` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CustomQueryInterfaceMode : int { Allow = 1, Ignore = 0, } - // Generated from `System.Runtime.InteropServices.CustomQueryInterfaceResult` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CustomQueryInterfaceResult : int { Failed = 2, @@ -399,42 +361,36 @@ namespace System NotHandled = 1, } - // Generated from `System.Runtime.InteropServices.DefaultCharSetAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultCharSetAttribute : System.Attribute { public System.Runtime.InteropServices.CharSet CharSet { get => throw null; } public DefaultCharSetAttribute(System.Runtime.InteropServices.CharSet charSet) => throw null; } - // Generated from `System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultDllImportSearchPathsAttribute : System.Attribute { public DefaultDllImportSearchPathsAttribute(System.Runtime.InteropServices.DllImportSearchPath paths) => throw null; public System.Runtime.InteropServices.DllImportSearchPath Paths { get => throw null; } } - // Generated from `System.Runtime.InteropServices.DefaultParameterValueAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultParameterValueAttribute : System.Attribute { public DefaultParameterValueAttribute(object value) => throw null; public object Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.DispIdAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DispIdAttribute : System.Attribute { public DispIdAttribute(int dispId) => throw null; public int Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.DispatchWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DispatchWrapper { public DispatchWrapper(object obj) => throw null; public object WrappedObject { get => throw null; } } - // Generated from `System.Runtime.InteropServices.DllImportAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DllImportAttribute : System.Attribute { public bool BestFitMapping; @@ -449,10 +405,8 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.DllImportResolver` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.IntPtr DllImportResolver(string libraryName, System.Reflection.Assembly assembly, System.Runtime.InteropServices.DllImportSearchPath? searchPath); - // Generated from `System.Runtime.InteropServices.DllImportSearchPath` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DllImportSearchPath : int { @@ -465,13 +419,11 @@ namespace System UserDirectories = 1024, } - // Generated from `System.Runtime.InteropServices.DynamicInterfaceCastableImplementationAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicInterfaceCastableImplementationAttribute : System.Attribute { public DynamicInterfaceCastableImplementationAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.ErrorWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ErrorWrapper { public int ErrorCode { get => throw null; } @@ -480,14 +432,12 @@ namespace System public ErrorWrapper(object errorCode) => throw null; } - // Generated from `System.Runtime.InteropServices.GuidAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GuidAttribute : System.Attribute { public GuidAttribute(string guid) => throw null; public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.HandleCollector` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HandleCollector { public void Add() => throw null; @@ -500,7 +450,6 @@ namespace System public void Remove() => throw null; } - // Generated from `System.Runtime.InteropServices.HandleRef` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct HandleRef { public System.IntPtr Handle { get => throw null; } @@ -511,19 +460,16 @@ namespace System public static explicit operator System.IntPtr(System.Runtime.InteropServices.HandleRef value) => throw null; } - // Generated from `System.Runtime.InteropServices.ICustomAdapter` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomAdapter { object GetUnderlyingObject(); } - // Generated from `System.Runtime.InteropServices.ICustomFactory` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomFactory { System.MarshalByRefObject CreateInstance(System.Type serverType); } - // Generated from `System.Runtime.InteropServices.ICustomMarshaler` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomMarshaler { void CleanUpManagedData(object ManagedObj); @@ -533,27 +479,23 @@ namespace System object MarshalNativeToManaged(System.IntPtr pNativeData); } - // Generated from `System.Runtime.InteropServices.ICustomQueryInterface` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomQueryInterface { System.Runtime.InteropServices.CustomQueryInterfaceResult GetInterface(ref System.Guid iid, out System.IntPtr ppv); } - // Generated from `System.Runtime.InteropServices.IDynamicInterfaceCastable` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDynamicInterfaceCastable { System.RuntimeTypeHandle GetInterfaceImplementation(System.RuntimeTypeHandle interfaceType); bool IsInterfaceImplemented(System.RuntimeTypeHandle interfaceType, bool throwIfNotImplemented); } - // Generated from `System.Runtime.InteropServices.ImportedFromTypeLibAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImportedFromTypeLibAttribute : System.Attribute { public ImportedFromTypeLibAttribute(string tlbFile) => throw null; public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.InterfaceTypeAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InterfaceTypeAttribute : System.Attribute { public InterfaceTypeAttribute(System.Runtime.InteropServices.ComInterfaceType interfaceType) => throw null; @@ -561,7 +503,6 @@ namespace System public System.Runtime.InteropServices.ComInterfaceType Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.InvalidComObjectException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidComObjectException : System.SystemException { public InvalidComObjectException() => throw null; @@ -570,7 +511,6 @@ namespace System public InvalidComObjectException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.InvalidOleVariantTypeException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidOleVariantTypeException : System.SystemException { public InvalidOleVariantTypeException() => throw null; @@ -579,14 +519,22 @@ namespace System public InvalidOleVariantTypeException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.LCIDConversionAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LCIDConversionAttribute : System.Attribute { public LCIDConversionAttribute(int lcid) => throw null; public int Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class LibraryImportAttribute : System.Attribute + { + public string EntryPoint { get => throw null; set => throw null; } + public LibraryImportAttribute(string libraryName) => throw null; + public string LibraryName { get => throw null; } + public bool SetLastError { get => throw null; set => throw null; } + public System.Runtime.InteropServices.StringMarshalling StringMarshalling { get => throw null; set => throw null; } + public System.Type StringMarshallingCustomType { get => throw null; set => throw null; } + } + public class ManagedToNativeComInteropStubAttribute : System.Attribute { public System.Type ClassType { get => throw null; } @@ -594,7 +542,6 @@ namespace System public string MethodName { get => throw null; } } - // Generated from `System.Runtime.InteropServices.Marshal` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Marshal { public static int AddRef(System.IntPtr pUnk) => throw null; @@ -652,6 +599,7 @@ namespace System public static System.IntPtr GetIDispatchForObject(object o) => throw null; public static System.IntPtr GetIUnknownForObject(object o) => throw null; public static int GetLastPInvokeError() => throw null; + public static string GetLastPInvokeErrorMessage() => throw null; public static int GetLastSystemError() => throw null; public static int GetLastWin32Error() => throw null; public static void GetNativeVariantForObject(object obj, System.IntPtr pDstNativeVariant) => throw null; @@ -661,6 +609,7 @@ namespace System public static T GetObjectForNativeVariant(System.IntPtr pSrcNativeVariant) => throw null; public static object[] GetObjectsForNativeVariants(System.IntPtr aSrcNativeVariant, int cVars) => throw null; public static T[] GetObjectsForNativeVariants(System.IntPtr aSrcNativeVariant, int cVars) => throw null; + public static string GetPInvokeErrorMessage(int error) => throw null; public static int GetStartComSlot(System.Type t) => throw null; public static System.Type GetTypeFromCLSID(System.Guid clsid) => throw null; public static string GetTypeInfoName(System.Runtime.InteropServices.ComTypes.ITypeInfo typeInfo) => throw null; @@ -760,7 +709,6 @@ namespace System public static void ZeroFreeGlobalAllocUnicode(System.IntPtr s) => throw null; } - // Generated from `System.Runtime.InteropServices.MarshalAsAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MarshalAsAttribute : System.Attribute { public System.Runtime.InteropServices.UnmanagedType ArraySubType; @@ -777,7 +725,6 @@ namespace System public System.Runtime.InteropServices.UnmanagedType Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.MarshalDirectiveException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MarshalDirectiveException : System.SystemException { public MarshalDirectiveException() => throw null; @@ -786,24 +733,234 @@ namespace System public MarshalDirectiveException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.NFloat` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct NFloat : System.IEquatable + public struct NFloat : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryFloatingPointIeee754, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { + static bool System.Numerics.IEqualityOperators.operator !=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IModulusOperators.operator %(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IBitwiseOperators.operator &(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IMultiplyOperators.operator *(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IUnaryPlusOperators.operator +(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IAdditionOperators.operator +(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IIncrementOperators.operator ++(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IUnaryNegationOperators.operator -(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.ISubtractionOperators.operator -(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IDecrementOperators.operator --(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IDivisionOperators.operator /(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + public static System.Runtime.InteropServices.NFloat Abs(System.Runtime.InteropServices.NFloat value) => throw null; + public static System.Runtime.InteropServices.NFloat Acos(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat AcosPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Acosh(System.Runtime.InteropServices.NFloat x) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.Runtime.InteropServices.NFloat Asin(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat AsinPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Asinh(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Atan(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Atan2(System.Runtime.InteropServices.NFloat y, System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Atan2Pi(System.Runtime.InteropServices.NFloat y, System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat AtanPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Atanh(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat BitDecrement(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat BitIncrement(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Cbrt(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Ceiling(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Clamp(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat min, System.Runtime.InteropServices.NFloat max) => throw null; + public int CompareTo(System.Runtime.InteropServices.NFloat other) => throw null; + public int CompareTo(object obj) => throw null; + public static System.Runtime.InteropServices.NFloat CopySign(System.Runtime.InteropServices.NFloat value, System.Runtime.InteropServices.NFloat sign) => throw null; + public static System.Runtime.InteropServices.NFloat Cos(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat CosPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Cosh(System.Runtime.InteropServices.NFloat x) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointConstants.E { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointIeee754.Epsilon { get => throw null; } public bool Equals(System.Runtime.InteropServices.NFloat other) => throw null; public override bool Equals(object obj) => throw null; + public static System.Runtime.InteropServices.NFloat Exp(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Exp10(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Exp10M1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Exp2(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Exp2M1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat ExpM1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Floor(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat FusedMultiplyAdd(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right, System.Runtime.InteropServices.NFloat addend) => throw null; + int System.Numerics.IFloatingPoint.GetExponentByteCount() => throw null; + int System.Numerics.IFloatingPoint.GetExponentShortestBitLength() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandBitLength() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandByteCount() => throw null; + public static System.Runtime.InteropServices.NFloat Hypot(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static int ILogB(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Ieee754Remainder(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + public static bool IsCanonical(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsComplexNumber(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsEvenInteger(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsFinite(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsImaginaryNumber(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsInfinity(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsInteger(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsNaN(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsNegative(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsNegativeInfinity(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsNormal(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsOddInteger(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsPositive(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsPositiveInfinity(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsPow2(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsRealNumber(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsSubnormal(System.Runtime.InteropServices.NFloat value) => throw null; + public static bool IsZero(System.Runtime.InteropServices.NFloat value) => throw null; + public static System.Runtime.InteropServices.NFloat Log(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Log(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat newBase) => throw null; + public static System.Runtime.InteropServices.NFloat Log10(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Log10P1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Log2(System.Runtime.InteropServices.NFloat value) => throw null; + public static System.Runtime.InteropServices.NFloat Log2P1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat LogP1(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Max(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MaxMagnitude(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MaxMagnitudeNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MaxNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Runtime.InteropServices.NFloat Min(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MinMagnitude(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MinMagnitudeNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + public static System.Runtime.InteropServices.NFloat MinNumber(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } // Stub generator skipped constructor public NFloat(double value) => throw null; public NFloat(float value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointIeee754.NaN { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointIeee754.NegativeInfinity { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointIeee754.NegativeZero { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.INumberBase.One { get => throw null; } + public static System.Runtime.InteropServices.NFloat Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; + public static System.Runtime.InteropServices.NFloat Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static System.Runtime.InteropServices.NFloat Parse(string s) => throw null; + public static System.Runtime.InteropServices.NFloat Parse(string s, System.IFormatProvider provider) => throw null; + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style) => throw null; + public static System.Runtime.InteropServices.NFloat Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointConstants.Pi { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointIeee754.PositiveInfinity { get => throw null; } + public static System.Runtime.InteropServices.NFloat Pow(System.Runtime.InteropServices.NFloat x, System.Runtime.InteropServices.NFloat y) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Runtime.InteropServices.NFloat ReciprocalEstimate(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat ReciprocalSqrtEstimate(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat RootN(System.Runtime.InteropServices.NFloat x, int n) => throw null; + public static System.Runtime.InteropServices.NFloat Round(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Round(System.Runtime.InteropServices.NFloat x, System.MidpointRounding mode) => throw null; + public static System.Runtime.InteropServices.NFloat Round(System.Runtime.InteropServices.NFloat x, int digits) => throw null; + public static System.Runtime.InteropServices.NFloat Round(System.Runtime.InteropServices.NFloat x, int digits, System.MidpointRounding mode) => throw null; + public static System.Runtime.InteropServices.NFloat ScaleB(System.Runtime.InteropServices.NFloat x, int n) => throw null; + public static int Sign(System.Runtime.InteropServices.NFloat value) => throw null; + public static System.Runtime.InteropServices.NFloat Sin(System.Runtime.InteropServices.NFloat x) => throw null; + public static (System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat) SinCos(System.Runtime.InteropServices.NFloat x) => throw null; + public static (System.Runtime.InteropServices.NFloat, System.Runtime.InteropServices.NFloat) SinCosPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat SinPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Sinh(System.Runtime.InteropServices.NFloat x) => throw null; + public static int Size { get => throw null; } + public static System.Runtime.InteropServices.NFloat Sqrt(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Tan(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat TanPi(System.Runtime.InteropServices.NFloat x) => throw null; + public static System.Runtime.InteropServices.NFloat Tanh(System.Runtime.InteropServices.NFloat x) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IFloatingPointConstants.Tau { get => throw null; } public override string ToString() => throw null; + public string ToString(System.IFormatProvider provider) => throw null; + public string ToString(string format) => throw null; + public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.Runtime.InteropServices.NFloat Truncate(System.Runtime.InteropServices.NFloat x) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Runtime.InteropServices.NFloat result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Runtime.InteropServices.NFloat result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Runtime.InteropServices.NFloat result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Runtime.InteropServices.NFloat value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Runtime.InteropServices.NFloat value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Runtime.InteropServices.NFloat value, out TOther result) => throw null; + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Runtime.InteropServices.NFloat result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Runtime.InteropServices.NFloat result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, out System.Runtime.InteropServices.NFloat result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Runtime.InteropServices.NFloat result) => throw null; + public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Runtime.InteropServices.NFloat result) => throw null; + public static bool TryParse(string s, out System.Runtime.InteropServices.NFloat result) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten) => throw null; public double Value { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.INumberBase.Zero { get => throw null; } + static System.Runtime.InteropServices.NFloat System.Numerics.IBitwiseOperators.operator ^(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IMultiplyOperators.operator checked *(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IAdditionOperators.operator checked +(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IIncrementOperators.operator checked ++(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IUnaryNegationOperators.operator checked -(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.ISubtractionOperators.operator checked -(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IDecrementOperators.operator checked --(System.Runtime.InteropServices.NFloat value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IDivisionOperators.operator checked /(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + public static explicit operator checked System.Byte(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.Char(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.Int128(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.Int16(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.Int64(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.IntPtr(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.SByte(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.UInt128(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.UInt16(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.UInt32(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.UInt64(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked System.UIntPtr(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator checked int(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Runtime.InteropServices.NFloat(System.Int128 value) => throw null; + public static explicit operator System.Byte(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Char(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Decimal(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Half(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Int128(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Int16(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Int64(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.IntPtr(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.SByte(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.UInt128(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.UInt16(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.UInt32(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.UInt64(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.UIntPtr(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator float(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator int(System.Runtime.InteropServices.NFloat value) => throw null; + public static explicit operator System.Runtime.InteropServices.NFloat(System.UInt128 value) => throw null; + public static explicit operator System.Runtime.InteropServices.NFloat(System.Decimal value) => throw null; + public static explicit operator System.Runtime.InteropServices.NFloat(double value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.Half value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.IntPtr value) => throw null; + public static implicit operator double(System.Runtime.InteropServices.NFloat value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.UIntPtr value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.Byte value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.Char value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(float value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(int value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.Int64 value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.SByte value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.Int16 value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.UInt32 value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.UInt64 value) => throw null; + public static implicit operator System.Runtime.InteropServices.NFloat(System.UInt16 value) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IBitwiseOperators.operator |(System.Runtime.InteropServices.NFloat left, System.Runtime.InteropServices.NFloat right) => throw null; + static System.Runtime.InteropServices.NFloat System.Numerics.IBitwiseOperators.operator ~(System.Runtime.InteropServices.NFloat value) => throw null; } - // Generated from `System.Runtime.InteropServices.NativeLibrary` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class NativeLibrary { public static void Free(System.IntPtr handle) => throw null; public static System.IntPtr GetExport(System.IntPtr handle, string name) => throw null; + public static System.IntPtr GetMainProgramHandle() => throw null; public static System.IntPtr Load(string libraryPath) => throw null; public static System.IntPtr Load(string libraryName, System.Reflection.Assembly assembly, System.Runtime.InteropServices.DllImportSearchPath? searchPath) => throw null; public static void SetDllImportResolver(System.Reflection.Assembly assembly, System.Runtime.InteropServices.DllImportResolver resolver) => throw null; @@ -812,7 +969,6 @@ namespace System public static bool TryLoad(string libraryPath, out System.IntPtr handle) => throw null; } - // Generated from `System.Runtime.InteropServices.NativeMemory` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class NativeMemory { unsafe public static void* AlignedAlloc(System.UIntPtr byteCount, System.UIntPtr alignment) => throw null; @@ -822,17 +978,18 @@ namespace System unsafe public static void* Alloc(System.UIntPtr elementCount, System.UIntPtr elementSize) => throw null; unsafe public static void* AllocZeroed(System.UIntPtr byteCount) => throw null; unsafe public static void* AllocZeroed(System.UIntPtr elementCount, System.UIntPtr elementSize) => throw null; + unsafe public static void Clear(void* ptr, System.UIntPtr byteCount) => throw null; + unsafe public static void Copy(void* source, void* destination, System.UIntPtr byteCount) => throw null; + unsafe public static void Fill(void* ptr, System.UIntPtr byteCount, System.Byte value) => throw null; unsafe public static void Free(void* ptr) => throw null; unsafe public static void* Realloc(void* ptr, System.UIntPtr byteCount) => throw null; } - // Generated from `System.Runtime.InteropServices.OptionalAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OptionalAttribute : System.Attribute { public OptionalAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.PosixSignal` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PosixSignal : int { SIGCHLD = -5, @@ -847,7 +1004,6 @@ namespace System SIGWINCH = -7, } - // Generated from `System.Runtime.InteropServices.PosixSignalContext` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PosixSignalContext { public bool Cancel { get => throw null; set => throw null; } @@ -855,7 +1011,6 @@ namespace System public System.Runtime.InteropServices.PosixSignal Signal { get => throw null; } } - // Generated from `System.Runtime.InteropServices.PosixSignalRegistration` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PosixSignalRegistration : System.IDisposable { public static System.Runtime.InteropServices.PosixSignalRegistration Create(System.Runtime.InteropServices.PosixSignal signal, System.Action handler) => throw null; @@ -863,13 +1018,11 @@ namespace System // ERR: Stub generator didn't handle member: ~PosixSignalRegistration } - // Generated from `System.Runtime.InteropServices.PreserveSigAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PreserveSigAttribute : System.Attribute { public PreserveSigAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.PrimaryInteropAssemblyAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PrimaryInteropAssemblyAttribute : System.Attribute { public int MajorVersion { get => throw null; } @@ -877,14 +1030,12 @@ namespace System public PrimaryInteropAssemblyAttribute(int major, int minor) => throw null; } - // Generated from `System.Runtime.InteropServices.ProgIdAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ProgIdAttribute : System.Attribute { public ProgIdAttribute(string progId) => throw null; public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.RuntimeEnvironment` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class RuntimeEnvironment { public static bool FromGlobalAccessCache(System.Reflection.Assembly a) => throw null; @@ -895,7 +1046,6 @@ namespace System public static string SystemConfigurationFile { get => throw null; } } - // Generated from `System.Runtime.InteropServices.SEHException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SEHException : System.Runtime.InteropServices.ExternalException { public virtual bool CanResume() => throw null; @@ -905,7 +1055,6 @@ namespace System public SEHException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.SafeArrayRankMismatchException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeArrayRankMismatchException : System.SystemException { public SafeArrayRankMismatchException() => throw null; @@ -914,7 +1063,6 @@ namespace System public SafeArrayRankMismatchException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.SafeArrayTypeMismatchException` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeArrayTypeMismatchException : System.SystemException { public SafeArrayTypeMismatchException() => throw null; @@ -923,13 +1071,18 @@ namespace System public SafeArrayTypeMismatchException(string message, System.Exception inner) => throw null; } - // Generated from `System.Runtime.InteropServices.StandardOleMarshalObject` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StandardOleMarshalObject : System.MarshalByRefObject { protected StandardOleMarshalObject() => throw null; } - // Generated from `System.Runtime.InteropServices.TypeIdentifierAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public enum StringMarshalling : int + { + Custom = 0, + Utf16 = 2, + Utf8 = 1, + } + public class TypeIdentifierAttribute : System.Attribute { public string Identifier { get => throw null; } @@ -938,7 +1091,6 @@ namespace System public TypeIdentifierAttribute(string scope, string identifier) => throw null; } - // Generated from `System.Runtime.InteropServices.TypeLibFuncAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLibFuncAttribute : System.Attribute { public TypeLibFuncAttribute(System.Runtime.InteropServices.TypeLibFuncFlags flags) => throw null; @@ -946,7 +1098,6 @@ namespace System public System.Runtime.InteropServices.TypeLibFuncFlags Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.TypeLibFuncFlags` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TypeLibFuncFlags : int { @@ -965,14 +1116,12 @@ namespace System FUsesGetLastError = 128, } - // Generated from `System.Runtime.InteropServices.TypeLibImportClassAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLibImportClassAttribute : System.Attribute { public TypeLibImportClassAttribute(System.Type importClass) => throw null; public string Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.TypeLibTypeAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLibTypeAttribute : System.Attribute { public TypeLibTypeAttribute(System.Runtime.InteropServices.TypeLibTypeFlags flags) => throw null; @@ -980,7 +1129,6 @@ namespace System public System.Runtime.InteropServices.TypeLibTypeFlags Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.TypeLibTypeFlags` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TypeLibTypeFlags : int { @@ -1000,7 +1148,6 @@ namespace System FReverseBind = 8192, } - // Generated from `System.Runtime.InteropServices.TypeLibVarAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLibVarAttribute : System.Attribute { public TypeLibVarAttribute(System.Runtime.InteropServices.TypeLibVarFlags flags) => throw null; @@ -1008,7 +1155,6 @@ namespace System public System.Runtime.InteropServices.TypeLibVarFlags Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.TypeLibVarFlags` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TypeLibVarFlags : int { @@ -1027,7 +1173,6 @@ namespace System FUiDefault = 512, } - // Generated from `System.Runtime.InteropServices.TypeLibVersionAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLibVersionAttribute : System.Attribute { public int MajorVersion { get => throw null; } @@ -1035,21 +1180,18 @@ namespace System public TypeLibVersionAttribute(int major, int minor) => throw null; } - // Generated from `System.Runtime.InteropServices.UnknownWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnknownWrapper { public UnknownWrapper(object obj) => throw null; public object WrappedObject { get => throw null; } } - // Generated from `System.Runtime.InteropServices.UnmanagedCallConvAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnmanagedCallConvAttribute : System.Attribute { public System.Type[] CallConvs; public UnmanagedCallConvAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.UnmanagedCallersOnlyAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnmanagedCallersOnlyAttribute : System.Attribute { public System.Type[] CallConvs; @@ -1057,7 +1199,6 @@ namespace System public UnmanagedCallersOnlyAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnmanagedFunctionPointerAttribute : System.Attribute { public bool BestFitMapping; @@ -1068,50 +1209,6 @@ namespace System public UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention callingConvention) => throw null; } - // Generated from `System.Runtime.InteropServices.UnmanagedType` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum UnmanagedType : int - { - AnsiBStr = 35, - AsAny = 40, - BStr = 19, - Bool = 2, - ByValArray = 30, - ByValTStr = 23, - Currency = 15, - CustomMarshaler = 44, - Error = 45, - FunctionPtr = 38, - HString = 47, - I1 = 3, - I2 = 5, - I4 = 7, - I8 = 9, - IDispatch = 26, - IInspectable = 46, - IUnknown = 25, - Interface = 28, - LPArray = 42, - LPStr = 20, - LPStruct = 43, - LPTStr = 22, - LPUTF8Str = 48, - LPWStr = 21, - R4 = 11, - R8 = 12, - SafeArray = 29, - Struct = 27, - SysInt = 31, - SysUInt = 32, - TBStr = 36, - U1 = 4, - U2 = 6, - U4 = 8, - U8 = 10, - VBByRefStr = 34, - VariantBool = 37, - } - - // Generated from `System.Runtime.InteropServices.VarEnum` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum VarEnum : int { VT_ARRAY = 8192, @@ -1160,7 +1257,6 @@ namespace System VT_VOID = 24, } - // Generated from `System.Runtime.InteropServices.VariantWrapper` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VariantWrapper { public VariantWrapper(object obj) => throw null; @@ -1169,7 +1265,6 @@ namespace System namespace ComTypes { - // Generated from `System.Runtime.InteropServices.ComTypes.ADVF` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ADVF : int { @@ -1182,7 +1277,6 @@ namespace System ADVF_PRIMEFIRST = 2, } - // Generated from `System.Runtime.InteropServices.ComTypes.BINDPTR` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BINDPTR { // Stub generator skipped constructor @@ -1191,7 +1285,6 @@ namespace System public System.IntPtr lpvardesc; } - // Generated from `System.Runtime.InteropServices.ComTypes.BIND_OPTS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct BIND_OPTS { // Stub generator skipped constructor @@ -1201,7 +1294,6 @@ namespace System public int grfMode; } - // Generated from `System.Runtime.InteropServices.ComTypes.CALLCONV` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CALLCONV : int { CC_CDECL = 1, @@ -1216,7 +1308,6 @@ namespace System CC_SYSCALL = 6, } - // Generated from `System.Runtime.InteropServices.ComTypes.CONNECTDATA` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CONNECTDATA { // Stub generator skipped constructor @@ -1224,14 +1315,12 @@ namespace System public object pUnk; } - // Generated from `System.Runtime.InteropServices.ComTypes.DATADIR` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DATADIR : int { DATADIR_GET = 1, DATADIR_SET = 2, } - // Generated from `System.Runtime.InteropServices.ComTypes.DESCKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DESCKIND : int { DESCKIND_FUNCDESC = 1, @@ -1242,7 +1331,6 @@ namespace System DESCKIND_VARDESC = 2, } - // Generated from `System.Runtime.InteropServices.ComTypes.DISPPARAMS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DISPPARAMS { // Stub generator skipped constructor @@ -1252,7 +1340,6 @@ namespace System public System.IntPtr rgvarg; } - // Generated from `System.Runtime.InteropServices.ComTypes.DVASPECT` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DVASPECT : int { @@ -1262,10 +1349,8 @@ namespace System DVASPECT_THUMBNAIL = 2, } - // Generated from `System.Runtime.InteropServices.ComTypes.ELEMDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ELEMDESC { - // Generated from `System.Runtime.InteropServices.ComTypes.ELEMDESC+DESCUNION` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DESCUNION { // Stub generator skipped constructor @@ -1279,7 +1364,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.TYPEDESC tdesc; } - // Generated from `System.Runtime.InteropServices.ComTypes.EXCEPINFO` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct EXCEPINFO { // Stub generator skipped constructor @@ -1294,7 +1378,6 @@ namespace System public System.Int16 wReserved; } - // Generated from `System.Runtime.InteropServices.ComTypes.FILETIME` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FILETIME { // Stub generator skipped constructor @@ -1302,7 +1385,6 @@ namespace System public int dwLowDateTime; } - // Generated from `System.Runtime.InteropServices.ComTypes.FORMATETC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FORMATETC { // Stub generator skipped constructor @@ -1313,7 +1395,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.TYMED tymed; } - // Generated from `System.Runtime.InteropServices.ComTypes.FUNCDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FUNCDESC { // Stub generator skipped constructor @@ -1331,7 +1412,6 @@ namespace System public System.Int16 wFuncFlags; } - // Generated from `System.Runtime.InteropServices.ComTypes.FUNCFLAGS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FUNCFLAGS : short { @@ -1350,7 +1430,6 @@ namespace System FUNCFLAG_FUSESGETLASTERROR = 128, } - // Generated from `System.Runtime.InteropServices.ComTypes.FUNCKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FUNCKIND : int { FUNC_DISPATCH = 4, @@ -1360,7 +1439,6 @@ namespace System FUNC_VIRTUAL = 0, } - // Generated from `System.Runtime.InteropServices.ComTypes.IAdviseSink` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAdviseSink { void OnClose(); @@ -1370,7 +1448,6 @@ namespace System void OnViewChange(int aspect, int index); } - // Generated from `System.Runtime.InteropServices.ComTypes.IBindCtx` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IBindCtx { void EnumObjectParam(out System.Runtime.InteropServices.ComTypes.IEnumString ppenum); @@ -1385,7 +1462,6 @@ namespace System void SetBindOptions(ref System.Runtime.InteropServices.ComTypes.BIND_OPTS pbindopts); } - // Generated from `System.Runtime.InteropServices.ComTypes.IConnectionPoint` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IConnectionPoint { void Advise(object pUnkSink, out int pdwCookie); @@ -1395,14 +1471,12 @@ namespace System void Unadvise(int dwCookie); } - // Generated from `System.Runtime.InteropServices.ComTypes.IConnectionPointContainer` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IConnectionPointContainer { void EnumConnectionPoints(out System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints ppEnum); void FindConnectionPoint(ref System.Guid riid, out System.Runtime.InteropServices.ComTypes.IConnectionPoint ppCP); } - // Generated from `System.Runtime.InteropServices.ComTypes.IDLDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct IDLDESC { // Stub generator skipped constructor @@ -1410,7 +1484,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.IDLFLAG wIDLFlags; } - // Generated from `System.Runtime.InteropServices.ComTypes.IDLFLAG` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum IDLFLAG : short { @@ -1421,7 +1494,6 @@ namespace System IDLFLAG_NONE = 0, } - // Generated from `System.Runtime.InteropServices.ComTypes.IDataObject` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataObject { int DAdvise(ref System.Runtime.InteropServices.ComTypes.FORMATETC pFormatetc, System.Runtime.InteropServices.ComTypes.ADVF advf, System.Runtime.InteropServices.ComTypes.IAdviseSink adviseSink, out int connection); @@ -1435,7 +1507,6 @@ namespace System void SetData(ref System.Runtime.InteropServices.ComTypes.FORMATETC formatIn, ref System.Runtime.InteropServices.ComTypes.STGMEDIUM medium, bool release); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumConnectionPoints { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumConnectionPoints ppenum); @@ -1444,7 +1515,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumConnections` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumConnections { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumConnections ppenum); @@ -1453,7 +1523,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumFORMATETC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumFORMATETC { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumFORMATETC newEnum); @@ -1462,7 +1531,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumMoniker` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumMoniker { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumMoniker ppenum); @@ -1471,7 +1539,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumSTATDATA` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumSTATDATA { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumSTATDATA newEnum); @@ -1480,7 +1547,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumString` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumString { void Clone(out System.Runtime.InteropServices.ComTypes.IEnumString ppenum); @@ -1489,7 +1555,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IEnumVARIANT` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumVARIANT { System.Runtime.InteropServices.ComTypes.IEnumVARIANT Clone(); @@ -1498,7 +1563,6 @@ namespace System int Skip(int celt); } - // Generated from `System.Runtime.InteropServices.ComTypes.IMPLTYPEFLAGS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum IMPLTYPEFLAGS : int { @@ -1508,7 +1572,6 @@ namespace System IMPLTYPEFLAG_FSOURCE = 2, } - // Generated from `System.Runtime.InteropServices.ComTypes.IMoniker` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IMoniker { void BindToObject(System.Runtime.InteropServices.ComTypes.IBindCtx pbc, System.Runtime.InteropServices.ComTypes.IMoniker pmkToLeft, ref System.Guid riidResult, out object ppvResult); @@ -1533,7 +1596,6 @@ namespace System void Save(System.Runtime.InteropServices.ComTypes.IStream pStm, bool fClearDirty); } - // Generated from `System.Runtime.InteropServices.ComTypes.INVOKEKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum INVOKEKIND : int { @@ -1543,7 +1605,6 @@ namespace System INVOKE_PROPERTYPUTREF = 8, } - // Generated from `System.Runtime.InteropServices.ComTypes.IPersistFile` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IPersistFile { void GetClassID(out System.Guid pClassID); @@ -1554,7 +1615,6 @@ namespace System void SaveCompleted(string pszFileName); } - // Generated from `System.Runtime.InteropServices.ComTypes.IRunningObjectTable` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IRunningObjectTable { void EnumRunning(out System.Runtime.InteropServices.ComTypes.IEnumMoniker ppenumMoniker); @@ -1566,7 +1626,6 @@ namespace System void Revoke(int dwRegister); } - // Generated from `System.Runtime.InteropServices.ComTypes.IStream` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStream { void Clone(out System.Runtime.InteropServices.ComTypes.IStream ppstm); @@ -1582,14 +1641,12 @@ namespace System void Write(System.Byte[] pv, int cb, System.IntPtr pcbWritten); } - // Generated from `System.Runtime.InteropServices.ComTypes.ITypeComp` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeComp { void Bind(string szName, int lHashVal, System.Int16 wFlags, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo, out System.Runtime.InteropServices.ComTypes.DESCKIND pDescKind, out System.Runtime.InteropServices.ComTypes.BINDPTR pBindPtr); void BindType(string szName, int lHashVal, out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo, out System.Runtime.InteropServices.ComTypes.ITypeComp ppTComp); } - // Generated from `System.Runtime.InteropServices.ComTypes.ITypeInfo` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeInfo { void AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out System.IntPtr ppv); @@ -1613,7 +1670,6 @@ namespace System void ReleaseVarDesc(System.IntPtr pVarDesc); } - // Generated from `System.Runtime.InteropServices.ComTypes.ITypeInfo2` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeInfo2 : System.Runtime.InteropServices.ComTypes.ITypeInfo { void AddressOfMember(int memid, System.Runtime.InteropServices.ComTypes.INVOKEKIND invKind, out System.IntPtr ppv); @@ -1652,7 +1708,6 @@ namespace System void ReleaseVarDesc(System.IntPtr pVarDesc); } - // Generated from `System.Runtime.InteropServices.ComTypes.ITypeLib` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeLib { void FindName(string szNameBuf, int lHashVal, System.Runtime.InteropServices.ComTypes.ITypeInfo[] ppTInfo, int[] rgMemId, ref System.Int16 pcFound); @@ -1667,7 +1722,6 @@ namespace System void ReleaseTLibAttr(System.IntPtr pTLibAttr); } - // Generated from `System.Runtime.InteropServices.ComTypes.ITypeLib2` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITypeLib2 : System.Runtime.InteropServices.ComTypes.ITypeLib { void FindName(string szNameBuf, int lHashVal, System.Runtime.InteropServices.ComTypes.ITypeInfo[] ppTInfo, int[] rgMemId, ref System.Int16 pcFound); @@ -1686,7 +1740,6 @@ namespace System void ReleaseTLibAttr(System.IntPtr pTLibAttr); } - // Generated from `System.Runtime.InteropServices.ComTypes.LIBFLAGS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum LIBFLAGS : short { @@ -1696,7 +1749,6 @@ namespace System LIBFLAG_FRESTRICTED = 1, } - // Generated from `System.Runtime.InteropServices.ComTypes.PARAMDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PARAMDESC { // Stub generator skipped constructor @@ -1704,7 +1756,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.PARAMFLAG wParamFlags; } - // Generated from `System.Runtime.InteropServices.ComTypes.PARAMFLAG` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PARAMFLAG : short { @@ -1718,7 +1769,6 @@ namespace System PARAMFLAG_NONE = 0, } - // Generated from `System.Runtime.InteropServices.ComTypes.STATDATA` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct STATDATA { // Stub generator skipped constructor @@ -1728,7 +1778,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.FORMATETC formatetc; } - // Generated from `System.Runtime.InteropServices.ComTypes.STATSTG` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct STATSTG { // Stub generator skipped constructor @@ -1745,7 +1794,6 @@ namespace System public int type; } - // Generated from `System.Runtime.InteropServices.ComTypes.STGMEDIUM` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct STGMEDIUM { // Stub generator skipped constructor @@ -1754,7 +1802,6 @@ namespace System public System.IntPtr unionmember; } - // Generated from `System.Runtime.InteropServices.ComTypes.SYSKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SYSKIND : int { SYS_MAC = 2, @@ -1763,7 +1810,6 @@ namespace System SYS_WIN64 = 3, } - // Generated from `System.Runtime.InteropServices.ComTypes.TYMED` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TYMED : int { @@ -1777,7 +1823,6 @@ namespace System TYMED_NULL = 0, } - // Generated from `System.Runtime.InteropServices.ComTypes.TYPEATTR` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TYPEATTR { public const int MEMBER_ID_NIL = default; @@ -1802,7 +1847,6 @@ namespace System public System.Runtime.InteropServices.ComTypes.TYPEFLAGS wTypeFlags; } - // Generated from `System.Runtime.InteropServices.ComTypes.TYPEDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TYPEDESC { // Stub generator skipped constructor @@ -1810,7 +1854,6 @@ namespace System public System.Int16 vt; } - // Generated from `System.Runtime.InteropServices.ComTypes.TYPEFLAGS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TYPEFLAGS : short { @@ -1831,7 +1874,6 @@ namespace System TYPEFLAG_FREVERSEBIND = 8192, } - // Generated from `System.Runtime.InteropServices.ComTypes.TYPEKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TYPEKIND : int { TKIND_ALIAS = 6, @@ -1845,7 +1887,6 @@ namespace System TKIND_UNION = 7, } - // Generated from `System.Runtime.InteropServices.ComTypes.TYPELIBATTR` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TYPELIBATTR { // Stub generator skipped constructor @@ -1857,10 +1898,8 @@ namespace System public System.Int16 wMinorVerNum; } - // Generated from `System.Runtime.InteropServices.ComTypes.VARDESC` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct VARDESC { - // Generated from `System.Runtime.InteropServices.ComTypes.VARDESC+DESCUNION` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DESCUNION { // Stub generator skipped constructor @@ -1878,7 +1917,6 @@ namespace System public System.Int16 wVarFlags; } - // Generated from `System.Runtime.InteropServices.ComTypes.VARFLAGS` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum VARFLAGS : short { @@ -1897,7 +1935,6 @@ namespace System VARFLAG_FUIDEFAULT = 512, } - // Generated from `System.Runtime.InteropServices.ComTypes.VARKIND` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum VARKIND : int { VAR_CONST = 2, @@ -1906,13 +1943,134 @@ namespace System VAR_STATIC = 1, } + } + namespace Marshalling + { + public static class AnsiStringMarshaller + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(string managed, System.Span buffer) => throw null; + // Stub generator skipped constructor + unsafe public System.Byte* ToUnmanaged() => throw null; + } + + + unsafe public static string ConvertToManaged(System.Byte* unmanaged) => throw null; + unsafe public static System.Byte* ConvertToUnmanaged(string managed) => throw null; + unsafe public static void Free(System.Byte* unmanaged) => throw null; + } + + public static class ArrayMarshaller where TUnmanagedElement : unmanaged + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(T[] array, System.Span buffer) => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public TUnmanagedElement GetPinnableReference() => throw null; + public static T GetPinnableReference(T[] array) => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + // Stub generator skipped constructor + unsafe public TUnmanagedElement* ToUnmanaged() => throw null; + } + + + unsafe public static T[] AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T[] managed, out int numElements) => throw null; + unsafe public static void Free(TUnmanagedElement* unmanaged) => throw null; + public static System.Span GetManagedValuesDestination(T[] managed) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(T[] managed) => throw null; + unsafe public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements) => throw null; + } + + public static class BStrStringMarshaller + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(string managed, System.Span buffer) => throw null; + // Stub generator skipped constructor + unsafe public System.UInt16* ToUnmanaged() => throw null; + } + + + unsafe public static string ConvertToManaged(System.UInt16* unmanaged) => throw null; + unsafe public static System.UInt16* ConvertToUnmanaged(string managed) => throw null; + unsafe public static void Free(System.UInt16* unmanaged) => throw null; + } + + public class MarshalUsingAttribute : System.Attribute + { + public int ConstantElementCount { get => throw null; set => throw null; } + public string CountElementName { get => throw null; set => throw null; } + public int ElementIndirectionDepth { get => throw null; set => throw null; } + public MarshalUsingAttribute() => throw null; + public MarshalUsingAttribute(System.Type nativeType) => throw null; + public System.Type NativeType { get => throw null; } + public const string ReturnsCountValue = default; + } + + public static class PointerArrayMarshaller where T : unmanaged where TUnmanagedElement : unmanaged + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + unsafe public void FromManaged(T*[] array, System.Span buffer) => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public TUnmanagedElement GetPinnableReference() => throw null; + unsafe public static System.Byte GetPinnableReference(T*[] array) => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + // Stub generator skipped constructor + unsafe public TUnmanagedElement* ToUnmanaged() => throw null; + } + + + unsafe public static T*[] AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static TUnmanagedElement* AllocateContainerForUnmanagedElements(T*[] managed, out int numElements) => throw null; + unsafe public static void Free(TUnmanagedElement* unmanaged) => throw null; + unsafe public static System.Span GetManagedValuesDestination(T*[] managed) => throw null; + unsafe public static System.ReadOnlySpan GetManagedValuesSource(T*[] managed) => throw null; + unsafe public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanagedValue, int numElements) => throw null; + } + + public static class Utf16StringMarshaller + { + unsafe public static string ConvertToManaged(System.UInt16* unmanaged) => throw null; + unsafe public static System.UInt16* ConvertToUnmanaged(string managed) => throw null; + unsafe public static void Free(System.UInt16* unmanaged) => throw null; + public static System.Char GetPinnableReference(string str) => throw null; + } + + public static class Utf8StringMarshaller + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(string managed, System.Span buffer) => throw null; + // Stub generator skipped constructor + unsafe public System.Byte* ToUnmanaged() => throw null; + } + + + unsafe public static string ConvertToManaged(System.Byte* unmanaged) => throw null; + unsafe public static System.Byte* ConvertToUnmanaged(string managed) => throw null; + unsafe public static void Free(System.Byte* unmanaged) => throw null; + } + } namespace ObjectiveC { - // Generated from `System.Runtime.InteropServices.ObjectiveC.ObjectiveCMarshal` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ObjectiveCMarshal { - // Generated from `System.Runtime.InteropServices.ObjectiveC.ObjectiveCMarshal+MessageSendFunction` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MessageSendFunction : int { MsgSend = 0, @@ -1923,7 +2081,6 @@ namespace System } - // Generated from `System.Runtime.InteropServices.ObjectiveC.ObjectiveCMarshal+UnhandledExceptionPropagationHandler` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` unsafe public delegate delegate* unmanaged UnhandledExceptionPropagationHandler(System.Exception exception, System.RuntimeMethodHandle lastMethod, out System.IntPtr context); @@ -1933,7 +2090,6 @@ namespace System public static void SetMessageSendPendingException(System.Exception exception) => throw null; } - // Generated from `System.Runtime.InteropServices.ObjectiveC.ObjectiveCTrackedTypeAttribute` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectiveCTrackedTypeAttribute : System.Attribute { public ObjectiveCTrackedTypeAttribute() => throw null; @@ -1944,7 +2100,6 @@ namespace System } namespace Security { - // Generated from `System.Security.SecureString` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecureString : System.IDisposable { public void AppendChar(System.Char c) => throw null; @@ -1961,7 +2116,6 @@ namespace System public void SetAt(int index, System.Char c) => throw null; } - // Generated from `System.Security.SecureStringMarshal` in `System.Runtime.InteropServices, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class SecureStringMarshal { public static System.IntPtr SecureStringToCoTaskMemAnsi(System.Security.SecureString s) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Intrinsics.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Intrinsics.cs index 9a719c531c8..f210bdeba43 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Intrinsics.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Intrinsics.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Intrinsics, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,15 +7,19 @@ namespace System { namespace Intrinsics { - // Generated from `System.Runtime.Intrinsics.Vector128` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Vector128 { - public static System.Runtime.Intrinsics.Vector128 As(this System.Runtime.Intrinsics.Vector128 vector) where T : struct where U : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Abs(System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Add(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 AndNot(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 As(this System.Runtime.Intrinsics.Vector128 vector) where TFrom : struct where TTo : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsByte(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsDouble(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsInt16(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsInt32(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsInt64(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 AsNInt(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 AsNUInt(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsSByte(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsSingle(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 AsUInt16(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; @@ -28,6 +33,24 @@ namespace System public static System.Numerics.Vector3 AsVector3(this System.Runtime.Intrinsics.Vector128 value) => throw null; public static System.Numerics.Vector4 AsVector4(this System.Runtime.Intrinsics.Vector128 value) => throw null; public static System.Numerics.Vector AsVector(this System.Runtime.Intrinsics.Vector128 value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 BitwiseAnd(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 BitwiseOr(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Ceiling(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 Ceiling(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConditionalSelect(System.Runtime.Intrinsics.Vector128 condition, System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToDouble(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToInt32(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToInt64(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToSingle(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt32(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 ConvertToUInt64(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector128 vector, T[] destination, int startIndex) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector128 Create(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; public static System.Runtime.Intrinsics.Vector128 Create(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; public static System.Runtime.Intrinsics.Vector128 Create(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; @@ -58,6 +81,12 @@ namespace System public static System.Runtime.Intrinsics.Vector128 Create(System.UInt64 e0, System.UInt64 e1) => throw null; public static System.Runtime.Intrinsics.Vector128 Create(System.UInt16 value) => throw null; public static System.Runtime.Intrinsics.Vector128 Create(System.UInt16 e0, System.UInt16 e1, System.UInt16 e2, System.UInt16 e3, System.UInt16 e4, System.UInt16 e5, System.UInt16 e6, System.UInt16 e7) => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(System.ReadOnlySpan values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(T value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(T[] values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Create(T[] values, int index) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalar(double value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalar(float value) => throw null; @@ -68,6 +97,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalar(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(double value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(float value) => throw null; @@ -78,39 +109,150 @@ namespace System public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector128 CreateScalarUnsafe(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector128 Divide(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static T Dot(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Equals(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool EqualsAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool EqualsAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.UInt32 ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Floor(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 Floor(System.Runtime.Intrinsics.Vector128 vector) => throw null; public static T GetElement(this System.Runtime.Intrinsics.Vector128 vector, int index) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 GetLower(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 GetUpper(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 GreaterThan(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool GreaterThanAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool GreaterThanAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool IsHardwareAccelerated { get => throw null; } + public static System.Runtime.Intrinsics.Vector128 LessThan(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool LessThanAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool LessThanAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 LessThanOrEqual(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static bool LessThanOrEqualAny(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + unsafe public static System.Runtime.Intrinsics.Vector128 Load(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector128 LoadAligned(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector128 LoadAlignedNonTemporal(T* source) where T : unmanaged => throw null; + public static System.Runtime.Intrinsics.Vector128 LoadUnsafe(ref T source) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 LoadUnsafe(ref T source, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Max(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Min(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Multiply(T left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, T right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Multiply(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Narrow(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; + public static System.Runtime.Intrinsics.Vector128 Negate(System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 OnesComplement(System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftLeft(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 ShiftRightLogical(System.Runtime.Intrinsics.Vector128 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Shuffle(System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector128 indices) => throw null; + public static System.Runtime.Intrinsics.Vector128 Sqrt(System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + unsafe public static void Store(this System.Runtime.Intrinsics.Vector128 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAligned(this System.Runtime.Intrinsics.Vector128 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAlignedNonTemporal(this System.Runtime.Intrinsics.Vector128 source, T* destination) where T : unmanaged => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector128 source, ref T destination) where T : struct => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector128 source, ref T destination, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Subtract(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; + public static T Sum(System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static T ToScalar(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 ToVector256(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 ToVector256Unsafe(this System.Runtime.Intrinsics.Vector128 vector) where T : struct => throw null; + public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector128 vector, System.Span destination) where T : struct => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; + public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) Widen(System.Runtime.Intrinsics.Vector128 source) => throw null; public static System.Runtime.Intrinsics.Vector128 WithElement(this System.Runtime.Intrinsics.Vector128 vector, int index, T value) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 WithLower(this System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector64 value) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 WithUpper(this System.Runtime.Intrinsics.Vector128 vector, System.Runtime.Intrinsics.Vector64 value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector128 Xor(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) where T : struct => throw null; } - // Generated from `System.Runtime.Intrinsics.Vector128<>` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Vector128 : System.IEquatable> where T : struct { + public static bool operator !=(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator &(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator *(T left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator *(System.Runtime.Intrinsics.Vector128 left, T right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator *(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator +(System.Runtime.Intrinsics.Vector128 value) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator +(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator -(System.Runtime.Intrinsics.Vector128 vector) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator -(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator /(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static bool operator ==(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; public static System.Runtime.Intrinsics.Vector128 AllBitsSet { get => throw null; } public static int Count { get => throw null; } public bool Equals(System.Runtime.Intrinsics.Vector128 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public static bool IsSupported { get => throw null; } + public T this[int index] { get => throw null; } public override string ToString() => throw null; // Stub generator skipped constructor public static System.Runtime.Intrinsics.Vector128 Zero { get => throw null; } + public static System.Runtime.Intrinsics.Vector128 operator ^(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator |(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; + public static System.Runtime.Intrinsics.Vector128 operator ~(System.Runtime.Intrinsics.Vector128 vector) => throw null; } - // Generated from `System.Runtime.Intrinsics.Vector256` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Vector256 { - public static System.Runtime.Intrinsics.Vector256 As(this System.Runtime.Intrinsics.Vector256 vector) where T : struct where U : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Abs(System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Add(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 AndNot(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 As(this System.Runtime.Intrinsics.Vector256 vector) where TFrom : struct where TTo : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsByte(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsDouble(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsInt16(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsInt32(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsInt64(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 AsNInt(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 AsNUInt(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsSByte(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsSingle(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsUInt16(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; @@ -118,6 +260,24 @@ namespace System public static System.Runtime.Intrinsics.Vector256 AsUInt64(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 AsVector256(this System.Numerics.Vector value) where T : struct => throw null; public static System.Numerics.Vector AsVector(this System.Runtime.Intrinsics.Vector256 value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 BitwiseAnd(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 BitwiseOr(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Ceiling(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 Ceiling(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConditionalSelect(System.Runtime.Intrinsics.Vector256 condition, System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToDouble(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToInt32(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToInt64(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToSingle(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt32(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 ConvertToUInt64(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector256 vector, T[] destination, int startIndex) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; public static System.Runtime.Intrinsics.Vector256 Create(System.Runtime.Intrinsics.Vector128 lower, System.Runtime.Intrinsics.Vector128 upper) => throw null; @@ -148,6 +308,12 @@ namespace System public static System.Runtime.Intrinsics.Vector256 Create(System.UInt64 e0, System.UInt64 e1, System.UInt64 e2, System.UInt64 e3) => throw null; public static System.Runtime.Intrinsics.Vector256 Create(System.UInt16 value) => throw null; public static System.Runtime.Intrinsics.Vector256 Create(System.UInt16 e0, System.UInt16 e1, System.UInt16 e2, System.UInt16 e3, System.UInt16 e4, System.UInt16 e5, System.UInt16 e6, System.UInt16 e7, System.UInt16 e8, System.UInt16 e9, System.UInt16 e10, System.UInt16 e11, System.UInt16 e12, System.UInt16 e13, System.UInt16 e14, System.UInt16 e15) => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(System.ReadOnlySpan values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(T value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(T[] values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Create(T[] values, int index) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalar(double value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalar(float value) => throw null; @@ -158,6 +324,8 @@ namespace System public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalar(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(double value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(float value) => throw null; @@ -168,42 +336,171 @@ namespace System public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector256 CreateScalarUnsafe(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector256 Divide(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static T Dot(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Equals(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool EqualsAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool EqualsAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.UInt32 ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Floor(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 Floor(System.Runtime.Intrinsics.Vector256 vector) => throw null; public static T GetElement(this System.Runtime.Intrinsics.Vector256 vector, int index) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 GetLower(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 GetUpper(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 GreaterThan(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool GreaterThanAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool GreaterThanAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool IsHardwareAccelerated { get => throw null; } + public static System.Runtime.Intrinsics.Vector256 LessThan(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool LessThanAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool LessThanAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 LessThanOrEqual(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static bool LessThanOrEqualAny(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + unsafe public static System.Runtime.Intrinsics.Vector256 Load(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector256 LoadAligned(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector256 LoadAlignedNonTemporal(T* source) where T : unmanaged => throw null; + public static System.Runtime.Intrinsics.Vector256 LoadUnsafe(ref T source) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 LoadUnsafe(ref T source, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Max(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Min(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Multiply(T left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, T right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Multiply(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Narrow(System.Runtime.Intrinsics.Vector256 lower, System.Runtime.Intrinsics.Vector256 upper) => throw null; + public static System.Runtime.Intrinsics.Vector256 Negate(System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 OnesComplement(System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftLeft(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 ShiftRightLogical(System.Runtime.Intrinsics.Vector256 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Shuffle(System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector256 indices) => throw null; + public static System.Runtime.Intrinsics.Vector256 Sqrt(System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + unsafe public static void Store(this System.Runtime.Intrinsics.Vector256 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAligned(this System.Runtime.Intrinsics.Vector256 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAlignedNonTemporal(this System.Runtime.Intrinsics.Vector256 source, T* destination) where T : unmanaged => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector256 source, ref T destination) where T : struct => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector256 source, ref T destination, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Subtract(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; + public static T Sum(System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; public static T ToScalar(this System.Runtime.Intrinsics.Vector256 vector) where T : struct => throw null; + public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector256 vector, System.Span destination) where T : struct => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; + public static (System.Runtime.Intrinsics.Vector256, System.Runtime.Intrinsics.Vector256) Widen(System.Runtime.Intrinsics.Vector256 source) => throw null; public static System.Runtime.Intrinsics.Vector256 WithElement(this System.Runtime.Intrinsics.Vector256 vector, int index, T value) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 WithLower(this System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector128 value) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector256 WithUpper(this System.Runtime.Intrinsics.Vector256 vector, System.Runtime.Intrinsics.Vector128 value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector256 Xor(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) where T : struct => throw null; } - // Generated from `System.Runtime.Intrinsics.Vector256<>` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Vector256 : System.IEquatable> where T : struct { + public static bool operator !=(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator &(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator *(T left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator *(System.Runtime.Intrinsics.Vector256 left, T right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator *(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator +(System.Runtime.Intrinsics.Vector256 value) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator +(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator -(System.Runtime.Intrinsics.Vector256 vector) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator -(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator /(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static bool operator ==(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; public static System.Runtime.Intrinsics.Vector256 AllBitsSet { get => throw null; } public static int Count { get => throw null; } public bool Equals(System.Runtime.Intrinsics.Vector256 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public static bool IsSupported { get => throw null; } + public T this[int index] { get => throw null; } public override string ToString() => throw null; // Stub generator skipped constructor public static System.Runtime.Intrinsics.Vector256 Zero { get => throw null; } + public static System.Runtime.Intrinsics.Vector256 operator ^(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator |(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; + public static System.Runtime.Intrinsics.Vector256 operator ~(System.Runtime.Intrinsics.Vector256 vector) => throw null; } - // Generated from `System.Runtime.Intrinsics.Vector64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Vector64 { - public static System.Runtime.Intrinsics.Vector64 As(this System.Runtime.Intrinsics.Vector64 vector) where T : struct where U : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Abs(System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Add(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 AndNot(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 As(this System.Runtime.Intrinsics.Vector64 vector) where TFrom : struct where TTo : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsByte(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsDouble(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsInt16(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsInt32(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsInt64(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 AsNInt(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 AsNUInt(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsSByte(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsSingle(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsUInt16(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsUInt32(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector64 AsUInt64(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 BitwiseAnd(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 BitwiseOr(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Ceiling(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 Ceiling(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConditionalSelect(System.Runtime.Intrinsics.Vector64 condition, System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToDouble(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToInt32(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToInt64(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToSingle(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt32(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 ConvertToUInt64(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination) where T : struct => throw null; + public static void CopyTo(this System.Runtime.Intrinsics.Vector64 vector, T[] destination, int startIndex) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector64 Create(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector64 Create(System.Byte e0, System.Byte e1, System.Byte e2, System.Byte e3, System.Byte e4, System.Byte e5, System.Byte e6, System.Byte e7) => throw null; public static System.Runtime.Intrinsics.Vector64 Create(double value) => throw null; @@ -221,6 +518,12 @@ namespace System public static System.Runtime.Intrinsics.Vector64 Create(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector64 Create(System.UInt16 value) => throw null; public static System.Runtime.Intrinsics.Vector64 Create(System.UInt16 e0, System.UInt16 e1, System.UInt16 e2, System.UInt16 e3) => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(System.ReadOnlySpan values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(T value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(T[] values) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Create(T[] values, int index) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalar(double value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalar(float value) => throw null; @@ -231,6 +534,8 @@ namespace System public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.UInt64 value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalar(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.IntPtr value) => throw null; + public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.UIntPtr value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.Byte value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(float value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(int value) => throw null; @@ -238,32 +543,134 @@ namespace System public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.Int16 value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.UInt32 value) => throw null; public static System.Runtime.Intrinsics.Vector64 CreateScalarUnsafe(System.UInt16 value) => throw null; + public static System.Runtime.Intrinsics.Vector64 Divide(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static T Dot(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Equals(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool EqualsAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool EqualsAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.UInt32 ExtractMostSignificantBits(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Floor(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 Floor(System.Runtime.Intrinsics.Vector64 vector) => throw null; public static T GetElement(this System.Runtime.Intrinsics.Vector64 vector, int index) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 GreaterThan(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool GreaterThanAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool GreaterThanAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 GreaterThanOrEqual(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool GreaterThanOrEqualAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool IsHardwareAccelerated { get => throw null; } + public static System.Runtime.Intrinsics.Vector64 LessThan(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool LessThanAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool LessThanAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 LessThanOrEqual(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool LessThanOrEqualAll(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static bool LessThanOrEqualAny(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + unsafe public static System.Runtime.Intrinsics.Vector64 Load(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector64 LoadAligned(T* source) where T : unmanaged => throw null; + unsafe public static System.Runtime.Intrinsics.Vector64 LoadAlignedNonTemporal(T* source) where T : unmanaged => throw null; + public static System.Runtime.Intrinsics.Vector64 LoadUnsafe(ref T source) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 LoadUnsafe(ref T source, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Max(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Min(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Multiply(T left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, T right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Multiply(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Narrow(System.Runtime.Intrinsics.Vector64 lower, System.Runtime.Intrinsics.Vector64 upper) => throw null; + public static System.Runtime.Intrinsics.Vector64 Negate(System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 OnesComplement(System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftLeft(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightArithmetic(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 ShiftRightLogical(System.Runtime.Intrinsics.Vector64 vector, int shiftCount) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Shuffle(System.Runtime.Intrinsics.Vector64 vector, System.Runtime.Intrinsics.Vector64 indices) => throw null; + public static System.Runtime.Intrinsics.Vector64 Sqrt(System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + unsafe public static void Store(this System.Runtime.Intrinsics.Vector64 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAligned(this System.Runtime.Intrinsics.Vector64 source, T* destination) where T : unmanaged => throw null; + unsafe public static void StoreAlignedNonTemporal(this System.Runtime.Intrinsics.Vector64 source, T* destination) where T : unmanaged => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector64 source, ref T destination) where T : struct => throw null; + public static void StoreUnsafe(this System.Runtime.Intrinsics.Vector64 source, ref T destination, System.UIntPtr elementOffset) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Subtract(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; + public static T Sum(System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static T ToScalar(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 ToVector128(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; public static System.Runtime.Intrinsics.Vector128 ToVector128Unsafe(this System.Runtime.Intrinsics.Vector64 vector) where T : struct => throw null; + public static bool TryCopyTo(this System.Runtime.Intrinsics.Vector64 vector, System.Span destination) where T : struct => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; + public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) Widen(System.Runtime.Intrinsics.Vector64 source) => throw null; public static System.Runtime.Intrinsics.Vector64 WithElement(this System.Runtime.Intrinsics.Vector64 vector, int index, T value) where T : struct => throw null; + public static System.Runtime.Intrinsics.Vector64 Xor(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) where T : struct => throw null; } - // Generated from `System.Runtime.Intrinsics.Vector64<>` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Vector64 : System.IEquatable> where T : struct { + public static bool operator !=(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator &(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator *(T left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator *(System.Runtime.Intrinsics.Vector64 left, T right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator *(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator +(System.Runtime.Intrinsics.Vector64 value) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator +(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator -(System.Runtime.Intrinsics.Vector64 vector) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator -(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator /(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static bool operator ==(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; public static System.Runtime.Intrinsics.Vector64 AllBitsSet { get => throw null; } public static int Count { get => throw null; } public bool Equals(System.Runtime.Intrinsics.Vector64 other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; + public static bool IsSupported { get => throw null; } + public T this[int index] { get => throw null; } public override string ToString() => throw null; // Stub generator skipped constructor public static System.Runtime.Intrinsics.Vector64 Zero { get => throw null; } + public static System.Runtime.Intrinsics.Vector64 operator ^(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator |(System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right) => throw null; + public static System.Runtime.Intrinsics.Vector64 operator ~(System.Runtime.Intrinsics.Vector64 vector) => throw null; } namespace Arm { - // Generated from `System.Runtime.Intrinsics.Arm.AdvSimd` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class AdvSimd : System.Runtime.Intrinsics.Arm.ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.AdvSimd+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { public static System.Runtime.Intrinsics.Vector128 Abs(System.Runtime.Intrinsics.Vector128 value) => throw null; @@ -503,6 +910,52 @@ namespace System unsafe public static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(double* address) => throw null; unsafe public static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(System.Int64* address) => throw null; unsafe public static System.Runtime.Intrinsics.Vector128 LoadAndReplicateToVector128(System.UInt64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64NonTemporal(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64NonTemporal(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairScalarVector64NonTemporal(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.Byte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(double* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.Int64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.SByte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.Int16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.UInt64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128(System.UInt16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.Byte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(double* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.Int64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.SByte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.Int16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.UInt64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector128, System.Runtime.Intrinsics.Vector128) LoadPairVector128NonTemporal(System.UInt16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.Byte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(double* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.Int64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.SByte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.Int16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.UInt64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64(System.UInt16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.Byte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(double* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(float* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(int* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.Int64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.SByte* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.Int16* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.UInt32* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.UInt64* address) => throw null; + unsafe public static (System.Runtime.Intrinsics.Vector64, System.Runtime.Intrinsics.Vector64) LoadPairVector64NonTemporal(System.UInt16* address) => throw null; public static System.Runtime.Intrinsics.Vector128 Max(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; public static System.Runtime.Intrinsics.Vector64 MaxAcross(System.Runtime.Intrinsics.Vector128 value) => throw null; public static System.Runtime.Intrinsics.Vector64 MaxAcross(System.Runtime.Intrinsics.Vector128 value) => throw null; @@ -2476,10 +2929,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 ZeroExtendWideningUpper(System.Runtime.Intrinsics.Vector128 value) => throw null; } - // Generated from `System.Runtime.Intrinsics.Arm.Aes` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Aes : System.Runtime.Intrinsics.Arm.ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.Aes+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { public static bool IsSupported { get => throw null; } @@ -2497,10 +2948,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 PolynomialMultiplyWideningUpper(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.Arm.ArmBase` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.ArmBase+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 { internal Arm64() => throw null; @@ -2522,12 +2971,11 @@ namespace System public static int LeadingZeroCount(System.UInt32 value) => throw null; public static int ReverseElementBits(int value) => throw null; public static System.UInt32 ReverseElementBits(System.UInt32 value) => throw null; + public static void Yield() => throw null; } - // Generated from `System.Runtime.Intrinsics.Arm.Crc32` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Crc32 : System.Runtime.Intrinsics.Arm.ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.Crc32+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { public static System.UInt32 ComputeCrc32(System.UInt32 crc, System.UInt64 data) => throw null; @@ -2545,10 +2993,8 @@ namespace System public static bool IsSupported { get => throw null; } } - // Generated from `System.Runtime.Intrinsics.Arm.Dp` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Dp : System.Runtime.Intrinsics.Arm.AdvSimd { - // Generated from `System.Runtime.Intrinsics.Arm.Dp+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.AdvSimd.Arm64 { public static bool IsSupported { get => throw null; } @@ -2570,10 +3016,8 @@ namespace System public static bool IsSupported { get => throw null; } } - // Generated from `System.Runtime.Intrinsics.Arm.Rdm` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Rdm : System.Runtime.Intrinsics.Arm.AdvSimd { - // Generated from `System.Runtime.Intrinsics.Arm.Rdm+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.AdvSimd.Arm64 { public static bool IsSupported { get => throw null; } @@ -2619,10 +3063,8 @@ namespace System public static System.Runtime.Intrinsics.Vector64 MultiplyRoundedDoublingBySelectedScalarAndSubtractSaturateHigh(System.Runtime.Intrinsics.Vector64 minuend, System.Runtime.Intrinsics.Vector64 left, System.Runtime.Intrinsics.Vector64 right, System.Byte rightIndex) => throw null; } - // Generated from `System.Runtime.Intrinsics.Arm.Sha1` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sha1 : System.Runtime.Intrinsics.Arm.ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.Sha1+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { public static bool IsSupported { get => throw null; } @@ -2638,10 +3080,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 ScheduleUpdate1(System.Runtime.Intrinsics.Vector128 tw0_3, System.Runtime.Intrinsics.Vector128 w12_15) => throw null; } - // Generated from `System.Runtime.Intrinsics.Arm.Sha256` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sha256 : System.Runtime.Intrinsics.Arm.ArmBase { - // Generated from `System.Runtime.Intrinsics.Arm.Sha256+Arm64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Arm64 : System.Runtime.Intrinsics.Arm.ArmBase.Arm64 { public static bool IsSupported { get => throw null; } @@ -2658,10 +3098,8 @@ namespace System } namespace X86 { - // Generated from `System.Runtime.Intrinsics.X86.Aes` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Aes : System.Runtime.Intrinsics.X86.Sse2 { - // Generated from `System.Runtime.Intrinsics.X86.Aes+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse2.X64 { public static bool IsSupported { get => throw null; } @@ -2677,10 +3115,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 KeygenAssist(System.Runtime.Intrinsics.Vector128 value, System.Byte control) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Avx` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Avx : System.Runtime.Intrinsics.X86.Sse42 { - // Generated from `System.Runtime.Intrinsics.X86.Avx+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse42.X64 { public static bool IsSupported { get => throw null; } @@ -2935,10 +3371,8 @@ namespace System public static System.Runtime.Intrinsics.Vector256 Xor(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Avx2` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Avx2 : System.Runtime.Intrinsics.X86.Avx { - // Generated from `System.Runtime.Intrinsics.X86.Avx2+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Avx.X64 { public static bool IsSupported { get => throw null; } @@ -3343,10 +3777,8 @@ namespace System public static System.Runtime.Intrinsics.Vector256 Xor(System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.AvxVnni` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class AvxVnni : System.Runtime.Intrinsics.X86.Avx2 { - // Generated from `System.Runtime.Intrinsics.X86.AvxVnni+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Avx2.X64 { public static bool IsSupported { get => throw null; } @@ -3364,10 +3796,8 @@ namespace System public static System.Runtime.Intrinsics.Vector256 MultiplyWideningAndAddSaturate(System.Runtime.Intrinsics.Vector256 addend, System.Runtime.Intrinsics.Vector256 left, System.Runtime.Intrinsics.Vector256 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Bmi1` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Bmi1 : System.Runtime.Intrinsics.X86.X86Base { - // Generated from `System.Runtime.Intrinsics.X86.Bmi1+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 { public static System.UInt64 AndNot(System.UInt64 left, System.UInt64 right) => throw null; @@ -3391,10 +3821,8 @@ namespace System public static System.UInt32 TrailingZeroCount(System.UInt32 value) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Bmi2` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Bmi2 : System.Runtime.Intrinsics.X86.X86Base { - // Generated from `System.Runtime.Intrinsics.X86.Bmi2+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 { public static bool IsSupported { get => throw null; } @@ -3414,7 +3842,6 @@ namespace System public static System.UInt32 ZeroHighBits(System.UInt32 value, System.UInt32 index) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.FloatComparisonMode` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum FloatComparisonMode : byte { OrderedEqualNonSignaling = 0, @@ -3451,10 +3878,8 @@ namespace System UnorderedTrueSignaling = 31, } - // Generated from `System.Runtime.Intrinsics.X86.Fma` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Fma : System.Runtime.Intrinsics.X86.Avx { - // Generated from `System.Runtime.Intrinsics.X86.Fma+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Avx.X64 { public static bool IsSupported { get => throw null; } @@ -3496,10 +3921,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 MultiplySubtractScalar(System.Runtime.Intrinsics.Vector128 a, System.Runtime.Intrinsics.Vector128 b, System.Runtime.Intrinsics.Vector128 c) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Lzcnt` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Lzcnt : System.Runtime.Intrinsics.X86.X86Base { - // Generated from `System.Runtime.Intrinsics.X86.Lzcnt+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 { public static bool IsSupported { get => throw null; } @@ -3511,10 +3934,8 @@ namespace System public static System.UInt32 LeadingZeroCount(System.UInt32 value) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Pclmulqdq` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Pclmulqdq : System.Runtime.Intrinsics.X86.Sse2 { - // Generated from `System.Runtime.Intrinsics.X86.Pclmulqdq+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse2.X64 { public static bool IsSupported { get => throw null; } @@ -3526,10 +3947,8 @@ namespace System public static bool IsSupported { get => throw null; } } - // Generated from `System.Runtime.Intrinsics.X86.Popcnt` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Popcnt : System.Runtime.Intrinsics.X86.Sse42 { - // Generated from `System.Runtime.Intrinsics.X86.Popcnt+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse42.X64 { public static bool IsSupported { get => throw null; } @@ -3541,10 +3960,8 @@ namespace System public static System.UInt32 PopCount(System.UInt32 value) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Sse` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sse : System.Runtime.Intrinsics.X86.X86Base { - // Generated from `System.Runtime.Intrinsics.X86.Sse+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 { public static System.Runtime.Intrinsics.Vector128 ConvertScalarToVector128Single(System.Runtime.Intrinsics.Vector128 upper, System.Int64 value) => throw null; @@ -3646,10 +4063,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 Xor(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Sse2` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sse2 : System.Runtime.Intrinsics.X86.Sse { - // Generated from `System.Runtime.Intrinsics.X86.Sse2+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse.X64 { public static System.Runtime.Intrinsics.Vector128 ConvertScalarToVector128Double(System.Runtime.Intrinsics.Vector128 upper, System.Int64 value) => throw null; @@ -3969,10 +4384,8 @@ namespace System public static System.Runtime.Intrinsics.Vector128 Xor(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Sse3` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sse3 : System.Runtime.Intrinsics.X86.Sse2 { - // Generated from `System.Runtime.Intrinsics.X86.Sse3+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse2.X64 { public static bool IsSupported { get => throw null; } @@ -4002,10 +4415,8 @@ namespace System internal Sse3() => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Sse41` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sse41 : System.Runtime.Intrinsics.X86.Ssse3 { - // Generated from `System.Runtime.Intrinsics.X86.Sse41+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Ssse3.X64 { public static System.Int64 Extract(System.Runtime.Intrinsics.Vector128 value, System.Byte index) => throw null; @@ -4160,10 +4571,8 @@ namespace System public static bool TestZ(System.Runtime.Intrinsics.Vector128 left, System.Runtime.Intrinsics.Vector128 right) => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Sse42` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Sse42 : System.Runtime.Intrinsics.X86.Sse41 { - // Generated from `System.Runtime.Intrinsics.X86.Sse42+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse41.X64 { public static System.UInt64 Crc32(System.UInt64 crc, System.UInt64 data) => throw null; @@ -4180,10 +4589,8 @@ namespace System internal Sse42() => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.Ssse3` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Ssse3 : System.Runtime.Intrinsics.X86.Sse3 { - // Generated from `System.Runtime.Intrinsics.X86.Ssse3+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 : System.Runtime.Intrinsics.X86.Sse3.X64 { public static bool IsSupported { get => throw null; } @@ -4219,10 +4626,8 @@ namespace System internal Ssse3() => throw null; } - // Generated from `System.Runtime.Intrinsics.X86.X86Base` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X86Base { - // Generated from `System.Runtime.Intrinsics.X86.X86Base+X64` in `System.Runtime.Intrinsics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class X64 { public static bool IsSupported { get => throw null; } @@ -4232,9 +4637,22 @@ namespace System public static (int, int, int, int) CpuId(int functionId, int subFunctionId) => throw null; public static bool IsSupported { get => throw null; } + public static void Pause() => throw null; internal X86Base() => throw null; } + public abstract class X86Serialize : System.Runtime.Intrinsics.X86.X86Base + { + public abstract class X64 : System.Runtime.Intrinsics.X86.X86Base.X64 + { + public static bool IsSupported { get => throw null; } + } + + + public static bool IsSupported { get => throw null; } + public static void Serialize() => throw null; + } + } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Loader.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Loader.cs index d4a5e43ecf8..46db4a1d80b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Loader.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Loader.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Loader, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,20 +7,17 @@ namespace System { namespace Metadata { - // Generated from `System.Reflection.Metadata.AssemblyExtensions` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class AssemblyExtensions { unsafe public static bool TryGetRawMetadata(this System.Reflection.Assembly assembly, out System.Byte* blob, out int length) => throw null; } - // Generated from `System.Reflection.Metadata.MetadataUpdateHandlerAttribute` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MetadataUpdateHandlerAttribute : System.Attribute { public System.Type HandlerType { get => throw null; } public MetadataUpdateHandlerAttribute(System.Type handlerType) => throw null; } - // Generated from `System.Reflection.Metadata.MetadataUpdater` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MetadataUpdater { public static void ApplyUpdate(System.Reflection.Assembly assembly, System.ReadOnlySpan metadataDelta, System.ReadOnlySpan ilDelta, System.ReadOnlySpan pdbDelta) => throw null; @@ -32,16 +30,20 @@ namespace System { namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.CreateNewOnMetadataUpdateAttribute` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CreateNewOnMetadataUpdateAttribute : System.Attribute { public CreateNewOnMetadataUpdateAttribute() => throw null; } + public class MetadataUpdateOriginalTypeAttribute : System.Attribute + { + public MetadataUpdateOriginalTypeAttribute(System.Type originalType) => throw null; + public System.Type OriginalType { get => throw null; } + } + } namespace Loader { - // Generated from `System.Runtime.Loader.AssemblyDependencyResolver` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyDependencyResolver { public AssemblyDependencyResolver(string componentAssemblyPath) => throw null; @@ -49,10 +51,8 @@ namespace System public string ResolveUnmanagedDllToPath(string unmanagedDllName) => throw null; } - // Generated from `System.Runtime.Loader.AssemblyLoadContext` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyLoadContext { - // Generated from `System.Runtime.Loader.AssemblyLoadContext+ContextualReflectionScope` in `System.Runtime.Loader, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ContextualReflectionScope : System.IDisposable { // Stub generator skipped constructor diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Numerics.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Numerics.cs index 8841306edb2..a271d3609e0 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Numerics.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Numerics.cs @@ -1,56 +1,59 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Numerics, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Numerics { - // Generated from `System.Numerics.BigInteger` in `System.Runtime.Numerics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct BigInteger : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct BigInteger : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { - public static bool operator !=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator !=(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator !=(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator !=(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator !=(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator %(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; - public static System.Numerics.BigInteger operator &(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator *(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator +(System.Numerics.BigInteger value) => throw null; - public static System.Numerics.BigInteger operator +(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator ++(System.Numerics.BigInteger value) => throw null; - public static System.Numerics.BigInteger operator -(System.Numerics.BigInteger value) => throw null; - public static System.Numerics.BigInteger operator -(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator --(System.Numerics.BigInteger value) => throw null; - public static System.Numerics.BigInteger operator /(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; - public static bool operator <(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IModulusOperators.operator %(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; + static System.Numerics.BigInteger System.Numerics.IBitwiseOperators.operator &(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IMultiplyOperators.operator *(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IUnaryPlusOperators.operator +(System.Numerics.BigInteger value) => throw null; + static System.Numerics.BigInteger System.Numerics.IAdditionOperators.operator +(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IIncrementOperators.operator ++(System.Numerics.BigInteger value) => throw null; + static System.Numerics.BigInteger System.Numerics.IUnaryNegationOperators.operator -(System.Numerics.BigInteger value) => throw null; + static System.Numerics.BigInteger System.Numerics.ISubtractionOperators.operator -(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IDecrementOperators.operator --(System.Numerics.BigInteger value) => throw null; + static System.Numerics.BigInteger System.Numerics.IDivisionOperators.operator /(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator <(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator <(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator <(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator <(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator <<(System.Numerics.BigInteger value, int shift) => throw null; - public static bool operator <=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IShiftOperators.operator <<(System.Numerics.BigInteger value, int shift) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator <=(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator <=(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator <=(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator <=(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static bool operator ==(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator ==(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator ==(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator ==(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator ==(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static bool operator >(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator >(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator >(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator >(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator >(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static bool operator >=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static bool operator >=(System.Numerics.BigInteger left, System.Int64 right) => throw null; public static bool operator >=(System.Numerics.BigInteger left, System.UInt64 right) => throw null; public static bool operator >=(System.Int64 left, System.Numerics.BigInteger right) => throw null; public static bool operator >=(System.UInt64 left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator >>(System.Numerics.BigInteger value, int shift) => throw null; + static System.Numerics.BigInteger System.Numerics.IShiftOperators.operator >>(System.Numerics.BigInteger value, int shift) => throw null; + static System.Numerics.BigInteger System.Numerics.IShiftOperators.operator >>>(System.Numerics.BigInteger value, int shiftAmount) => throw null; public static System.Numerics.BigInteger Abs(System.Numerics.BigInteger value) => throw null; public static System.Numerics.BigInteger Add(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Numerics.BigInteger System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } // Stub generator skipped constructor public BigInteger(System.Byte[] value) => throw null; public BigInteger(System.ReadOnlySpan value, bool isUnsigned = default(bool), bool isBigEndian = default(bool)) => throw null; @@ -61,11 +64,17 @@ namespace System public BigInteger(System.Int64 value) => throw null; public BigInteger(System.UInt32 value) => throw null; public BigInteger(System.UInt64 value) => throw null; + public static System.Numerics.BigInteger Clamp(System.Numerics.BigInteger value, System.Numerics.BigInteger min, System.Numerics.BigInteger max) => throw null; public static int Compare(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public int CompareTo(System.Numerics.BigInteger other) => throw null; public int CompareTo(System.Int64 other) => throw null; public int CompareTo(object obj) => throw null; public int CompareTo(System.UInt64 other) => throw null; + public static System.Numerics.BigInteger CopySign(System.Numerics.BigInteger value, System.Numerics.BigInteger sign) => throw null; + static System.Numerics.BigInteger System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Numerics.BigInteger System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Numerics.BigInteger System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + static (System.Numerics.BigInteger, System.Numerics.BigInteger) System.Numerics.IBinaryInteger.DivRem(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static System.Numerics.BigInteger DivRem(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor, out System.Numerics.BigInteger remainder) => throw null; public static System.Numerics.BigInteger Divide(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; public bool Equals(System.Numerics.BigInteger other) => throw null; @@ -73,31 +82,67 @@ namespace System public override bool Equals(object obj) => throw null; public bool Equals(System.UInt64 other) => throw null; public System.Int64 GetBitLength() => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public int GetByteCount(bool isUnsigned = default(bool)) => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public static System.Numerics.BigInteger GreatestCommonDivisor(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + public static bool IsCanonical(System.Numerics.BigInteger value) => throw null; + public static bool IsComplexNumber(System.Numerics.BigInteger value) => throw null; public bool IsEven { get => throw null; } + public static bool IsEvenInteger(System.Numerics.BigInteger value) => throw null; + public static bool IsFinite(System.Numerics.BigInteger value) => throw null; + public static bool IsImaginaryNumber(System.Numerics.BigInteger value) => throw null; + public static bool IsInfinity(System.Numerics.BigInteger value) => throw null; + public static bool IsInteger(System.Numerics.BigInteger value) => throw null; + public static bool IsNaN(System.Numerics.BigInteger value) => throw null; + public static bool IsNegative(System.Numerics.BigInteger value) => throw null; + public static bool IsNegativeInfinity(System.Numerics.BigInteger value) => throw null; + public static bool IsNormal(System.Numerics.BigInteger value) => throw null; + public static bool IsOddInteger(System.Numerics.BigInteger value) => throw null; public bool IsOne { get => throw null; } + public static bool IsPositive(System.Numerics.BigInteger value) => throw null; + public static bool IsPositiveInfinity(System.Numerics.BigInteger value) => throw null; + public static bool IsPow2(System.Numerics.BigInteger value) => throw null; public bool IsPowerOfTwo { get => throw null; } + public static bool IsRealNumber(System.Numerics.BigInteger value) => throw null; + public static bool IsSubnormal(System.Numerics.BigInteger value) => throw null; public bool IsZero { get => throw null; } + static bool System.Numerics.INumberBase.IsZero(System.Numerics.BigInteger value) => throw null; + public static System.Numerics.BigInteger LeadingZeroCount(System.Numerics.BigInteger value) => throw null; public static double Log(System.Numerics.BigInteger value) => throw null; public static double Log(System.Numerics.BigInteger value, double baseValue) => throw null; public static double Log10(System.Numerics.BigInteger value) => throw null; + public static System.Numerics.BigInteger Log2(System.Numerics.BigInteger value) => throw null; public static System.Numerics.BigInteger Max(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + public static System.Numerics.BigInteger MaxMagnitude(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; + public static System.Numerics.BigInteger MaxMagnitudeNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; + public static System.Numerics.BigInteger MaxNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; public static System.Numerics.BigInteger Min(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + public static System.Numerics.BigInteger MinMagnitude(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; + public static System.Numerics.BigInteger MinMagnitudeNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; + public static System.Numerics.BigInteger MinNumber(System.Numerics.BigInteger x, System.Numerics.BigInteger y) => throw null; public static System.Numerics.BigInteger MinusOne { get => throw null; } public static System.Numerics.BigInteger ModPow(System.Numerics.BigInteger value, System.Numerics.BigInteger exponent, System.Numerics.BigInteger modulus) => throw null; + static System.Numerics.BigInteger System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } public static System.Numerics.BigInteger Multiply(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static System.Numerics.BigInteger Negate(System.Numerics.BigInteger value) => throw null; - public static System.Numerics.BigInteger One { get => throw null; } + static System.Numerics.BigInteger System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Numerics.BigInteger System.Numerics.INumberBase.One { get => throw null; } + public static System.Numerics.BigInteger Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Numerics.BigInteger Parse(System.ReadOnlySpan value, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Numerics.BigInteger Parse(string value) => throw null; public static System.Numerics.BigInteger Parse(string value, System.IFormatProvider provider) => throw null; public static System.Numerics.BigInteger Parse(string value, System.Globalization.NumberStyles style) => throw null; public static System.Numerics.BigInteger Parse(string value, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Numerics.BigInteger PopCount(System.Numerics.BigInteger value) => throw null; public static System.Numerics.BigInteger Pow(System.Numerics.BigInteger value, int exponent) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } public static System.Numerics.BigInteger Remainder(System.Numerics.BigInteger dividend, System.Numerics.BigInteger divisor) => throw null; + public static System.Numerics.BigInteger RotateLeft(System.Numerics.BigInteger value, int rotateAmount) => throw null; + public static System.Numerics.BigInteger RotateRight(System.Numerics.BigInteger value, int rotateAmount) => throw null; public int Sign { get => throw null; } + static int System.Numerics.INumber.Sign(System.Numerics.BigInteger value) => throw null; public static System.Numerics.BigInteger Subtract(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public System.Byte[] ToByteArray() => throw null; public System.Byte[] ToByteArray(bool isUnsigned = default(bool), bool isBigEndian = default(bool)) => throw null; @@ -105,29 +150,55 @@ namespace System public string ToString(System.IFormatProvider provider) => throw null; public string ToString(string format) => throw null; public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.Numerics.BigInteger TrailingZeroCount(System.Numerics.BigInteger value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.BigInteger result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.BigInteger result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.BigInteger result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.BigInteger value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.BigInteger value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.BigInteger value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Numerics.BigInteger result) => throw null; public static bool TryParse(System.ReadOnlySpan value, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Numerics.BigInteger result) => throw null; public static bool TryParse(System.ReadOnlySpan value, out System.Numerics.BigInteger result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Numerics.BigInteger result) => throw null; public static bool TryParse(string value, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Numerics.BigInteger result) => throw null; public static bool TryParse(string value, out System.Numerics.BigInteger result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Numerics.BigInteger value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Numerics.BigInteger value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; public bool TryWriteBytes(System.Span destination, out int bytesWritten, bool isUnsigned = default(bool), bool isBigEndian = default(bool)) => throw null; - public static System.Numerics.BigInteger Zero { get => throw null; } - public static System.Numerics.BigInteger operator ^(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Numerics.BigInteger System.Numerics.INumberBase.Zero { get => throw null; } + static System.Numerics.BigInteger System.Numerics.IBitwiseOperators.operator ^(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; public static explicit operator System.Byte(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.Char(System.Numerics.BigInteger value) => throw null; public static explicit operator System.Decimal(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.Half(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.Int128(System.Numerics.BigInteger value) => throw null; public static explicit operator System.Int16(System.Numerics.BigInteger value) => throw null; public static explicit operator System.Int64(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.IntPtr(System.Numerics.BigInteger value) => throw null; public static explicit operator System.SByte(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.UInt128(System.Numerics.BigInteger value) => throw null; public static explicit operator System.UInt16(System.Numerics.BigInteger value) => throw null; public static explicit operator System.UInt32(System.Numerics.BigInteger value) => throw null; public static explicit operator System.UInt64(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.UIntPtr(System.Numerics.BigInteger value) => throw null; public static explicit operator double(System.Numerics.BigInteger value) => throw null; public static explicit operator float(System.Numerics.BigInteger value) => throw null; public static explicit operator int(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.Numerics.BigInteger(System.Numerics.Complex value) => throw null; + public static explicit operator System.Numerics.BigInteger(System.Half value) => throw null; public static explicit operator System.Numerics.BigInteger(System.Decimal value) => throw null; public static explicit operator System.Numerics.BigInteger(double value) => throw null; public static explicit operator System.Numerics.BigInteger(float value) => throw null; + public static implicit operator System.Numerics.BigInteger(System.Int128 value) => throw null; + public static implicit operator System.Numerics.BigInteger(System.IntPtr value) => throw null; + public static implicit operator System.Numerics.BigInteger(System.UInt128 value) => throw null; + public static implicit operator System.Numerics.BigInteger(System.UIntPtr value) => throw null; public static implicit operator System.Numerics.BigInteger(System.Byte value) => throw null; + public static implicit operator System.Numerics.BigInteger(System.Char value) => throw null; public static implicit operator System.Numerics.BigInteger(int value) => throw null; public static implicit operator System.Numerics.BigInteger(System.Int64 value) => throw null; public static implicit operator System.Numerics.BigInteger(System.SByte value) => throw null; @@ -135,33 +206,37 @@ namespace System public static implicit operator System.Numerics.BigInteger(System.UInt32 value) => throw null; public static implicit operator System.Numerics.BigInteger(System.UInt64 value) => throw null; public static implicit operator System.Numerics.BigInteger(System.UInt16 value) => throw null; - public static System.Numerics.BigInteger operator |(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; - public static System.Numerics.BigInteger operator ~(System.Numerics.BigInteger value) => throw null; + static System.Numerics.BigInteger System.Numerics.IBitwiseOperators.operator |(System.Numerics.BigInteger left, System.Numerics.BigInteger right) => throw null; + static System.Numerics.BigInteger System.Numerics.IBitwiseOperators.operator ~(System.Numerics.BigInteger value) => throw null; } - // Generated from `System.Numerics.Complex` in `System.Runtime.Numerics, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Complex : System.IEquatable, System.IFormattable + public struct Complex : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { - public static bool operator !=(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; - public static System.Numerics.Complex operator *(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static System.Numerics.Complex System.Numerics.IMultiplyOperators.operator *(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex operator *(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex operator *(double left, System.Numerics.Complex right) => throw null; - public static System.Numerics.Complex operator +(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static System.Numerics.Complex System.Numerics.IUnaryPlusOperators.operator +(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.IAdditionOperators.operator +(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex operator +(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex operator +(double left, System.Numerics.Complex right) => throw null; - public static System.Numerics.Complex operator -(System.Numerics.Complex value) => throw null; - public static System.Numerics.Complex operator -(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static System.Numerics.Complex System.Numerics.IIncrementOperators.operator ++(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.IUnaryNegationOperators.operator -(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.ISubtractionOperators.operator -(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex operator -(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex operator -(double left, System.Numerics.Complex right) => throw null; - public static System.Numerics.Complex operator /(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static System.Numerics.Complex System.Numerics.IDecrementOperators.operator --(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.IDivisionOperators.operator /(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex operator /(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex operator /(double left, System.Numerics.Complex right) => throw null; - public static bool operator ==(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static double Abs(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.INumberBase.Abs(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Acos(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Add(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex Add(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex Add(double left, System.Numerics.Complex right) => throw null; + static System.Numerics.Complex System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } public static System.Numerics.Complex Asin(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Atan(System.Numerics.Complex value) => throw null; // Stub generator skipped constructor @@ -169,6 +244,9 @@ namespace System public static System.Numerics.Complex Conjugate(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Cos(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Cosh(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Numerics.Complex System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Numerics.Complex System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; public static System.Numerics.Complex Divide(System.Numerics.Complex dividend, System.Numerics.Complex divisor) => throw null; public static System.Numerics.Complex Divide(System.Numerics.Complex dividend, double divisor) => throw null; public static System.Numerics.Complex Divide(double dividend, System.Numerics.Complex divisor) => throw null; @@ -180,22 +258,48 @@ namespace System public double Imaginary { get => throw null; } public static System.Numerics.Complex ImaginaryOne; public static System.Numerics.Complex Infinity; + public static bool IsCanonical(System.Numerics.Complex value) => throw null; + public static bool IsComplexNumber(System.Numerics.Complex value) => throw null; + public static bool IsEvenInteger(System.Numerics.Complex value) => throw null; public static bool IsFinite(System.Numerics.Complex value) => throw null; + public static bool IsImaginaryNumber(System.Numerics.Complex value) => throw null; public static bool IsInfinity(System.Numerics.Complex value) => throw null; + public static bool IsInteger(System.Numerics.Complex value) => throw null; public static bool IsNaN(System.Numerics.Complex value) => throw null; + public static bool IsNegative(System.Numerics.Complex value) => throw null; + public static bool IsNegativeInfinity(System.Numerics.Complex value) => throw null; + public static bool IsNormal(System.Numerics.Complex value) => throw null; + public static bool IsOddInteger(System.Numerics.Complex value) => throw null; + public static bool IsPositive(System.Numerics.Complex value) => throw null; + public static bool IsPositiveInfinity(System.Numerics.Complex value) => throw null; + public static bool IsRealNumber(System.Numerics.Complex value) => throw null; + public static bool IsSubnormal(System.Numerics.Complex value) => throw null; + public static bool IsZero(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Log(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Log(System.Numerics.Complex value, double baseValue) => throw null; public static System.Numerics.Complex Log10(System.Numerics.Complex value) => throw null; public double Magnitude { get => throw null; } + public static System.Numerics.Complex MaxMagnitude(System.Numerics.Complex x, System.Numerics.Complex y) => throw null; + public static System.Numerics.Complex MaxMagnitudeNumber(System.Numerics.Complex x, System.Numerics.Complex y) => throw null; + public static System.Numerics.Complex MinMagnitude(System.Numerics.Complex x, System.Numerics.Complex y) => throw null; + public static System.Numerics.Complex MinMagnitudeNumber(System.Numerics.Complex x, System.Numerics.Complex y) => throw null; + static System.Numerics.Complex System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } public static System.Numerics.Complex Multiply(System.Numerics.Complex left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex Multiply(System.Numerics.Complex left, double right) => throw null; public static System.Numerics.Complex Multiply(double left, System.Numerics.Complex right) => throw null; public static System.Numerics.Complex NaN; public static System.Numerics.Complex Negate(System.Numerics.Complex value) => throw null; + static System.Numerics.Complex System.Numerics.ISignedNumber.NegativeOne { get => throw null; } public static System.Numerics.Complex One; + static System.Numerics.Complex System.Numerics.INumberBase.One { get => throw null; } + public static System.Numerics.Complex Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; + public static System.Numerics.Complex Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Numerics.Complex Parse(string s, System.IFormatProvider provider) => throw null; + public static System.Numerics.Complex Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; public double Phase { get => throw null; } public static System.Numerics.Complex Pow(System.Numerics.Complex value, System.Numerics.Complex power) => throw null; public static System.Numerics.Complex Pow(System.Numerics.Complex value, double power) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } public double Real { get => throw null; } public static System.Numerics.Complex Reciprocal(System.Numerics.Complex value) => throw null; public static System.Numerics.Complex Sin(System.Numerics.Complex value) => throw null; @@ -210,10 +314,28 @@ namespace System public string ToString(System.IFormatProvider provider) => throw null; public string ToString(string format) => throw null; public string ToString(string format, System.IFormatProvider provider) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Numerics.Complex result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Numerics.Complex result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Numerics.Complex result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Numerics.Complex value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Numerics.Complex value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Numerics.Complex value, out TOther result) => throw null; + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider provider) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Numerics.Complex result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Numerics.Complex result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Numerics.Complex result) => throw null; + public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Numerics.Complex result) => throw null; public static System.Numerics.Complex Zero; + static System.Numerics.Complex System.Numerics.INumberBase.Zero { get => throw null; } public static explicit operator System.Numerics.Complex(System.Numerics.BigInteger value) => throw null; + public static explicit operator System.Numerics.Complex(System.Int128 value) => throw null; + public static explicit operator System.Numerics.Complex(System.UInt128 value) => throw null; public static explicit operator System.Numerics.Complex(System.Decimal value) => throw null; + public static implicit operator System.Numerics.Complex(System.Half value) => throw null; + public static implicit operator System.Numerics.Complex(System.IntPtr value) => throw null; + public static implicit operator System.Numerics.Complex(System.UIntPtr value) => throw null; public static implicit operator System.Numerics.Complex(System.Byte value) => throw null; + public static implicit operator System.Numerics.Complex(System.Char value) => throw null; public static implicit operator System.Numerics.Complex(double value) => throw null; public static implicit operator System.Numerics.Complex(float value) => throw null; public static implicit operator System.Numerics.Complex(int value) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Formatters.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Formatters.cs index 47c348fc473..13a21e51b74 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Formatters.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Formatters.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Serialization.Formatters, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Serialization { - // Generated from `System.Runtime.Serialization.Formatter` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Formatter : System.Runtime.Serialization.IFormatter { public abstract System.Runtime.Serialization.SerializationBinder Binder { get; set; } @@ -40,7 +40,6 @@ namespace System protected System.Collections.Queue m_objectQueue; } - // Generated from `System.Runtime.Serialization.FormatterConverter` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FormatterConverter : System.Runtime.Serialization.IFormatterConverter { public object Convert(object value, System.Type type) => throw null; @@ -63,7 +62,6 @@ namespace System public System.UInt64 ToUInt64(object value) => throw null; } - // Generated from `System.Runtime.Serialization.FormatterServices` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class FormatterServices { public static void CheckTypeSecurity(System.Type t, System.Runtime.Serialization.Formatters.TypeFilterLevel securityLevel) => throw null; @@ -77,7 +75,6 @@ namespace System public static object PopulateObjectMembers(object obj, System.Reflection.MemberInfo[] members, object[] data) => throw null; } - // Generated from `System.Runtime.Serialization.IFormatter` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFormatter { System.Runtime.Serialization.SerializationBinder Binder { get; set; } @@ -87,14 +84,12 @@ namespace System System.Runtime.Serialization.ISurrogateSelector SurrogateSelector { get; set; } } - // Generated from `System.Runtime.Serialization.ISerializationSurrogate` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISerializationSurrogate { void GetObjectData(object obj, System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context); object SetObjectData(object obj, System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.ISurrogateSelector selector); } - // Generated from `System.Runtime.Serialization.ISurrogateSelector` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISurrogateSelector { void ChainSelector(System.Runtime.Serialization.ISurrogateSelector selector); @@ -102,7 +97,6 @@ namespace System System.Runtime.Serialization.ISerializationSurrogate GetSurrogate(System.Type type, System.Runtime.Serialization.StreamingContext context, out System.Runtime.Serialization.ISurrogateSelector selector); } - // Generated from `System.Runtime.Serialization.ObjectIDGenerator` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectIDGenerator { public virtual System.Int64 GetId(object obj, out bool firstTime) => throw null; @@ -110,7 +104,6 @@ namespace System public ObjectIDGenerator() => throw null; } - // Generated from `System.Runtime.Serialization.ObjectManager` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectManager { public virtual void DoFixups() => throw null; @@ -128,7 +121,6 @@ namespace System public void RegisterObject(object obj, System.Int64 objectID, System.Runtime.Serialization.SerializationInfo info, System.Int64 idOfContainingObj, System.Reflection.MemberInfo member, int[] arrayIndex) => throw null; } - // Generated from `System.Runtime.Serialization.SerializationBinder` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SerializationBinder { public virtual void BindToName(System.Type serializedType, out string assemblyName, out string typeName) => throw null; @@ -136,7 +128,6 @@ namespace System protected SerializationBinder() => throw null; } - // Generated from `System.Runtime.Serialization.SerializationObjectManager` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SerializationObjectManager { public void RaiseOnSerializedEvent() => throw null; @@ -144,7 +135,6 @@ namespace System public SerializationObjectManager(System.Runtime.Serialization.StreamingContext context) => throw null; } - // Generated from `System.Runtime.Serialization.SurrogateSelector` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SurrogateSelector : System.Runtime.Serialization.ISurrogateSelector { public virtual void AddSurrogate(System.Type type, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.ISerializationSurrogate surrogate) => throw null; @@ -157,14 +147,12 @@ namespace System namespace Formatters { - // Generated from `System.Runtime.Serialization.Formatters.FormatterAssemblyStyle` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FormatterAssemblyStyle : int { Full = 1, Simple = 0, } - // Generated from `System.Runtime.Serialization.Formatters.FormatterTypeStyle` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FormatterTypeStyle : int { TypesAlways = 1, @@ -172,14 +160,12 @@ namespace System XsdString = 2, } - // Generated from `System.Runtime.Serialization.Formatters.IFieldInfo` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFieldInfo { string[] FieldNames { get; set; } System.Type[] FieldTypes { get; set; } } - // Generated from `System.Runtime.Serialization.Formatters.TypeFilterLevel` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TypeFilterLevel : int { Full = 3, @@ -188,7 +174,6 @@ namespace System namespace Binary { - // Generated from `System.Runtime.Serialization.Formatters.Binary.BinaryFormatter` in `System.Runtime.Serialization.Formatters, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BinaryFormatter : System.Runtime.Serialization.IFormatter { public System.Runtime.Serialization.Formatters.FormatterAssemblyStyle AssemblyFormat { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Json.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Json.cs index aba24d91075..d7a217a318b 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Json.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Json.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Serialization.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Serialization { - // Generated from `System.Runtime.Serialization.DateTimeFormat` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateTimeFormat { public DateTimeFormat(string formatString) => throw null; @@ -16,7 +16,6 @@ namespace System public string FormatString { get => throw null; } } - // Generated from `System.Runtime.Serialization.EmitTypeInformation` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EmitTypeInformation : int { Always = 1, @@ -26,7 +25,6 @@ namespace System namespace Json { - // Generated from `System.Runtime.Serialization.Json.DataContractJsonSerializer` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataContractJsonSerializer : System.Runtime.Serialization.XmlObjectSerializer { public DataContractJsonSerializer(System.Type type) => throw null; @@ -38,6 +36,7 @@ namespace System public DataContractJsonSerializer(System.Type type, string rootName, System.Collections.Generic.IEnumerable knownTypes) => throw null; public System.Runtime.Serialization.DateTimeFormat DateTimeFormat { get => throw null; } public System.Runtime.Serialization.EmitTypeInformation EmitTypeInformation { get => throw null; } + public System.Runtime.Serialization.ISerializationSurrogateProvider GetSerializationSurrogateProvider() => throw null; public bool IgnoreExtensionDataObject { get => throw null; } public override bool IsStartObject(System.Xml.XmlDictionaryReader reader) => throw null; public override bool IsStartObject(System.Xml.XmlReader reader) => throw null; @@ -49,6 +48,7 @@ namespace System public override object ReadObject(System.Xml.XmlReader reader) => throw null; public override object ReadObject(System.Xml.XmlReader reader, bool verifyObjectName) => throw null; public bool SerializeReadOnlyTypes { get => throw null; } + public void SetSerializationSurrogateProvider(System.Runtime.Serialization.ISerializationSurrogateProvider provider) => throw null; public bool UseSimpleDictionaryFormat { get => throw null; } public override void WriteEndObject(System.Xml.XmlDictionaryWriter writer) => throw null; public override void WriteEndObject(System.Xml.XmlWriter writer) => throw null; @@ -61,7 +61,6 @@ namespace System public override void WriteStartObject(System.Xml.XmlWriter writer, object graph) => throw null; } - // Generated from `System.Runtime.Serialization.Json.DataContractJsonSerializerSettings` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataContractJsonSerializerSettings { public DataContractJsonSerializerSettings() => throw null; @@ -75,20 +74,17 @@ namespace System public bool UseSimpleDictionaryFormat { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.Json.IXmlJsonReaderInitializer` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlJsonReaderInitializer { void SetInput(System.Byte[] buffer, int offset, int count, System.Text.Encoding encoding, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.OnXmlDictionaryReaderClose onClose); void SetInput(System.IO.Stream stream, System.Text.Encoding encoding, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.OnXmlDictionaryReaderClose onClose); } - // Generated from `System.Runtime.Serialization.Json.IXmlJsonWriterInitializer` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlJsonWriterInitializer { void SetOutput(System.IO.Stream stream, System.Text.Encoding encoding, bool ownsStream); } - // Generated from `System.Runtime.Serialization.Json.JsonReaderWriterFactory` in `System.Runtime.Serialization.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class JsonReaderWriterFactory { public static System.Xml.XmlDictionaryReader CreateJsonReader(System.Byte[] buffer, System.Xml.XmlDictionaryReaderQuotas quotas) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Primitives.cs index d1be990749d..b803f1ffcb2 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Primitives.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Primitives.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Serialization.Primitives, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Serialization { - // Generated from `System.Runtime.Serialization.CollectionDataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CollectionDataContractAttribute : System.Attribute { public CollectionDataContractAttribute() => throw null; @@ -24,7 +24,6 @@ namespace System public string ValueName { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.ContractNamespaceAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContractNamespaceAttribute : System.Attribute { public string ClrNamespace { get => throw null; set => throw null; } @@ -32,7 +31,6 @@ namespace System public ContractNamespaceAttribute(string contractNamespace) => throw null; } - // Generated from `System.Runtime.Serialization.DataContractAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataContractAttribute : System.Attribute { public DataContractAttribute() => throw null; @@ -44,7 +42,6 @@ namespace System public string Namespace { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.DataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataMemberAttribute : System.Attribute { public DataMemberAttribute() => throw null; @@ -55,7 +52,6 @@ namespace System public int Order { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.EnumMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumMemberAttribute : System.Attribute { public EnumMemberAttribute() => throw null; @@ -63,7 +59,6 @@ namespace System public string Value { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.ISerializationSurrogateProvider` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISerializationSurrogateProvider { object GetDeserializedObject(object obj, System.Type targetType); @@ -71,13 +66,19 @@ namespace System System.Type GetSurrogateType(System.Type type); } - // Generated from `System.Runtime.Serialization.IgnoreDataMemberAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public interface ISerializationSurrogateProvider2 : System.Runtime.Serialization.ISerializationSurrogateProvider + { + object GetCustomDataToExport(System.Reflection.MemberInfo memberInfo, System.Type dataContractType); + object GetCustomDataToExport(System.Type runtimeType, System.Type dataContractType); + void GetKnownCustomDataTypes(System.Collections.ObjectModel.Collection customDataTypes); + System.Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData); + } + public class IgnoreDataMemberAttribute : System.Attribute { public IgnoreDataMemberAttribute() => throw null; } - // Generated from `System.Runtime.Serialization.InvalidDataContractException` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidDataContractException : System.Exception { public InvalidDataContractException() => throw null; @@ -86,7 +87,6 @@ namespace System public InvalidDataContractException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Runtime.Serialization.KnownTypeAttribute` in `System.Runtime.Serialization.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KnownTypeAttribute : System.Attribute { public KnownTypeAttribute(System.Type type) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Xml.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Xml.cs index eb184cbe56a..c68f9be0b74 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Xml.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.Serialization.Xml.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime.Serialization.Xml, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Serialization { - // Generated from `System.Runtime.Serialization.DataContractResolver` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DataContractResolver { protected DataContractResolver() => throw null; @@ -14,7 +14,6 @@ namespace System public abstract bool TryResolveType(System.Type type, System.Type declaredType, System.Runtime.Serialization.DataContractResolver knownTypeResolver, out System.Xml.XmlDictionaryString typeName, out System.Xml.XmlDictionaryString typeNamespace); } - // Generated from `System.Runtime.Serialization.DataContractSerializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataContractSerializer : System.Runtime.Serialization.XmlObjectSerializer { public System.Runtime.Serialization.DataContractResolver DataContractResolver { get => throw null; } @@ -46,14 +45,12 @@ namespace System public override void WriteStartObject(System.Xml.XmlWriter writer, object graph) => throw null; } - // Generated from `System.Runtime.Serialization.DataContractSerializerExtensions` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataContractSerializerExtensions { public static System.Runtime.Serialization.ISerializationSurrogateProvider GetSerializationSurrogateProvider(this System.Runtime.Serialization.DataContractSerializer serializer) => throw null; public static void SetSerializationSurrogateProvider(this System.Runtime.Serialization.DataContractSerializer serializer, System.Runtime.Serialization.ISerializationSurrogateProvider provider) => throw null; } - // Generated from `System.Runtime.Serialization.DataContractSerializerSettings` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataContractSerializerSettings { public System.Runtime.Serialization.DataContractResolver DataContractResolver { get => throw null; set => throw null; } @@ -67,32 +64,28 @@ namespace System public bool SerializeReadOnlyTypes { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.ExportOptions` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExportOptions { + public System.Runtime.Serialization.ISerializationSurrogateProvider DataContractSurrogate { get => throw null; set => throw null; } public ExportOptions() => throw null; public System.Collections.ObjectModel.Collection KnownTypes { get => throw null; } } - // Generated from `System.Runtime.Serialization.ExtensionDataObject` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExtensionDataObject { } - // Generated from `System.Runtime.Serialization.IExtensibleDataObject` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IExtensibleDataObject { System.Runtime.Serialization.ExtensionDataObject ExtensionData { get; set; } } - // Generated from `System.Runtime.Serialization.XPathQueryGenerator` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class XPathQueryGenerator { public static string CreateFromDataContractSerializer(System.Type type, System.Reflection.MemberInfo[] pathToMember, System.Text.StringBuilder rootElementXpath, out System.Xml.XmlNamespaceManager namespaces) => throw null; public static string CreateFromDataContractSerializer(System.Type type, System.Reflection.MemberInfo[] pathToMember, out System.Xml.XmlNamespaceManager namespaces) => throw null; } - // Generated from `System.Runtime.Serialization.XmlObjectSerializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlObjectSerializer { public abstract bool IsStartObject(System.Xml.XmlDictionaryReader reader); @@ -114,7 +107,6 @@ namespace System protected XmlObjectSerializer() => throw null; } - // Generated from `System.Runtime.Serialization.XmlSerializableServices` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class XmlSerializableServices { public static void AddDefaultSchema(System.Xml.Schema.XmlSchemaSet schemas, System.Xml.XmlQualifiedName typeQName) => throw null; @@ -122,7 +114,6 @@ namespace System public static void WriteNodes(System.Xml.XmlWriter xmlWriter, System.Xml.XmlNode[] nodes) => throw null; } - // Generated from `System.Runtime.Serialization.XsdDataContractExporter` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XsdDataContractExporter { public bool CanExport(System.Collections.Generic.ICollection assemblies) => throw null; @@ -140,11 +131,75 @@ namespace System public XsdDataContractExporter(System.Xml.Schema.XmlSchemaSet schemas) => throw null; } + namespace DataContracts + { + public abstract class DataContract + { + public virtual System.Runtime.Serialization.DataContracts.DataContract BaseContract { get => throw null; } + public virtual string ContractType { get => throw null; } + internal DataContract(System.Runtime.Serialization.DataContracts.DataContractCriticalHelper helper) => throw null; + public virtual System.Collections.ObjectModel.ReadOnlyCollection DataMembers { get => throw null; } + public virtual System.Xml.XmlQualifiedName GetArrayTypeName(bool isNullable) => throw null; + public static System.Runtime.Serialization.DataContracts.DataContract GetBuiltInDataContract(string name, string ns) => throw null; + public static System.Xml.XmlQualifiedName GetXmlName(System.Type type) => throw null; + public virtual bool IsBuiltInDataContract { get => throw null; } + public virtual bool IsDictionaryLike(out string keyName, out string valueName, out string itemName) => throw null; + public virtual bool IsISerializable { get => throw null; } + public virtual bool IsReference { get => throw null; } + public virtual bool IsValueType { get => throw null; } + public virtual System.Collections.Generic.Dictionary KnownDataContracts { get => throw null; } + public virtual System.Type OriginalUnderlyingType { get => throw null; } + public virtual System.Xml.XmlDictionaryString TopLevelElementName { get => throw null; } + public virtual System.Xml.XmlDictionaryString TopLevelElementNamespace { get => throw null; } + public virtual System.Type UnderlyingType { get => throw null; } + public virtual System.Xml.XmlQualifiedName XmlName { get => throw null; } + } + + internal abstract class DataContractCriticalHelper + { + } + + public class DataContractSet + { + public System.Collections.Generic.Dictionary Contracts { get => throw null; } + public DataContractSet(System.Runtime.Serialization.DataContracts.DataContractSet dataContractSet) => throw null; + public DataContractSet(System.Runtime.Serialization.ISerializationSurrogateProvider dataContractSurrogate, System.Collections.Generic.IEnumerable referencedTypes, System.Collections.Generic.IEnumerable referencedCollectionTypes) => throw null; + public System.Runtime.Serialization.DataContracts.DataContract GetDataContract(System.Type type) => throw null; + public System.Runtime.Serialization.DataContracts.DataContract GetDataContract(System.Xml.XmlQualifiedName key) => throw null; + public System.Type GetReferencedType(System.Xml.XmlQualifiedName xmlName, System.Runtime.Serialization.DataContracts.DataContract dataContract, out System.Runtime.Serialization.DataContracts.DataContract referencedContract, out object[] genericParameters, bool? supportGenericTypes = default(bool?)) => throw null; + public void ImportSchemaSet(System.Xml.Schema.XmlSchemaSet schemaSet, System.Collections.Generic.IEnumerable typeNames, bool importXmlDataType) => throw null; + public System.Collections.Generic.List ImportSchemaSet(System.Xml.Schema.XmlSchemaSet schemaSet, System.Collections.Generic.IEnumerable elements, bool importXmlDataType) => throw null; + public System.Collections.Generic.Dictionary KnownTypesForObject { get => throw null; } + public System.Collections.Generic.Dictionary ProcessedContracts { get => throw null; } + public System.Collections.Hashtable SurrogateData { get => throw null; } + } + + public class DataMember + { + public bool EmitDefaultValue { get => throw null; } + public bool IsNullable { get => throw null; } + public bool IsRequired { get => throw null; } + public System.Runtime.Serialization.DataContracts.DataContract MemberTypeContract { get => throw null; } + public string Name { get => throw null; } + public System.Int64 Order { get => throw null; } + } + + public class XmlDataContract : System.Runtime.Serialization.DataContracts.DataContract + { + public bool HasRoot { get => throw null; } + public bool IsAnonymous { get => throw null; } + public bool IsTopLevelElementNullable { get => throw null; } + public bool IsTypeDefinedOnImport { get => throw null; set => throw null; } + public bool IsValueType { get => throw null; set => throw null; } + internal XmlDataContract(System.Type type) : base(default(System.Runtime.Serialization.DataContracts.DataContractCriticalHelper)) => throw null; + public System.Xml.Schema.XmlSchemaType XsdType { get => throw null; } + } + + } } } namespace Xml { - // Generated from `System.Xml.IFragmentCapableXmlDictionaryWriter` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFragmentCapableXmlDictionaryWriter { bool CanFragment { get; } @@ -153,27 +208,23 @@ namespace System void WriteFragment(System.Byte[] buffer, int offset, int count); } - // Generated from `System.Xml.IStreamProvider` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStreamProvider { System.IO.Stream GetStream(); void ReleaseStream(System.IO.Stream stream); } - // Generated from `System.Xml.IXmlBinaryReaderInitializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlBinaryReaderInitializer { void SetInput(System.Byte[] buffer, int offset, int count, System.Xml.IXmlDictionary dictionary, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.XmlBinaryReaderSession session, System.Xml.OnXmlDictionaryReaderClose onClose); void SetInput(System.IO.Stream stream, System.Xml.IXmlDictionary dictionary, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.XmlBinaryReaderSession session, System.Xml.OnXmlDictionaryReaderClose onClose); } - // Generated from `System.Xml.IXmlBinaryWriterInitializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlBinaryWriterInitializer { void SetOutput(System.IO.Stream stream, System.Xml.IXmlDictionary dictionary, System.Xml.XmlBinaryWriterSession session, bool ownsStream); } - // Generated from `System.Xml.IXmlDictionary` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlDictionary { bool TryLookup(System.Xml.XmlDictionaryString value, out System.Xml.XmlDictionaryString result); @@ -181,23 +232,19 @@ namespace System bool TryLookup(string value, out System.Xml.XmlDictionaryString result); } - // Generated from `System.Xml.IXmlTextReaderInitializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlTextReaderInitializer { void SetInput(System.Byte[] buffer, int offset, int count, System.Text.Encoding encoding, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.OnXmlDictionaryReaderClose onClose); void SetInput(System.IO.Stream stream, System.Text.Encoding encoding, System.Xml.XmlDictionaryReaderQuotas quotas, System.Xml.OnXmlDictionaryReaderClose onClose); } - // Generated from `System.Xml.IXmlTextWriterInitializer` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlTextWriterInitializer { void SetOutput(System.IO.Stream stream, System.Text.Encoding encoding, bool ownsStream); } - // Generated from `System.Xml.OnXmlDictionaryReaderClose` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void OnXmlDictionaryReaderClose(System.Xml.XmlDictionaryReader reader); - // Generated from `System.Xml.UniqueId` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UniqueId { public static bool operator !=(System.Xml.UniqueId id1, System.Xml.UniqueId id2) => throw null; @@ -218,7 +265,6 @@ namespace System public UniqueId(string value) => throw null; } - // Generated from `System.Xml.XmlBinaryReaderSession` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlBinaryReaderSession : System.Xml.IXmlDictionary { public System.Xml.XmlDictionaryString Add(int id, string value) => throw null; @@ -229,7 +275,6 @@ namespace System public XmlBinaryReaderSession() => throw null; } - // Generated from `System.Xml.XmlBinaryWriterSession` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlBinaryWriterSession { public void Reset() => throw null; @@ -237,7 +282,6 @@ namespace System public XmlBinaryWriterSession() => throw null; } - // Generated from `System.Xml.XmlDictionary` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDictionary : System.Xml.IXmlDictionary { public virtual System.Xml.XmlDictionaryString Add(string value) => throw null; @@ -249,7 +293,6 @@ namespace System public XmlDictionary(int capacity) => throw null; } - // Generated from `System.Xml.XmlDictionaryReader` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlDictionaryReader : System.Xml.XmlReader { public virtual bool CanCanonicalize { get => throw null; } @@ -378,7 +421,6 @@ namespace System protected XmlDictionaryReader() => throw null; } - // Generated from `System.Xml.XmlDictionaryReaderQuotaTypes` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum XmlDictionaryReaderQuotaTypes : int { @@ -389,7 +431,6 @@ namespace System MaxStringContentLength = 2, } - // Generated from `System.Xml.XmlDictionaryReaderQuotas` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDictionaryReaderQuotas { public void CopyTo(System.Xml.XmlDictionaryReaderQuotas quotas) => throw null; @@ -403,7 +444,6 @@ namespace System public XmlDictionaryReaderQuotas() => throw null; } - // Generated from `System.Xml.XmlDictionaryString` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDictionaryString { public System.Xml.IXmlDictionary Dictionary { get => throw null; } @@ -414,7 +454,6 @@ namespace System public XmlDictionaryString(System.Xml.IXmlDictionary dictionary, string value, int key) => throw null; } - // Generated from `System.Xml.XmlDictionaryWriter` in `System.Runtime.Serialization.Xml, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlDictionaryWriter : System.Xml.XmlWriter { public virtual bool CanCanonicalize { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.cs index 30de6a1c57b..fbe44d3c8fb 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Runtime.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Runtime, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,21 +7,18 @@ namespace Microsoft { namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.CriticalHandleMinusOneIsInvalid` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CriticalHandleMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle { protected CriticalHandleMinusOneIsInvalid() : base(default(System.IntPtr)) => throw null; public override bool IsInvalid { get => throw null; } } - // Generated from `Microsoft.Win32.SafeHandles.CriticalHandleZeroOrMinusOneIsInvalid` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CriticalHandleZeroOrMinusOneIsInvalid : System.Runtime.InteropServices.CriticalHandle { protected CriticalHandleZeroOrMinusOneIsInvalid() : base(default(System.IntPtr)) => throw null; public override bool IsInvalid { get => throw null; } } - // Generated from `Microsoft.Win32.SafeHandles.SafeFileHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeFileHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public bool IsAsync { get => throw null; } @@ -30,21 +28,18 @@ namespace Microsoft public SafeFileHandle(System.IntPtr preexistingHandle, bool ownsHandle) : base(default(bool)) => throw null; } - // Generated from `Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SafeHandleMinusOneIsInvalid : System.Runtime.InteropServices.SafeHandle { public override bool IsInvalid { get => throw null; } protected SafeHandleMinusOneIsInvalid(bool ownsHandle) : base(default(System.IntPtr), default(bool)) => throw null; } - // Generated from `Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SafeHandleZeroOrMinusOneIsInvalid : System.Runtime.InteropServices.SafeHandle { public override bool IsInvalid { get => throw null; } protected SafeHandleZeroOrMinusOneIsInvalid(bool ownsHandle) : base(default(System.IntPtr), default(bool)) => throw null; } - // Generated from `Microsoft.Win32.SafeHandles.SafeWaitHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeWaitHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { protected override bool ReleaseHandle() => throw null; @@ -57,7 +52,6 @@ namespace Microsoft } namespace System { - // Generated from `System.AccessViolationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AccessViolationException : System.SystemException { public AccessViolationException() => throw null; @@ -66,58 +60,40 @@ namespace System public AccessViolationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Action` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(); - // Generated from `System.Action<,,,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); - // Generated from `System.Action<,,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - // Generated from `System.Action<,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - // Generated from `System.Action<,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - // Generated from `System.Action<,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - // Generated from `System.Action<,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - // Generated from `System.Action<,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - // Generated from `System.Action<,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); - // Generated from `System.Action<,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); - // Generated from `System.Action<,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - // Generated from `System.Action<,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - // Generated from `System.Action<,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - // Generated from `System.Action<,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - // Generated from `System.Action<,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2, T3 arg3); - // Generated from `System.Action<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T1 arg1, T2 arg2); - // Generated from `System.Action<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void Action(T obj); - // Generated from `System.Activator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Activator { public static object CreateInstance(System.Type type) => throw null; @@ -135,7 +111,6 @@ namespace System public static System.Runtime.Remoting.ObjectHandle CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes) => throw null; } - // Generated from `System.AggregateException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AggregateException : System.Exception { public AggregateException() => throw null; @@ -155,17 +130,16 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.AppContext` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class AppContext { public static string BaseDirectory { get => throw null; } public static object GetData(string name) => throw null; + public static void SetData(string name, object data) => throw null; public static void SetSwitch(string switchName, bool isEnabled) => throw null; public static string TargetFrameworkName { get => throw null; } public static bool TryGetSwitch(string switchName, out bool isEnabled) => throw null; } - // Generated from `System.AppDomain` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AppDomain : System.MarshalByRefObject { public void AppendPrivatePath(string path) => throw null; @@ -238,14 +212,12 @@ namespace System public static void Unload(System.AppDomain domain) => throw null; } - // Generated from `System.AppDomainSetup` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AppDomainSetup { public string ApplicationBase { get => throw null; } public string TargetFrameworkName { get => throw null; } } - // Generated from `System.AppDomainUnloadedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AppDomainUnloadedException : System.SystemException { public AppDomainUnloadedException() => throw null; @@ -254,7 +226,6 @@ namespace System public AppDomainUnloadedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ApplicationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ApplicationException : System.Exception { public ApplicationException() => throw null; @@ -263,7 +234,6 @@ namespace System public ApplicationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ApplicationId` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ApplicationId { public ApplicationId(System.Byte[] publicKeyToken, string name, System.Version version, string processorArchitecture, string culture) => throw null; @@ -278,7 +248,6 @@ namespace System public System.Version Version { get => throw null; } } - // Generated from `System.ArgIterator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ArgIterator { // Stub generator skipped constructor @@ -293,7 +262,6 @@ namespace System public int GetRemainingCount() => throw null; } - // Generated from `System.ArgumentException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArgumentException : System.SystemException { public ArgumentException() => throw null; @@ -305,9 +273,9 @@ namespace System public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; public override string Message { get => throw null; } public virtual string ParamName { get => throw null; } + public static void ThrowIfNullOrEmpty(string argument, string paramName = default(string)) => throw null; } - // Generated from `System.ArgumentNullException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArgumentNullException : System.ArgumentException { public ArgumentNullException() => throw null; @@ -315,10 +283,10 @@ namespace System public ArgumentNullException(string paramName) => throw null; public ArgumentNullException(string message, System.Exception innerException) => throw null; public ArgumentNullException(string paramName, string message) => throw null; + unsafe public static void ThrowIfNull(void* argument, string paramName = default(string)) => throw null; public static void ThrowIfNull(object argument, string paramName = default(string)) => throw null; } - // Generated from `System.ArgumentOutOfRangeException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArgumentOutOfRangeException : System.ArgumentException { public virtual object ActualValue { get => throw null; } @@ -332,7 +300,6 @@ namespace System public override string Message { get => throw null; } } - // Generated from `System.ArithmeticException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArithmeticException : System.SystemException { public ArithmeticException() => throw null; @@ -341,7 +308,6 @@ namespace System public ArithmeticException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Array` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Array : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.ICloneable { int System.Collections.IList.Add(object value) => throw null; @@ -463,10 +429,8 @@ namespace System public static bool TrueForAll(T[] array, System.Predicate match) => throw null; } - // Generated from `System.ArraySegment<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ArraySegment : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.IEnumerable { - // Generated from `System.ArraySegment<>+Enumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public T Current { get => throw null; } @@ -513,7 +477,6 @@ namespace System public static implicit operator System.ArraySegment(T[] array) => throw null; } - // Generated from `System.ArrayTypeMismatchException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArrayTypeMismatchException : System.SystemException { public ArrayTypeMismatchException() => throw null; @@ -522,20 +485,16 @@ namespace System public ArrayTypeMismatchException(string message, System.Exception innerException) => throw null; } - // Generated from `System.AssemblyLoadEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyLoadEventArgs : System.EventArgs { public AssemblyLoadEventArgs(System.Reflection.Assembly loadedAssembly) => throw null; public System.Reflection.Assembly LoadedAssembly { get => throw null; } } - // Generated from `System.AssemblyLoadEventHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void AssemblyLoadEventHandler(object sender, System.AssemblyLoadEventArgs args); - // Generated from `System.AsyncCallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void AsyncCallback(System.IAsyncResult ar); - // Generated from `System.Attribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Attribute { protected Attribute() => throw null; @@ -578,7 +537,6 @@ namespace System public virtual object TypeId { get => throw null; } } - // Generated from `System.AttributeTargets` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AttributeTargets : int { @@ -600,7 +558,6 @@ namespace System Struct = 8, } - // Generated from `System.AttributeUsageAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AttributeUsageAttribute : System.Attribute { public bool AllowMultiple { get => throw null; set => throw null; } @@ -609,7 +566,6 @@ namespace System public System.AttributeTargets ValidOn { get => throw null; } } - // Generated from `System.BadImageFormatException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BadImageFormatException : System.SystemException { public BadImageFormatException() => throw null; @@ -625,7 +581,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Base64FormattingOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum Base64FormattingOptions : int { @@ -633,7 +588,6 @@ namespace System None = 0, } - // Generated from `System.BitConverter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class BitConverter { public static System.Int64 DoubleToInt64Bits(double value) => throw null; @@ -698,7 +652,6 @@ namespace System public static double UInt64BitsToDouble(System.UInt64 value) => throw null; } - // Generated from `System.Boolean` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Boolean : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable { // Stub generator skipped constructor @@ -734,7 +687,6 @@ namespace System public static bool TryParse(string value, out bool result) => throw null; } - // Generated from `System.Buffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Buffer { public static void BlockCopy(System.Array src, int srcOffset, System.Array dst, int dstOffset, int count) => throw null; @@ -745,23 +697,90 @@ namespace System public static void SetByte(System.Array array, int index, System.Byte value) => throw null; } - // Generated from `System.Byte` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Byte : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Byte : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber { + static bool System.Numerics.IEqualityOperators.operator !=(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IModulusOperators.operator %(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IBitwiseOperators.operator &(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IMultiplyOperators.operator *(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IUnaryPlusOperators.operator +(System.Byte value) => throw null; + static System.Byte System.Numerics.IAdditionOperators.operator +(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IIncrementOperators.operator ++(System.Byte value) => throw null; + static System.Byte System.Numerics.IUnaryNegationOperators.operator -(System.Byte value) => throw null; + static System.Byte System.Numerics.ISubtractionOperators.operator -(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IDecrementOperators.operator --(System.Byte value) => throw null; + static System.Byte System.Numerics.IDivisionOperators.operator /(System.Byte left, System.Byte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IShiftOperators.operator <<(System.Byte value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Byte left, System.Byte right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Byte left, System.Byte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Byte left, System.Byte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IShiftOperators.operator >>(System.Byte value, int shiftAmount) => throw null; + static System.Byte System.Numerics.IShiftOperators.operator >>>(System.Byte value, int shiftAmount) => throw null; + public static System.Byte Abs(System.Byte value) => throw null; + static System.Byte System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Byte System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } // Stub generator skipped constructor + public static System.Byte Clamp(System.Byte value, System.Byte min, System.Byte max) => throw null; public int CompareTo(System.Byte value) => throw null; public int CompareTo(object value) => throw null; + public static System.Byte CopySign(System.Byte value, System.Byte sign) => throw null; + static System.Byte System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Byte System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Byte System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.Byte, System.Byte) DivRem(System.Byte left, System.Byte right) => throw null; public bool Equals(System.Byte obj) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.Byte value) => throw null; + public static bool IsComplexNumber(System.Byte value) => throw null; + public static bool IsEvenInteger(System.Byte value) => throw null; + public static bool IsFinite(System.Byte value) => throw null; + public static bool IsImaginaryNumber(System.Byte value) => throw null; + public static bool IsInfinity(System.Byte value) => throw null; + public static bool IsInteger(System.Byte value) => throw null; + public static bool IsNaN(System.Byte value) => throw null; + public static bool IsNegative(System.Byte value) => throw null; + public static bool IsNegativeInfinity(System.Byte value) => throw null; + public static bool IsNormal(System.Byte value) => throw null; + public static bool IsOddInteger(System.Byte value) => throw null; + public static bool IsPositive(System.Byte value) => throw null; + public static bool IsPositiveInfinity(System.Byte value) => throw null; + public static bool IsPow2(System.Byte value) => throw null; + public static bool IsRealNumber(System.Byte value) => throw null; + public static bool IsSubnormal(System.Byte value) => throw null; + public static bool IsZero(System.Byte value) => throw null; + public static System.Byte LeadingZeroCount(System.Byte value) => throw null; + public static System.Byte Log2(System.Byte value) => throw null; + public static System.Byte Max(System.Byte x, System.Byte y) => throw null; + public static System.Byte MaxMagnitude(System.Byte x, System.Byte y) => throw null; + public static System.Byte MaxMagnitudeNumber(System.Byte x, System.Byte y) => throw null; + public static System.Byte MaxNumber(System.Byte x, System.Byte y) => throw null; public const System.Byte MaxValue = default; + static System.Byte System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Byte Min(System.Byte x, System.Byte y) => throw null; + public static System.Byte MinMagnitude(System.Byte x, System.Byte y) => throw null; + public static System.Byte MinMagnitudeNumber(System.Byte x, System.Byte y) => throw null; + public static System.Byte MinNumber(System.Byte x, System.Byte y) => throw null; public const System.Byte MinValue = default; + static System.Byte System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Byte System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Byte System.Numerics.INumberBase.One { get => throw null; } + public static System.Byte Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Byte Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Byte Parse(string s) => throw null; public static System.Byte Parse(string s, System.IFormatProvider provider) => throw null; public static System.Byte Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.Byte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Byte PopCount(System.Byte value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Byte RotateLeft(System.Byte value, int rotateAmount) => throw null; + public static System.Byte RotateRight(System.Byte value, int rotateAmount) => throw null; + public static int Sign(System.Byte value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -781,21 +800,42 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.Byte TrailingZeroCount(System.Byte value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Byte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Byte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Byte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Byte value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Byte value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Byte value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Byte result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Byte result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.Byte result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Byte result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Byte result) => throw null; public static bool TryParse(string s, out System.Byte result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Byte value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Byte value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Byte System.Numerics.INumberBase.Zero { get => throw null; } + static System.Byte System.Numerics.IBitwiseOperators.operator ^(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IMultiplyOperators.operator checked *(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IAdditionOperators.operator checked +(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IIncrementOperators.operator checked ++(System.Byte value) => throw null; + static System.Byte System.Numerics.IUnaryNegationOperators.operator checked -(System.Byte value) => throw null; + static System.Byte System.Numerics.ISubtractionOperators.operator checked -(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IDecrementOperators.operator checked --(System.Byte value) => throw null; + static System.Byte System.Numerics.IBitwiseOperators.operator |(System.Byte left, System.Byte right) => throw null; + static System.Byte System.Numerics.IBitwiseOperators.operator ~(System.Byte value) => throw null; } - // Generated from `System.CLSCompliantAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CLSCompliantAttribute : System.Attribute { public CLSCompliantAttribute(bool isCompliant) => throw null; public bool IsCompliant { get => throw null; } } - // Generated from `System.CannotUnloadAppDomainException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CannotUnloadAppDomainException : System.SystemException { public CannotUnloadAppDomainException() => throw null; @@ -804,9 +844,30 @@ namespace System public CannotUnloadAppDomainException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Char` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Char : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Char : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber { + static bool System.Numerics.IEqualityOperators.operator !=(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IModulusOperators.operator %(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IBitwiseOperators.operator &(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IMultiplyOperators.operator *(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IUnaryPlusOperators.operator +(System.Char value) => throw null; + static System.Char System.Numerics.IAdditionOperators.operator +(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IIncrementOperators.operator ++(System.Char value) => throw null; + static System.Char System.Numerics.IUnaryNegationOperators.operator -(System.Char value) => throw null; + static System.Char System.Numerics.ISubtractionOperators.operator -(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IDecrementOperators.operator --(System.Char value) => throw null; + static System.Char System.Numerics.IDivisionOperators.operator /(System.Char left, System.Char right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IShiftOperators.operator <<(System.Char value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Char left, System.Char right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Char left, System.Char right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Char left, System.Char right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IShiftOperators.operator >>(System.Char value, int shiftAmount) => throw null; + static System.Char System.Numerics.IShiftOperators.operator >>>(System.Char value, int shiftAmount) => throw null; + public static System.Char Abs(System.Char value) => throw null; + static System.Char System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Char System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } // Stub generator skipped constructor public int CompareTo(System.Char value) => throw null; public int CompareTo(object value) => throw null; @@ -815,19 +876,37 @@ namespace System public static int ConvertToUtf32(string s, int index) => throw null; public bool Equals(System.Char obj) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; public static double GetNumericValue(System.Char c) => throw null; public static double GetNumericValue(string s, int index) => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; public static System.Globalization.UnicodeCategory GetUnicodeCategory(System.Char c) => throw null; public static System.Globalization.UnicodeCategory GetUnicodeCategory(string s, int index) => throw null; public static bool IsAscii(System.Char c) => throw null; + public static bool IsAsciiDigit(System.Char c) => throw null; + public static bool IsAsciiHexDigit(System.Char c) => throw null; + public static bool IsAsciiHexDigitLower(System.Char c) => throw null; + public static bool IsAsciiHexDigitUpper(System.Char c) => throw null; + public static bool IsAsciiLetter(System.Char c) => throw null; + public static bool IsAsciiLetterLower(System.Char c) => throw null; + public static bool IsAsciiLetterOrDigit(System.Char c) => throw null; + public static bool IsAsciiLetterUpper(System.Char c) => throw null; + public static bool IsBetween(System.Char c, System.Char minInclusive, System.Char maxInclusive) => throw null; + public static bool IsCanonical(System.Char value) => throw null; + public static bool IsComplexNumber(System.Char value) => throw null; public static bool IsControl(System.Char c) => throw null; public static bool IsControl(string s, int index) => throw null; public static bool IsDigit(System.Char c) => throw null; public static bool IsDigit(string s, int index) => throw null; + public static bool IsEvenInteger(System.Char value) => throw null; + public static bool IsFinite(System.Char value) => throw null; public static bool IsHighSurrogate(System.Char c) => throw null; public static bool IsHighSurrogate(string s, int index) => throw null; + public static bool IsImaginaryNumber(System.Char value) => throw null; + public static bool IsInfinity(System.Char value) => throw null; + public static bool IsInteger(System.Char value) => throw null; public static bool IsLetter(System.Char c) => throw null; public static bool IsLetter(string s, int index) => throw null; public static bool IsLetterOrDigit(System.Char c) => throw null; @@ -836,12 +915,22 @@ namespace System public static bool IsLowSurrogate(string s, int index) => throw null; public static bool IsLower(System.Char c) => throw null; public static bool IsLower(string s, int index) => throw null; + public static bool IsNaN(System.Char value) => throw null; + public static bool IsNegative(System.Char value) => throw null; + public static bool IsNegativeInfinity(System.Char value) => throw null; + public static bool IsNormal(System.Char value) => throw null; public static bool IsNumber(System.Char c) => throw null; public static bool IsNumber(string s, int index) => throw null; + public static bool IsOddInteger(System.Char value) => throw null; + public static bool IsPositive(System.Char value) => throw null; + public static bool IsPositiveInfinity(System.Char value) => throw null; + public static bool IsPow2(System.Char value) => throw null; public static bool IsPunctuation(System.Char c) => throw null; public static bool IsPunctuation(string s, int index) => throw null; + public static bool IsRealNumber(System.Char value) => throw null; public static bool IsSeparator(System.Char c) => throw null; public static bool IsSeparator(string s, int index) => throw null; + public static bool IsSubnormal(System.Char value) => throw null; public static bool IsSurrogate(System.Char c) => throw null; public static bool IsSurrogate(string s, int index) => throw null; public static bool IsSurrogatePair(System.Char highSurrogate, System.Char lowSurrogate) => throw null; @@ -852,9 +941,28 @@ namespace System public static bool IsUpper(string s, int index) => throw null; public static bool IsWhiteSpace(System.Char c) => throw null; public static bool IsWhiteSpace(string s, int index) => throw null; + public static bool IsZero(System.Char value) => throw null; + public static System.Char LeadingZeroCount(System.Char value) => throw null; + public static System.Char Log2(System.Char value) => throw null; + public static System.Char MaxMagnitude(System.Char x, System.Char y) => throw null; + public static System.Char MaxMagnitudeNumber(System.Char x, System.Char y) => throw null; public const System.Char MaxValue = default; + static System.Char System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Char MinMagnitude(System.Char x, System.Char y) => throw null; + public static System.Char MinMagnitudeNumber(System.Char x, System.Char y) => throw null; public const System.Char MinValue = default; + static System.Char System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Char System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Char System.Numerics.INumberBase.One { get => throw null; } + public static System.Char Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; + public static System.Char Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; public static System.Char Parse(string s) => throw null; + public static System.Char Parse(string s, System.IFormatProvider provider) => throw null; + public static System.Char Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Char PopCount(System.Char value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Char RotateLeft(System.Char value, int rotateAmount) => throw null; + public static System.Char RotateRight(System.Char value, int rotateAmount) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -880,11 +988,35 @@ namespace System public static System.Char ToUpper(System.Char c) => throw null; public static System.Char ToUpper(System.Char c, System.Globalization.CultureInfo culture) => throw null; public static System.Char ToUpperInvariant(System.Char c) => throw null; + public static System.Char TrailingZeroCount(System.Char value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Char result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Char result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Char result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Char value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Char value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Char value, out TOther result) => throw null; bool System.ISpanFormattable.TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider provider) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Char result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Char result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Char result) => throw null; + public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Char result) => throw null; public static bool TryParse(string s, out System.Char result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Char value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Char value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Char System.Numerics.INumberBase.Zero { get => throw null; } + static System.Char System.Numerics.IBitwiseOperators.operator ^(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IMultiplyOperators.operator checked *(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IAdditionOperators.operator checked +(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IIncrementOperators.operator checked ++(System.Char value) => throw null; + static System.Char System.Numerics.IUnaryNegationOperators.operator checked -(System.Char value) => throw null; + static System.Char System.Numerics.ISubtractionOperators.operator checked -(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IDecrementOperators.operator checked --(System.Char value) => throw null; + static System.Char System.Numerics.IBitwiseOperators.operator |(System.Char left, System.Char right) => throw null; + static System.Char System.Numerics.IBitwiseOperators.operator ~(System.Char value) => throw null; } - // Generated from `System.CharEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CharEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.ICloneable, System.IDisposable { public object Clone() => throw null; @@ -895,16 +1027,13 @@ namespace System public void Reset() => throw null; } - // Generated from `System.Comparison<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate int Comparison(T x, T y); - // Generated from `System.ContextBoundObject` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ContextBoundObject : System.MarshalByRefObject { protected ContextBoundObject() => throw null; } - // Generated from `System.ContextMarshalException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContextMarshalException : System.SystemException { public ContextMarshalException() => throw null; @@ -913,13 +1042,11 @@ namespace System public ContextMarshalException(string message, System.Exception inner) => throw null; } - // Generated from `System.ContextStaticAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ContextStaticAttribute : System.Attribute { public ContextStaticAttribute() => throw null; } - // Generated from `System.Convert` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Convert { public static object ChangeType(object value, System.Type conversionType) => throw null; @@ -1244,10 +1371,8 @@ namespace System public static bool TryToBase64Chars(System.ReadOnlySpan bytes, System.Span chars, out int charsWritten, System.Base64FormattingOptions options = default(System.Base64FormattingOptions)) => throw null; } - // Generated from `System.Converter<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TOutput Converter(TInput input); - // Generated from `System.DBNull` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DBNull : System.IConvertible, System.Runtime.Serialization.ISerializable { public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -1272,8 +1397,7 @@ namespace System public static System.DBNull Value; } - // Generated from `System.DateOnly` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct DateOnly : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct DateOnly : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable { public static bool operator !=(System.DateOnly left, System.DateOnly right) => throw null; public static bool operator <(System.DateOnly left, System.DateOnly right) => throw null; @@ -1301,8 +1425,10 @@ namespace System public static System.DateOnly MaxValue { get => throw null; } public static System.DateOnly MinValue { get => throw null; } public int Month { get => throw null; } + public static System.DateOnly Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.DateOnly Parse(System.ReadOnlySpan s, System.IFormatProvider provider = default(System.IFormatProvider), System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.DateOnly Parse(string s) => throw null; + public static System.DateOnly Parse(string s, System.IFormatProvider provider) => throw null; public static System.DateOnly Parse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.DateOnly ParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider provider = default(System.IFormatProvider), System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.DateOnly ParseExact(System.ReadOnlySpan s, string[] formats) => throw null; @@ -1321,8 +1447,10 @@ namespace System public string ToString(string format, System.IFormatProvider provider) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.DateOnly result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.DateOnly result) => throw null; public static bool TryParse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.DateOnly result) => throw null; public static bool TryParse(string s, out System.DateOnly result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateOnly result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, out System.DateOnly result) => throw null; @@ -1335,8 +1463,7 @@ namespace System public int Year { get => throw null; } } - // Generated from `System.DateTime` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct DateTime : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable, System.Runtime.Serialization.ISerializable + public struct DateTime : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.DateTime d1, System.DateTime d2) => throw null; public static System.DateTime operator +(System.DateTime d, System.TimeSpan t) => throw null; @@ -1350,6 +1477,7 @@ namespace System public System.DateTime Add(System.TimeSpan value) => throw null; public System.DateTime AddDays(double value) => throw null; public System.DateTime AddHours(double value) => throw null; + public System.DateTime AddMicroseconds(double value) => throw null; public System.DateTime AddMilliseconds(double value) => throw null; public System.DateTime AddMinutes(double value) => throw null; public System.DateTime AddMonths(int months) => throw null; @@ -1370,6 +1498,10 @@ namespace System public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar) => throw null; public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar, System.DateTimeKind kind) => throw null; public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, System.DateTimeKind kind) => throw null; + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond) => throw null; + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.Globalization.Calendar calendar) => throw null; + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.Globalization.Calendar calendar, System.DateTimeKind kind) => throw null; + public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.DateTimeKind kind) => throw null; public DateTime(System.Int64 ticks) => throw null; public DateTime(System.Int64 ticks, System.DateTimeKind kind) => throw null; public int Day { get => throw null; } @@ -1395,11 +1527,14 @@ namespace System public static bool IsLeapYear(int year) => throw null; public System.DateTimeKind Kind { get => throw null; } public static System.DateTime MaxValue; + public int Microsecond { get => throw null; } public int Millisecond { get => throw null; } public static System.DateTime MinValue; public int Minute { get => throw null; } public int Month { get => throw null; } + public int Nanosecond { get => throw null; } public static System.DateTime Now { get => throw null; } + public static System.DateTime Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.DateTime Parse(System.ReadOnlySpan s, System.IFormatProvider provider = default(System.IFormatProvider), System.Globalization.DateTimeStyles styles = default(System.Globalization.DateTimeStyles)) => throw null; public static System.DateTime Parse(string s) => throw null; public static System.DateTime Parse(string s, System.IFormatProvider provider) => throw null; @@ -1447,8 +1582,10 @@ namespace System public static System.DateTime Today { get => throw null; } public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles, out System.DateTime result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.DateTime result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.DateTime result) => throw null; public static bool TryParse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles styles, out System.DateTime result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.DateTime result) => throw null; public static bool TryParse(string s, out System.DateTime result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateTime result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, string[] formats, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.DateTime result) => throw null; @@ -1459,7 +1596,6 @@ namespace System public int Year { get => throw null; } } - // Generated from `System.DateTimeKind` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DateTimeKind : int { Local = 2, @@ -1467,8 +1603,7 @@ namespace System Utc = 1, } - // Generated from `System.DateTimeOffset` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct DateTimeOffset : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable + public struct DateTimeOffset : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.DateTimeOffset left, System.DateTimeOffset right) => throw null; public static System.DateTimeOffset operator +(System.DateTimeOffset dateTimeOffset, System.TimeSpan timeSpan) => throw null; @@ -1482,6 +1617,7 @@ namespace System public System.DateTimeOffset Add(System.TimeSpan timeSpan) => throw null; public System.DateTimeOffset AddDays(double days) => throw null; public System.DateTimeOffset AddHours(double hours) => throw null; + public System.DateTimeOffset AddMicroseconds(double microseconds) => throw null; public System.DateTimeOffset AddMilliseconds(double milliseconds) => throw null; public System.DateTimeOffset AddMinutes(double minutes) => throw null; public System.DateTimeOffset AddMonths(int months) => throw null; @@ -1499,6 +1635,8 @@ namespace System public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, System.TimeSpan offset) => throw null; public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, System.Globalization.Calendar calendar, System.TimeSpan offset) => throw null; public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, System.TimeSpan offset) => throw null; + public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.Globalization.Calendar calendar, System.TimeSpan offset) => throw null; + public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond, System.TimeSpan offset) => throw null; public DateTimeOffset(System.Int64 ticks, System.TimeSpan offset) => throw null; public int Day { get => throw null; } public System.DayOfWeek DayOfWeek { get => throw null; } @@ -1515,13 +1653,16 @@ namespace System public int Hour { get => throw null; } public System.DateTime LocalDateTime { get => throw null; } public static System.DateTimeOffset MaxValue; + public int Microsecond { get => throw null; } public int Millisecond { get => throw null; } public static System.DateTimeOffset MinValue; public int Minute { get => throw null; } public int Month { get => throw null; } + public int Nanosecond { get => throw null; } public static System.DateTimeOffset Now { get => throw null; } public System.TimeSpan Offset { get => throw null; } void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null; + public static System.DateTimeOffset Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.DateTimeOffset Parse(System.ReadOnlySpan input, System.IFormatProvider formatProvider = default(System.IFormatProvider), System.Globalization.DateTimeStyles styles = default(System.Globalization.DateTimeStyles)) => throw null; public static System.DateTimeOffset Parse(string input) => throw null; public static System.DateTimeOffset Parse(string input, System.IFormatProvider formatProvider) => throw null; @@ -1548,8 +1689,10 @@ namespace System public System.Int64 ToUnixTimeSeconds() => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider formatProvider = default(System.IFormatProvider)) => throw null; public static bool TryParse(System.ReadOnlySpan input, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.DateTimeOffset result) => throw null; public static bool TryParse(System.ReadOnlySpan input, out System.DateTimeOffset result) => throw null; public static bool TryParse(string input, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.DateTimeOffset result) => throw null; public static bool TryParse(string input, out System.DateTimeOffset result) => throw null; public static bool TryParseExact(System.ReadOnlySpan input, System.ReadOnlySpan format, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) => throw null; public static bool TryParseExact(System.ReadOnlySpan input, string[] formats, System.IFormatProvider formatProvider, System.Globalization.DateTimeStyles styles, out System.DateTimeOffset result) => throw null; @@ -1563,7 +1706,6 @@ namespace System public static implicit operator System.DateTimeOffset(System.DateTime dateTime) => throw null; } - // Generated from `System.DayOfWeek` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DayOfWeek : int { Friday = 5, @@ -1575,29 +1717,35 @@ namespace System Wednesday = 3, } - // Generated from `System.Decimal` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Decimal : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable + public struct Decimal : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - public static bool operator !=(System.Decimal d1, System.Decimal d2) => throw null; - public static System.Decimal operator %(System.Decimal d1, System.Decimal d2) => throw null; - public static System.Decimal operator *(System.Decimal d1, System.Decimal d2) => throw null; - public static System.Decimal operator +(System.Decimal d) => throw null; - public static System.Decimal operator +(System.Decimal d1, System.Decimal d2) => throw null; - public static System.Decimal operator ++(System.Decimal d) => throw null; - public static System.Decimal operator -(System.Decimal d) => throw null; - public static System.Decimal operator -(System.Decimal d1, System.Decimal d2) => throw null; - public static System.Decimal operator --(System.Decimal d) => throw null; - public static System.Decimal operator /(System.Decimal d1, System.Decimal d2) => throw null; - public static bool operator <(System.Decimal d1, System.Decimal d2) => throw null; - public static bool operator <=(System.Decimal d1, System.Decimal d2) => throw null; - public static bool operator ==(System.Decimal d1, System.Decimal d2) => throw null; - public static bool operator >(System.Decimal d1, System.Decimal d2) => throw null; - public static bool operator >=(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IModulusOperators.operator %(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IMultiplyOperators.operator *(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IUnaryPlusOperators.operator +(System.Decimal d) => throw null; + static System.Decimal System.Numerics.IAdditionOperators.operator +(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IIncrementOperators.operator ++(System.Decimal d) => throw null; + static System.Decimal System.Numerics.IUnaryNegationOperators.operator -(System.Decimal d) => throw null; + static System.Decimal System.Numerics.ISubtractionOperators.operator -(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IDecrementOperators.operator --(System.Decimal d) => throw null; + static System.Decimal System.Numerics.IDivisionOperators.operator /(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Decimal d1, System.Decimal d2) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Decimal d1, System.Decimal d2) => throw null; + public static System.Decimal Abs(System.Decimal value) => throw null; public static System.Decimal Add(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } public static System.Decimal Ceiling(System.Decimal d) => throw null; + public static System.Decimal Clamp(System.Decimal value, System.Decimal min, System.Decimal max) => throw null; public static int Compare(System.Decimal d1, System.Decimal d2) => throw null; public int CompareTo(System.Decimal value) => throw null; public int CompareTo(object value) => throw null; + public static System.Decimal CopySign(System.Decimal value, System.Decimal sign) => throw null; + static System.Decimal System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Decimal System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Decimal System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; // Stub generator skipped constructor public Decimal(int[] bits) => throw null; public Decimal(System.ReadOnlySpan bits) => throw null; @@ -1609,6 +1757,7 @@ namespace System public Decimal(System.UInt32 value) => throw null; public Decimal(System.UInt64 value) => throw null; public static System.Decimal Divide(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IFloatingPointConstants.E { get => throw null; } public bool Equals(System.Decimal value) => throw null; public static bool Equals(System.Decimal d1, System.Decimal d2) => throw null; public override bool Equals(object value) => throw null; @@ -1616,27 +1765,67 @@ namespace System public static System.Decimal FromOACurrency(System.Int64 cy) => throw null; public static int[] GetBits(System.Decimal d) => throw null; public static int GetBits(System.Decimal d, System.Span destination) => throw null; + int System.Numerics.IFloatingPoint.GetExponentByteCount() => throw null; + int System.Numerics.IFloatingPoint.GetExponentShortestBitLength() => throw null; public override int GetHashCode() => throw null; void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + int System.Numerics.IFloatingPoint.GetSignificandBitLength() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandByteCount() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.Decimal value) => throw null; + public static bool IsComplexNumber(System.Decimal value) => throw null; + public static bool IsEvenInteger(System.Decimal value) => throw null; + public static bool IsFinite(System.Decimal value) => throw null; + public static bool IsImaginaryNumber(System.Decimal value) => throw null; + public static bool IsInfinity(System.Decimal value) => throw null; + public static bool IsInteger(System.Decimal value) => throw null; + public static bool IsNaN(System.Decimal value) => throw null; + public static bool IsNegative(System.Decimal value) => throw null; + public static bool IsNegativeInfinity(System.Decimal value) => throw null; + public static bool IsNormal(System.Decimal value) => throw null; + public static bool IsOddInteger(System.Decimal value) => throw null; + public static bool IsPositive(System.Decimal value) => throw null; + public static bool IsPositiveInfinity(System.Decimal value) => throw null; + public static bool IsRealNumber(System.Decimal value) => throw null; + public static bool IsSubnormal(System.Decimal value) => throw null; + public static bool IsZero(System.Decimal value) => throw null; + public static System.Decimal Max(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MaxMagnitude(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MaxMagnitudeNumber(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MaxNumber(System.Decimal x, System.Decimal y) => throw null; public const System.Decimal MaxValue = default; + static System.Decimal System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Decimal Min(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MinMagnitude(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MinMagnitudeNumber(System.Decimal x, System.Decimal y) => throw null; + public static System.Decimal MinNumber(System.Decimal x, System.Decimal y) => throw null; public const System.Decimal MinValue = default; + static System.Decimal System.Numerics.IMinMaxValue.MinValue { get => throw null; } public const System.Decimal MinusOne = default; + static System.Decimal System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } public static System.Decimal Multiply(System.Decimal d1, System.Decimal d2) => throw null; public static System.Decimal Negate(System.Decimal d) => throw null; + static System.Decimal System.Numerics.ISignedNumber.NegativeOne { get => throw null; } void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null; public const System.Decimal One = default; + static System.Decimal System.Numerics.INumberBase.One { get => throw null; } + public static System.Decimal Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Decimal Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Decimal Parse(string s) => throw null; public static System.Decimal Parse(string s, System.IFormatProvider provider) => throw null; public static System.Decimal Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.Decimal Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + static System.Decimal System.Numerics.IFloatingPointConstants.Pi { get => throw null; } + static int System.Numerics.INumberBase.Radix { get => throw null; } public static System.Decimal Remainder(System.Decimal d1, System.Decimal d2) => throw null; public static System.Decimal Round(System.Decimal d) => throw null; public static System.Decimal Round(System.Decimal d, System.MidpointRounding mode) => throw null; public static System.Decimal Round(System.Decimal d, int decimals) => throw null; public static System.Decimal Round(System.Decimal d, int decimals, System.MidpointRounding mode) => throw null; + public System.Byte Scale { get => throw null; } + public static int Sign(System.Decimal d) => throw null; public static System.Decimal Subtract(System.Decimal d1, System.Decimal d2) => throw null; + static System.Decimal System.Numerics.IFloatingPointConstants.Tau { get => throw null; } bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; public static System.Byte ToByte(System.Decimal value) => throw null; @@ -1668,13 +1857,26 @@ namespace System System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; public static System.UInt64 ToUInt64(System.Decimal d) => throw null; public static System.Decimal Truncate(System.Decimal d) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Decimal result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Decimal result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Decimal result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Decimal value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Decimal value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Decimal value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static bool TryGetBits(System.Decimal d, System.Span destination, out int valuesWritten) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Decimal result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Decimal result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.Decimal result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Decimal result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Decimal result) => throw null; public static bool TryParse(string s, out System.Decimal result) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten) => throw null; public const System.Decimal Zero = default; + static System.Decimal System.Numerics.INumberBase.Zero { get => throw null; } public static explicit operator System.Byte(System.Decimal value) => throw null; public static explicit operator System.Char(System.Decimal value) => throw null; public static explicit operator System.Int16(System.Decimal value) => throw null; @@ -1699,7 +1901,6 @@ namespace System public static implicit operator System.Decimal(System.UInt16 value) => throw null; } - // Generated from `System.Delegate` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Delegate : System.ICloneable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Delegate d1, System.Delegate d2) => throw null; @@ -1734,7 +1935,6 @@ namespace System public object Target { get => throw null; } } - // Generated from `System.DivideByZeroException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DivideByZeroException : System.ArithmeticException { public DivideByZeroException() => throw null; @@ -1743,41 +1943,154 @@ namespace System public DivideByZeroException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Double` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Double : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Double : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryFloatingPointIeee754, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { - public static bool operator !=(double left, double right) => throw null; - public static bool operator <(double left, double right) => throw null; - public static bool operator <=(double left, double right) => throw null; - public static bool operator ==(double left, double right) => throw null; - public static bool operator >(double left, double right) => throw null; - public static bool operator >=(double left, double right) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(double left, double right) => throw null; + static double System.Numerics.IModulusOperators.operator %(double left, double right) => throw null; + static double System.Numerics.IBitwiseOperators.operator &(double left, double right) => throw null; + static double System.Numerics.IMultiplyOperators.operator *(double left, double right) => throw null; + static double System.Numerics.IUnaryPlusOperators.operator +(double value) => throw null; + static double System.Numerics.IAdditionOperators.operator +(double left, double right) => throw null; + static double System.Numerics.IIncrementOperators.operator ++(double value) => throw null; + static double System.Numerics.IUnaryNegationOperators.operator -(double value) => throw null; + static double System.Numerics.ISubtractionOperators.operator -(double left, double right) => throw null; + static double System.Numerics.IDecrementOperators.operator --(double value) => throw null; + static double System.Numerics.IDivisionOperators.operator /(double left, double right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(double left, double right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(double left, double right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(double left, double right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(double left, double right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(double left, double right) => throw null; + public static double Abs(double value) => throw null; + public static double Acos(double x) => throw null; + public static double AcosPi(double x) => throw null; + public static double Acosh(double x) => throw null; + static double System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static double System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static double Asin(double x) => throw null; + public static double AsinPi(double x) => throw null; + public static double Asinh(double x) => throw null; + public static double Atan(double x) => throw null; + public static double Atan2(double y, double x) => throw null; + public static double Atan2Pi(double y, double x) => throw null; + public static double AtanPi(double x) => throw null; + public static double Atanh(double x) => throw null; + public static double BitDecrement(double x) => throw null; + public static double BitIncrement(double x) => throw null; + public static double Cbrt(double x) => throw null; + public static double Ceiling(double x) => throw null; + public static double Clamp(double value, double min, double max) => throw null; public int CompareTo(double value) => throw null; public int CompareTo(object value) => throw null; + public static double CopySign(double value, double sign) => throw null; + public static double Cos(double x) => throw null; + public static double CosPi(double x) => throw null; + public static double Cosh(double x) => throw null; + static double System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static double System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static double System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; // Stub generator skipped constructor + public const double E = default; + static double System.Numerics.IFloatingPointConstants.E { get => throw null; } public const double Epsilon = default; + static double System.Numerics.IFloatingPointIeee754.Epsilon { get => throw null; } public bool Equals(double obj) => throw null; public override bool Equals(object obj) => throw null; + public static double Exp(double x) => throw null; + public static double Exp10(double x) => throw null; + public static double Exp10M1(double x) => throw null; + public static double Exp2(double x) => throw null; + public static double Exp2M1(double x) => throw null; + public static double ExpM1(double x) => throw null; + public static double Floor(double x) => throw null; + public static double FusedMultiplyAdd(double left, double right, double addend) => throw null; + int System.Numerics.IFloatingPoint.GetExponentByteCount() => throw null; + int System.Numerics.IFloatingPoint.GetExponentShortestBitLength() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandBitLength() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandByteCount() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static double Hypot(double x, double y) => throw null; + public static int ILogB(double x) => throw null; + public static double Ieee754Remainder(double left, double right) => throw null; + public static bool IsCanonical(double value) => throw null; + public static bool IsComplexNumber(double value) => throw null; + public static bool IsEvenInteger(double value) => throw null; public static bool IsFinite(double d) => throw null; + public static bool IsImaginaryNumber(double value) => throw null; public static bool IsInfinity(double d) => throw null; + public static bool IsInteger(double value) => throw null; public static bool IsNaN(double d) => throw null; public static bool IsNegative(double d) => throw null; public static bool IsNegativeInfinity(double d) => throw null; public static bool IsNormal(double d) => throw null; + public static bool IsOddInteger(double value) => throw null; + public static bool IsPositive(double value) => throw null; public static bool IsPositiveInfinity(double d) => throw null; + public static bool IsPow2(double value) => throw null; + public static bool IsRealNumber(double value) => throw null; public static bool IsSubnormal(double d) => throw null; + public static bool IsZero(double value) => throw null; + public static double Log(double x) => throw null; + public static double Log(double x, double newBase) => throw null; + public static double Log10(double x) => throw null; + public static double Log10P1(double x) => throw null; + public static double Log2(double value) => throw null; + public static double Log2P1(double x) => throw null; + public static double LogP1(double x) => throw null; + public static double Max(double x, double y) => throw null; + public static double MaxMagnitude(double x, double y) => throw null; + public static double MaxMagnitudeNumber(double x, double y) => throw null; + public static double MaxNumber(double x, double y) => throw null; public const double MaxValue = default; + static double System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static double Min(double x, double y) => throw null; + public static double MinMagnitude(double x, double y) => throw null; + public static double MinMagnitudeNumber(double x, double y) => throw null; + public static double MinNumber(double x, double y) => throw null; public const double MinValue = default; + static double System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static double System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } public const double NaN = default; + static double System.Numerics.IFloatingPointIeee754.NaN { get => throw null; } public const double NegativeInfinity = default; + static double System.Numerics.IFloatingPointIeee754.NegativeInfinity { get => throw null; } + static double System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + public const double NegativeZero = default; + static double System.Numerics.IFloatingPointIeee754.NegativeZero { get => throw null; } + static double System.Numerics.INumberBase.One { get => throw null; } + public static double Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static double Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static double Parse(string s) => throw null; public static double Parse(string s, System.IFormatProvider provider) => throw null; public static double Parse(string s, System.Globalization.NumberStyles style) => throw null; public static double Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public const double Pi = default; + static double System.Numerics.IFloatingPointConstants.Pi { get => throw null; } public const double PositiveInfinity = default; + static double System.Numerics.IFloatingPointIeee754.PositiveInfinity { get => throw null; } + public static double Pow(double x, double y) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static double ReciprocalEstimate(double x) => throw null; + public static double ReciprocalSqrtEstimate(double x) => throw null; + public static double RootN(double x, int n) => throw null; + public static double Round(double x) => throw null; + public static double Round(double x, System.MidpointRounding mode) => throw null; + public static double Round(double x, int digits) => throw null; + public static double Round(double x, int digits, System.MidpointRounding mode) => throw null; + public static double ScaleB(double x, int n) => throw null; + public static int Sign(double value) => throw null; + public static double Sin(double x) => throw null; + public static (double, double) SinCos(double x) => throw null; + public static (double, double) SinCosPi(double x) => throw null; + public static double SinPi(double x) => throw null; + public static double Sinh(double x) => throw null; + public static double Sqrt(double x) => throw null; + public static double Tan(double x) => throw null; + public static double TanPi(double x) => throw null; + public static double Tanh(double x) => throw null; + public const double Tau = default; + static double System.Numerics.IFloatingPointConstants.Tau { get => throw null; } bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -1797,14 +2110,30 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static double Truncate(double x) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out double result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out double result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out double result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(double value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(double value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(double value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out double result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out double result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out double result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out double result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out double result) => throw null; public static bool TryParse(string s, out double result) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static double System.Numerics.INumberBase.Zero { get => throw null; } + static double System.Numerics.IBitwiseOperators.operator ^(double left, double right) => throw null; + static double System.Numerics.IBitwiseOperators.operator |(double left, double right) => throw null; + static double System.Numerics.IBitwiseOperators.operator ~(double value) => throw null; } - // Generated from `System.DuplicateWaitObjectException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DuplicateWaitObjectException : System.ArgumentException { public DuplicateWaitObjectException() => throw null; @@ -1814,7 +2143,6 @@ namespace System public DuplicateWaitObjectException(string parameterName, string message) => throw null; } - // Generated from `System.EntryPointNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EntryPointNotFoundException : System.TypeLoadException { public EntryPointNotFoundException() => throw null; @@ -1823,7 +2151,6 @@ namespace System public EntryPointNotFoundException(string message, System.Exception inner) => throw null; } - // Generated from `System.Enum` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Enum : System.IComparable, System.IConvertible, System.IFormattable { public int CompareTo(object target) => throw null; @@ -1839,6 +2166,8 @@ namespace System public static System.Type GetUnderlyingType(System.Type enumType) => throw null; public static System.Array GetValues(System.Type enumType) => throw null; public static TEnum[] GetValues() where TEnum : System.Enum => throw null; + public static System.Array GetValuesAsUnderlyingType(System.Type enumType) => throw null; + public static System.Array GetValuesAsUnderlyingType() where TEnum : System.Enum => throw null; public bool HasFlag(System.Enum flag) => throw null; public static bool IsDefined(System.Type enumType, object value) => throw null; public static bool IsDefined(TEnum value) where TEnum : System.Enum => throw null; @@ -1888,10 +2217,8 @@ namespace System public static bool TryParse(string value, out TEnum result) where TEnum : struct => throw null; } - // Generated from `System.Environment` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Environment { - // Generated from `System.Environment+SpecialFolder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SpecialFolder : int { AdminTools = 48, @@ -1944,7 +2271,6 @@ namespace System } - // Generated from `System.Environment+SpecialFolderOption` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SpecialFolderOption : int { Create = 32768, @@ -1992,7 +2318,6 @@ namespace System public static System.Int64 WorkingSet { get => throw null; } } - // Generated from `System.EnvironmentVariableTarget` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EnvironmentVariableTarget : int { Machine = 2, @@ -2000,20 +2325,16 @@ namespace System User = 1, } - // Generated from `System.EventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventArgs { public static System.EventArgs Empty; public EventArgs() => throw null; } - // Generated from `System.EventHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void EventHandler(object sender, System.EventArgs e); - // Generated from `System.EventHandler<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void EventHandler(object sender, TEventArgs e); - // Generated from `System.Exception` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Exception : System.Runtime.Serialization.ISerializable { public virtual System.Collections.IDictionary Data { get => throw null; } @@ -2035,7 +2356,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.ExecutionEngineException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExecutionEngineException : System.SystemException { public ExecutionEngineException() => throw null; @@ -2043,7 +2363,6 @@ namespace System public ExecutionEngineException(string message, System.Exception innerException) => throw null; } - // Generated from `System.FieldAccessException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FieldAccessException : System.MemberAccessException { public FieldAccessException() => throw null; @@ -2052,19 +2371,16 @@ namespace System public FieldAccessException(string message, System.Exception inner) => throw null; } - // Generated from `System.FileStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileStyleUriParser : System.UriParser { public FileStyleUriParser() => throw null; } - // Generated from `System.FlagsAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FlagsAttribute : System.Attribute { public FlagsAttribute() => throw null; } - // Generated from `System.FormatException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FormatException : System.SystemException { public FormatException() => throw null; @@ -2073,7 +2389,6 @@ namespace System public FormatException(string message, System.Exception innerException) => throw null; } - // Generated from `System.FormattableString` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class FormattableString : System.IFormattable { public abstract int ArgumentCount { get; } @@ -2088,64 +2403,45 @@ namespace System string System.IFormattable.ToString(string ignored, System.IFormatProvider formatProvider) => throw null; } - // Generated from `System.FtpStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FtpStyleUriParser : System.UriParser { public FtpStyleUriParser() => throw null; } - // Generated from `System.Func<,,,,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); - // Generated from `System.Func<,,,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - // Generated from `System.Func<,,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - // Generated from `System.Func<,,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - // Generated from `System.Func<,,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - // Generated from `System.Func<,,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - // Generated from `System.Func<,,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - // Generated from `System.Func<,,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); - // Generated from `System.Func<,,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); - // Generated from `System.Func<,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - // Generated from `System.Func<,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - // Generated from `System.Func<,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - // Generated from `System.Func<,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - // Generated from `System.Func<,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - // Generated from `System.Func<,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T1 arg1, T2 arg2); - // Generated from `System.Func<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(T arg); - // Generated from `System.Func<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult Func(); - // Generated from `System.GC` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class GC { public static void AddMemoryPressure(System.Int64 bytesAllocated) => throw null; @@ -2160,12 +2456,14 @@ namespace System public static int CollectionCount(int generation) => throw null; public static void EndNoGCRegion() => throw null; public static System.Int64 GetAllocatedBytesForCurrentThread() => throw null; + public static System.Collections.Generic.IReadOnlyDictionary GetConfigurationVariables() => throw null; public static System.GCMemoryInfo GetGCMemoryInfo() => throw null; public static System.GCMemoryInfo GetGCMemoryInfo(System.GCKind kind) => throw null; public static int GetGeneration(System.WeakReference wo) => throw null; public static int GetGeneration(object obj) => throw null; public static System.Int64 GetTotalAllocatedBytes(bool precise = default(bool)) => throw null; public static System.Int64 GetTotalMemory(bool forceFullCollection) => throw null; + public static System.TimeSpan GetTotalPauseDuration() => throw null; public static void KeepAlive(object obj) => throw null; public static int MaxGeneration { get => throw null; } public static void ReRegisterForFinalize(object obj) => throw null; @@ -2177,21 +2475,22 @@ namespace System public static bool TryStartNoGCRegion(System.Int64 totalSize, System.Int64 lohSize) => throw null; public static bool TryStartNoGCRegion(System.Int64 totalSize, System.Int64 lohSize, bool disallowFullBlockingGC) => throw null; public static System.GCNotificationStatus WaitForFullGCApproach() => throw null; + public static System.GCNotificationStatus WaitForFullGCApproach(System.TimeSpan timeout) => throw null; public static System.GCNotificationStatus WaitForFullGCApproach(int millisecondsTimeout) => throw null; public static System.GCNotificationStatus WaitForFullGCComplete() => throw null; + public static System.GCNotificationStatus WaitForFullGCComplete(System.TimeSpan timeout) => throw null; public static System.GCNotificationStatus WaitForFullGCComplete(int millisecondsTimeout) => throw null; public static void WaitForPendingFinalizers() => throw null; } - // Generated from `System.GCCollectionMode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCCollectionMode : int { + Aggressive = 3, Default = 0, Forced = 1, Optimized = 2, } - // Generated from `System.GCGenerationInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GCGenerationInfo { public System.Int64 FragmentationAfterBytes { get => throw null; } @@ -2201,7 +2500,6 @@ namespace System public System.Int64 SizeBeforeBytes { get => throw null; } } - // Generated from `System.GCKind` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCKind : int { Any = 0, @@ -2210,7 +2508,6 @@ namespace System FullBlocking = 2, } - // Generated from `System.GCMemoryInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct GCMemoryInfo { public bool Compacted { get => throw null; } @@ -2232,7 +2529,6 @@ namespace System public System.Int64 TotalCommittedBytes { get => throw null; } } - // Generated from `System.GCNotificationStatus` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCNotificationStatus : int { Canceled = 2, @@ -2242,13 +2538,11 @@ namespace System Timeout = 3, } - // Generated from `System.GenericUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GenericUriParser : System.UriParser { public GenericUriParser(System.GenericUriParserOptions options) => throw null; } - // Generated from `System.GenericUriParserOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum GenericUriParserOptions : int { @@ -2266,17 +2560,19 @@ namespace System NoUserInfo = 4, } - // Generated from `System.GopherStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GopherStyleUriParser : System.UriParser { public GopherStyleUriParser() => throw null; } - // Generated from `System.Guid` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Guid : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Guid : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable { public static bool operator !=(System.Guid a, System.Guid b) => throw null; + public static bool operator <(System.Guid left, System.Guid right) => throw null; + public static bool operator <=(System.Guid left, System.Guid right) => throw null; public static bool operator ==(System.Guid a, System.Guid b) => throw null; + public static bool operator >(System.Guid left, System.Guid right) => throw null; + public static bool operator >=(System.Guid left, System.Guid right) => throw null; public int CompareTo(System.Guid value) => throw null; public int CompareTo(object value) => throw null; public static System.Guid Empty; @@ -2292,7 +2588,9 @@ namespace System public Guid(System.UInt32 a, System.UInt16 b, System.UInt16 c, System.Byte d, System.Byte e, System.Byte f, System.Byte g, System.Byte h, System.Byte i, System.Byte j, System.Byte k) => throw null; public static System.Guid NewGuid() => throw null; public static System.Guid Parse(System.ReadOnlySpan input) => throw null; + public static System.Guid Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Guid Parse(string input) => throw null; + public static System.Guid Parse(string s, System.IFormatProvider provider) => throw null; public static System.Guid ParseExact(System.ReadOnlySpan input, System.ReadOnlySpan format) => throw null; public static System.Guid ParseExact(string input, string format) => throw null; public System.Byte[] ToByteArray() => throw null; @@ -2301,63 +2599,223 @@ namespace System public string ToString(string format, System.IFormatProvider provider) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan)) => throw null; bool System.ISpanFormattable.TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider provider) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Guid result) => throw null; public static bool TryParse(System.ReadOnlySpan input, out System.Guid result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Guid result) => throw null; public static bool TryParse(string input, out System.Guid result) => throw null; public static bool TryParseExact(System.ReadOnlySpan input, System.ReadOnlySpan format, out System.Guid result) => throw null; public static bool TryParseExact(string input, string format, out System.Guid result) => throw null; public bool TryWriteBytes(System.Span destination) => throw null; } - // Generated from `System.Half` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Half : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Half : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryFloatingPointIeee754, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { - public static bool operator !=(System.Half left, System.Half right) => throw null; - public static bool operator <(System.Half left, System.Half right) => throw null; - public static bool operator <=(System.Half left, System.Half right) => throw null; - public static bool operator ==(System.Half left, System.Half right) => throw null; - public static bool operator >(System.Half left, System.Half right) => throw null; - public static bool operator >=(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IModulusOperators.operator %(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IBitwiseOperators.operator &(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IMultiplyOperators.operator *(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IUnaryPlusOperators.operator +(System.Half value) => throw null; + static System.Half System.Numerics.IAdditionOperators.operator +(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IIncrementOperators.operator ++(System.Half value) => throw null; + static System.Half System.Numerics.IUnaryNegationOperators.operator -(System.Half value) => throw null; + static System.Half System.Numerics.ISubtractionOperators.operator -(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IDecrementOperators.operator --(System.Half value) => throw null; + static System.Half System.Numerics.IDivisionOperators.operator /(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Half left, System.Half right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Half left, System.Half right) => throw null; + public static System.Half Abs(System.Half value) => throw null; + public static System.Half Acos(System.Half x) => throw null; + public static System.Half AcosPi(System.Half x) => throw null; + public static System.Half Acosh(System.Half x) => throw null; + static System.Half System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Half System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.Half Asin(System.Half x) => throw null; + public static System.Half AsinPi(System.Half x) => throw null; + public static System.Half Asinh(System.Half x) => throw null; + public static System.Half Atan(System.Half x) => throw null; + public static System.Half Atan2(System.Half y, System.Half x) => throw null; + public static System.Half Atan2Pi(System.Half y, System.Half x) => throw null; + public static System.Half AtanPi(System.Half x) => throw null; + public static System.Half Atanh(System.Half x) => throw null; + public static System.Half BitDecrement(System.Half x) => throw null; + public static System.Half BitIncrement(System.Half x) => throw null; + public static System.Half Cbrt(System.Half x) => throw null; + public static System.Half Ceiling(System.Half x) => throw null; + public static System.Half Clamp(System.Half value, System.Half min, System.Half max) => throw null; public int CompareTo(System.Half other) => throw null; public int CompareTo(object obj) => throw null; - public static System.Half Epsilon { get => throw null; } + public static System.Half CopySign(System.Half value, System.Half sign) => throw null; + public static System.Half Cos(System.Half x) => throw null; + public static System.Half CosPi(System.Half x) => throw null; + public static System.Half Cosh(System.Half x) => throw null; + static System.Half System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Half System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Half System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + static System.Half System.Numerics.IFloatingPointConstants.E { get => throw null; } + static System.Half System.Numerics.IFloatingPointIeee754.Epsilon { get => throw null; } public bool Equals(System.Half other) => throw null; public override bool Equals(object obj) => throw null; + public static System.Half Exp(System.Half x) => throw null; + public static System.Half Exp10(System.Half x) => throw null; + public static System.Half Exp10M1(System.Half x) => throw null; + public static System.Half Exp2(System.Half x) => throw null; + public static System.Half Exp2M1(System.Half x) => throw null; + public static System.Half ExpM1(System.Half x) => throw null; + public static System.Half Floor(System.Half x) => throw null; + public static System.Half FusedMultiplyAdd(System.Half left, System.Half right, System.Half addend) => throw null; + int System.Numerics.IFloatingPoint.GetExponentByteCount() => throw null; + int System.Numerics.IFloatingPoint.GetExponentShortestBitLength() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandBitLength() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandByteCount() => throw null; // Stub generator skipped constructor + public static System.Half Hypot(System.Half x, System.Half y) => throw null; + public static int ILogB(System.Half x) => throw null; + public static System.Half Ieee754Remainder(System.Half left, System.Half right) => throw null; + public static bool IsCanonical(System.Half value) => throw null; + public static bool IsComplexNumber(System.Half value) => throw null; + public static bool IsEvenInteger(System.Half value) => throw null; public static bool IsFinite(System.Half value) => throw null; + public static bool IsImaginaryNumber(System.Half value) => throw null; public static bool IsInfinity(System.Half value) => throw null; + public static bool IsInteger(System.Half value) => throw null; public static bool IsNaN(System.Half value) => throw null; public static bool IsNegative(System.Half value) => throw null; public static bool IsNegativeInfinity(System.Half value) => throw null; public static bool IsNormal(System.Half value) => throw null; + public static bool IsOddInteger(System.Half value) => throw null; + public static bool IsPositive(System.Half value) => throw null; public static bool IsPositiveInfinity(System.Half value) => throw null; + public static bool IsPow2(System.Half value) => throw null; + public static bool IsRealNumber(System.Half value) => throw null; public static bool IsSubnormal(System.Half value) => throw null; - public static System.Half MaxValue { get => throw null; } - public static System.Half MinValue { get => throw null; } - public static System.Half NaN { get => throw null; } - public static System.Half NegativeInfinity { get => throw null; } + public static bool IsZero(System.Half value) => throw null; + public static System.Half Log(System.Half x) => throw null; + public static System.Half Log(System.Half x, System.Half newBase) => throw null; + public static System.Half Log10(System.Half x) => throw null; + public static System.Half Log10P1(System.Half x) => throw null; + public static System.Half Log2(System.Half value) => throw null; + public static System.Half Log2P1(System.Half x) => throw null; + public static System.Half LogP1(System.Half x) => throw null; + public static System.Half Max(System.Half x, System.Half y) => throw null; + public static System.Half MaxMagnitude(System.Half x, System.Half y) => throw null; + public static System.Half MaxMagnitudeNumber(System.Half x, System.Half y) => throw null; + public static System.Half MaxNumber(System.Half x, System.Half y) => throw null; + static System.Half System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Half Min(System.Half x, System.Half y) => throw null; + public static System.Half MinMagnitude(System.Half x, System.Half y) => throw null; + public static System.Half MinMagnitudeNumber(System.Half x, System.Half y) => throw null; + public static System.Half MinNumber(System.Half x, System.Half y) => throw null; + static System.Half System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Half System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Half System.Numerics.IFloatingPointIeee754.NaN { get => throw null; } + static System.Half System.Numerics.IFloatingPointIeee754.NegativeInfinity { get => throw null; } + static System.Half System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Half System.Numerics.IFloatingPointIeee754.NegativeZero { get => throw null; } + static System.Half System.Numerics.INumberBase.One { get => throw null; } + public static System.Half Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Half Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Half Parse(string s) => throw null; public static System.Half Parse(string s, System.IFormatProvider provider) => throw null; public static System.Half Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.Half Parse(string s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; - public static System.Half PositiveInfinity { get => throw null; } + static System.Half System.Numerics.IFloatingPointConstants.Pi { get => throw null; } + static System.Half System.Numerics.IFloatingPointIeee754.PositiveInfinity { get => throw null; } + public static System.Half Pow(System.Half x, System.Half y) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Half ReciprocalEstimate(System.Half x) => throw null; + public static System.Half ReciprocalSqrtEstimate(System.Half x) => throw null; + public static System.Half RootN(System.Half x, int n) => throw null; + public static System.Half Round(System.Half x) => throw null; + public static System.Half Round(System.Half x, System.MidpointRounding mode) => throw null; + public static System.Half Round(System.Half x, int digits) => throw null; + public static System.Half Round(System.Half x, int digits, System.MidpointRounding mode) => throw null; + public static System.Half ScaleB(System.Half x, int n) => throw null; + public static int Sign(System.Half value) => throw null; + public static System.Half Sin(System.Half x) => throw null; + public static (System.Half, System.Half) SinCos(System.Half x) => throw null; + public static (System.Half, System.Half) SinCosPi(System.Half x) => throw null; + public static System.Half SinPi(System.Half x) => throw null; + public static System.Half Sinh(System.Half x) => throw null; + public static System.Half Sqrt(System.Half x) => throw null; + public static System.Half Tan(System.Half x) => throw null; + public static System.Half TanPi(System.Half x) => throw null; + public static System.Half Tanh(System.Half x) => throw null; + static System.Half System.Numerics.IFloatingPointConstants.Tau { get => throw null; } public override string ToString() => throw null; public string ToString(System.IFormatProvider provider) => throw null; public string ToString(string format) => throw null; public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.Half Truncate(System.Half x) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Half result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Half result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Half result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Half value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Half value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Half value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Half result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Half result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.Half result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Half result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Half result) => throw null; public static bool TryParse(string s, out System.Half result) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Half System.Numerics.INumberBase.Zero { get => throw null; } + static System.Half System.Numerics.IBitwiseOperators.operator ^(System.Half left, System.Half right) => throw null; + public static explicit operator checked System.Byte(System.Half value) => throw null; + public static explicit operator checked System.Char(System.Half value) => throw null; + public static explicit operator checked System.Int128(System.Half value) => throw null; + public static explicit operator checked System.Int16(System.Half value) => throw null; + public static explicit operator checked System.Int64(System.Half value) => throw null; + public static explicit operator checked System.IntPtr(System.Half value) => throw null; + public static explicit operator checked System.SByte(System.Half value) => throw null; + public static explicit operator checked System.UInt128(System.Half value) => throw null; + public static explicit operator checked System.UInt16(System.Half value) => throw null; + public static explicit operator checked System.UInt32(System.Half value) => throw null; + public static explicit operator checked System.UInt64(System.Half value) => throw null; + public static explicit operator checked System.UIntPtr(System.Half value) => throw null; + public static explicit operator checked int(System.Half value) => throw null; + public static explicit operator System.Byte(System.Half value) => throw null; + public static explicit operator System.Char(System.Half value) => throw null; + public static explicit operator System.Decimal(System.Half value) => throw null; + public static explicit operator System.Int128(System.Half value) => throw null; + public static explicit operator System.Int16(System.Half value) => throw null; + public static explicit operator System.Int64(System.Half value) => throw null; + public static explicit operator System.IntPtr(System.Half value) => throw null; + public static explicit operator System.SByte(System.Half value) => throw null; + public static explicit operator System.UInt128(System.Half value) => throw null; + public static explicit operator System.UInt16(System.Half value) => throw null; + public static explicit operator System.UInt32(System.Half value) => throw null; + public static explicit operator System.UInt64(System.Half value) => throw null; + public static explicit operator System.UIntPtr(System.Half value) => throw null; public static explicit operator double(System.Half value) => throw null; public static explicit operator float(System.Half value) => throw null; + public static explicit operator int(System.Half value) => throw null; + public static explicit operator System.Half(System.IntPtr value) => throw null; + public static explicit operator System.Half(System.UIntPtr value) => throw null; + public static explicit operator System.Half(System.Char value) => throw null; + public static explicit operator System.Half(System.Decimal value) => throw null; public static explicit operator System.Half(double value) => throw null; public static explicit operator System.Half(float value) => throw null; + public static explicit operator System.Half(int value) => throw null; + public static explicit operator System.Half(System.Int64 value) => throw null; + public static explicit operator System.Half(System.Int16 value) => throw null; + public static explicit operator System.Half(System.UInt32 value) => throw null; + public static explicit operator System.Half(System.UInt64 value) => throw null; + public static explicit operator System.Half(System.UInt16 value) => throw null; + public static implicit operator System.Half(System.Byte value) => throw null; + public static implicit operator System.Half(System.SByte value) => throw null; + static System.Half System.Numerics.IBitwiseOperators.operator |(System.Half left, System.Half right) => throw null; + static System.Half System.Numerics.IBitwiseOperators.operator ~(System.Half value) => throw null; } - // Generated from `System.HashCode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct HashCode { public void Add(T value) => throw null; @@ -2377,19 +2835,16 @@ namespace System public int ToHashCode() => throw null; } - // Generated from `System.HttpStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HttpStyleUriParser : System.UriParser { public HttpStyleUriParser() => throw null; } - // Generated from `System.IAsyncDisposable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAsyncDisposable { System.Threading.Tasks.ValueTask DisposeAsync(); } - // Generated from `System.IAsyncResult` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAsyncResult { object AsyncState { get; } @@ -2398,25 +2853,21 @@ namespace System bool IsCompleted { get; } } - // Generated from `System.ICloneable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICloneable { object Clone(); } - // Generated from `System.IComparable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComparable { int CompareTo(object obj); } - // Generated from `System.IComparable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComparable { int CompareTo(T other); } - // Generated from `System.IConvertible` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IConvertible { System.TypeCode GetTypeCode(); @@ -2438,43 +2889,36 @@ namespace System System.UInt64 ToUInt64(System.IFormatProvider provider); } - // Generated from `System.ICustomFormatter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomFormatter { string Format(string format, object arg, System.IFormatProvider formatProvider); } - // Generated from `System.IDisposable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDisposable { void Dispose(); } - // Generated from `System.IEquatable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEquatable { bool Equals(T other); } - // Generated from `System.IFormatProvider` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFormatProvider { object GetFormat(System.Type formatType); } - // Generated from `System.IFormattable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFormattable { string ToString(string format, System.IFormatProvider formatProvider); } - // Generated from `System.IObservable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IObservable { System.IDisposable Subscribe(System.IObserver observer); } - // Generated from `System.IObserver<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IObserver { void OnCompleted(); @@ -2482,19 +2926,28 @@ namespace System void OnNext(T value); } - // Generated from `System.IProgress<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public interface IParsable where TSelf : System.IParsable + { + static abstract TSelf Parse(string s, System.IFormatProvider provider); + static abstract bool TryParse(string s, System.IFormatProvider provider, out TSelf result); + } + public interface IProgress { void Report(T value); } - // Generated from `System.ISpanFormattable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISpanFormattable : System.IFormattable { bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format, System.IFormatProvider provider); } - // Generated from `System.Index` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public interface ISpanParsable : System.IParsable where TSelf : System.ISpanParsable + { + static abstract TSelf Parse(System.ReadOnlySpan s, System.IFormatProvider provider); + static abstract bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out TSelf result); + } + public struct Index : System.IEquatable { public static System.Index End { get => throw null; } @@ -2513,7 +2966,6 @@ namespace System public static implicit operator System.Index(int value) => throw null; } - // Generated from `System.IndexOutOfRangeException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IndexOutOfRangeException : System.SystemException { public IndexOutOfRangeException() => throw null; @@ -2521,7 +2973,6 @@ namespace System public IndexOutOfRangeException(string message, System.Exception innerException) => throw null; } - // Generated from `System.InsufficientExecutionStackException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InsufficientExecutionStackException : System.SystemException { public InsufficientExecutionStackException() => throw null; @@ -2529,7 +2980,6 @@ namespace System public InsufficientExecutionStackException(string message, System.Exception innerException) => throw null; } - // Generated from `System.InsufficientMemoryException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InsufficientMemoryException : System.OutOfMemoryException { public InsufficientMemoryException() => throw null; @@ -2537,23 +2987,253 @@ namespace System public InsufficientMemoryException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Int16` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Int16 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Int128 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { + static bool System.Numerics.IEqualityOperators.operator !=(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IModulusOperators.operator %(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IBitwiseOperators.operator &(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IMultiplyOperators.operator *(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IUnaryPlusOperators.operator +(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IAdditionOperators.operator +(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IIncrementOperators.operator ++(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IUnaryNegationOperators.operator -(System.Int128 value) => throw null; + static System.Int128 System.Numerics.ISubtractionOperators.operator -(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IDecrementOperators.operator --(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IDivisionOperators.operator /(System.Int128 left, System.Int128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IShiftOperators.operator <<(System.Int128 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Int128 left, System.Int128 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Int128 left, System.Int128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Int128 left, System.Int128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IShiftOperators.operator >>(System.Int128 value, int shiftAmount) => throw null; + static System.Int128 System.Numerics.IShiftOperators.operator >>>(System.Int128 value, int shiftAmount) => throw null; + public static System.Int128 Abs(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Int128 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.Int128 Clamp(System.Int128 value, System.Int128 min, System.Int128 max) => throw null; + public int CompareTo(System.Int128 value) => throw null; + public int CompareTo(object value) => throw null; + public static System.Int128 CopySign(System.Int128 value, System.Int128 sign) => throw null; + static System.Int128 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Int128 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Int128 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.Int128, System.Int128) DivRem(System.Int128 left, System.Int128 right) => throw null; + public bool Equals(System.Int128 other) => throw null; + public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; + public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; + // Stub generator skipped constructor + public Int128(System.UInt64 upper, System.UInt64 lower) => throw null; + public static bool IsCanonical(System.Int128 value) => throw null; + public static bool IsComplexNumber(System.Int128 value) => throw null; + public static bool IsEvenInteger(System.Int128 value) => throw null; + public static bool IsFinite(System.Int128 value) => throw null; + public static bool IsImaginaryNumber(System.Int128 value) => throw null; + public static bool IsInfinity(System.Int128 value) => throw null; + public static bool IsInteger(System.Int128 value) => throw null; + public static bool IsNaN(System.Int128 value) => throw null; + public static bool IsNegative(System.Int128 value) => throw null; + public static bool IsNegativeInfinity(System.Int128 value) => throw null; + public static bool IsNormal(System.Int128 value) => throw null; + public static bool IsOddInteger(System.Int128 value) => throw null; + public static bool IsPositive(System.Int128 value) => throw null; + public static bool IsPositiveInfinity(System.Int128 value) => throw null; + public static bool IsPow2(System.Int128 value) => throw null; + public static bool IsRealNumber(System.Int128 value) => throw null; + public static bool IsSubnormal(System.Int128 value) => throw null; + public static bool IsZero(System.Int128 value) => throw null; + public static System.Int128 LeadingZeroCount(System.Int128 value) => throw null; + public static System.Int128 Log2(System.Int128 value) => throw null; + public static System.Int128 Max(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MaxMagnitude(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MaxMagnitudeNumber(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MaxNumber(System.Int128 x, System.Int128 y) => throw null; + static System.Int128 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Int128 Min(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MinMagnitude(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MinMagnitudeNumber(System.Int128 x, System.Int128 y) => throw null; + public static System.Int128 MinNumber(System.Int128 x, System.Int128 y) => throw null; + static System.Int128 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Int128 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Int128 System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Int128 System.Numerics.INumberBase.One { get => throw null; } + public static System.Int128 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; + public static System.Int128 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static System.Int128 Parse(string s) => throw null; + public static System.Int128 Parse(string s, System.IFormatProvider provider) => throw null; + public static System.Int128 Parse(string s, System.Globalization.NumberStyles style) => throw null; + public static System.Int128 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Int128 PopCount(System.Int128 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Int128 RotateLeft(System.Int128 value, int rotateAmount) => throw null; + public static System.Int128 RotateRight(System.Int128 value, int rotateAmount) => throw null; + public static int Sign(System.Int128 value) => throw null; + public override string ToString() => throw null; + public string ToString(System.IFormatProvider provider) => throw null; + public string ToString(string format) => throw null; + public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.Int128 TrailingZeroCount(System.Int128 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Int128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Int128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Int128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Int128 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Int128 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Int128 value, out TOther result) => throw null; + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Int128 result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int128 result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, out System.Int128 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Int128 result) => throw null; + public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int128 result) => throw null; + public static bool TryParse(string s, out System.Int128 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int128 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int128 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Int128 System.Numerics.INumberBase.Zero { get => throw null; } + static System.Int128 System.Numerics.IBitwiseOperators.operator ^(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IMultiplyOperators.operator checked *(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IAdditionOperators.operator checked +(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IIncrementOperators.operator checked ++(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IUnaryNegationOperators.operator checked -(System.Int128 value) => throw null; + static System.Int128 System.Numerics.ISubtractionOperators.operator checked -(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IDecrementOperators.operator checked --(System.Int128 value) => throw null; + static System.Int128 System.Numerics.IDivisionOperators.operator checked /(System.Int128 left, System.Int128 right) => throw null; + public static explicit operator checked System.Byte(System.Int128 value) => throw null; + public static explicit operator checked System.Char(System.Int128 value) => throw null; + public static explicit operator checked System.Int16(System.Int128 value) => throw null; + public static explicit operator checked System.Int64(System.Int128 value) => throw null; + public static explicit operator checked System.IntPtr(System.Int128 value) => throw null; + public static explicit operator checked System.SByte(System.Int128 value) => throw null; + public static explicit operator checked System.UInt128(System.Int128 value) => throw null; + public static explicit operator checked System.UInt16(System.Int128 value) => throw null; + public static explicit operator checked System.UInt32(System.Int128 value) => throw null; + public static explicit operator checked System.UInt64(System.Int128 value) => throw null; + public static explicit operator checked System.UIntPtr(System.Int128 value) => throw null; + public static explicit operator checked int(System.Int128 value) => throw null; + public static explicit operator checked System.Int128(double value) => throw null; + public static explicit operator checked System.Int128(float value) => throw null; + public static explicit operator System.Byte(System.Int128 value) => throw null; + public static explicit operator System.Char(System.Int128 value) => throw null; + public static explicit operator System.Decimal(System.Int128 value) => throw null; + public static explicit operator System.Half(System.Int128 value) => throw null; + public static explicit operator System.Int16(System.Int128 value) => throw null; + public static explicit operator System.Int64(System.Int128 value) => throw null; + public static explicit operator System.IntPtr(System.Int128 value) => throw null; + public static explicit operator System.SByte(System.Int128 value) => throw null; + public static explicit operator System.UInt128(System.Int128 value) => throw null; + public static explicit operator System.UInt16(System.Int128 value) => throw null; + public static explicit operator System.UInt32(System.Int128 value) => throw null; + public static explicit operator System.UInt64(System.Int128 value) => throw null; + public static explicit operator System.UIntPtr(System.Int128 value) => throw null; + public static explicit operator double(System.Int128 value) => throw null; + public static explicit operator float(System.Int128 value) => throw null; + public static explicit operator int(System.Int128 value) => throw null; + public static explicit operator System.Int128(System.Decimal value) => throw null; + public static explicit operator System.Int128(double value) => throw null; + public static explicit operator System.Int128(float value) => throw null; + public static implicit operator System.Int128(System.IntPtr value) => throw null; + public static implicit operator System.Int128(System.UIntPtr value) => throw null; + public static implicit operator System.Int128(System.Byte value) => throw null; + public static implicit operator System.Int128(System.Char value) => throw null; + public static implicit operator System.Int128(int value) => throw null; + public static implicit operator System.Int128(System.Int64 value) => throw null; + public static implicit operator System.Int128(System.SByte value) => throw null; + public static implicit operator System.Int128(System.Int16 value) => throw null; + public static implicit operator System.Int128(System.UInt32 value) => throw null; + public static implicit operator System.Int128(System.UInt64 value) => throw null; + public static implicit operator System.Int128(System.UInt16 value) => throw null; + static System.Int128 System.Numerics.IBitwiseOperators.operator |(System.Int128 left, System.Int128 right) => throw null; + static System.Int128 System.Numerics.IBitwiseOperators.operator ~(System.Int128 value) => throw null; + } + + public struct Int16 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators + { + static bool System.Numerics.IEqualityOperators.operator !=(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IModulusOperators.operator %(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IBitwiseOperators.operator &(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IMultiplyOperators.operator *(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IUnaryPlusOperators.operator +(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IAdditionOperators.operator +(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IIncrementOperators.operator ++(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IUnaryNegationOperators.operator -(System.Int16 value) => throw null; + static System.Int16 System.Numerics.ISubtractionOperators.operator -(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IDecrementOperators.operator --(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IDivisionOperators.operator /(System.Int16 left, System.Int16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IShiftOperators.operator <<(System.Int16 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Int16 left, System.Int16 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Int16 left, System.Int16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Int16 left, System.Int16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IShiftOperators.operator >>(System.Int16 value, int shiftAmount) => throw null; + static System.Int16 System.Numerics.IShiftOperators.operator >>>(System.Int16 value, int shiftAmount) => throw null; + public static System.Int16 Abs(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Int16 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.Int16 Clamp(System.Int16 value, System.Int16 min, System.Int16 max) => throw null; public int CompareTo(object value) => throw null; public int CompareTo(System.Int16 value) => throw null; + public static System.Int16 CopySign(System.Int16 value, System.Int16 sign) => throw null; + static System.Int16 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Int16 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Int16 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.Int16, System.Int16) DivRem(System.Int16 left, System.Int16 right) => throw null; public override bool Equals(object obj) => throw null; public bool Equals(System.Int16 obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; // Stub generator skipped constructor + public static bool IsCanonical(System.Int16 value) => throw null; + public static bool IsComplexNumber(System.Int16 value) => throw null; + public static bool IsEvenInteger(System.Int16 value) => throw null; + public static bool IsFinite(System.Int16 value) => throw null; + public static bool IsImaginaryNumber(System.Int16 value) => throw null; + public static bool IsInfinity(System.Int16 value) => throw null; + public static bool IsInteger(System.Int16 value) => throw null; + public static bool IsNaN(System.Int16 value) => throw null; + public static bool IsNegative(System.Int16 value) => throw null; + public static bool IsNegativeInfinity(System.Int16 value) => throw null; + public static bool IsNormal(System.Int16 value) => throw null; + public static bool IsOddInteger(System.Int16 value) => throw null; + public static bool IsPositive(System.Int16 value) => throw null; + public static bool IsPositiveInfinity(System.Int16 value) => throw null; + public static bool IsPow2(System.Int16 value) => throw null; + public static bool IsRealNumber(System.Int16 value) => throw null; + public static bool IsSubnormal(System.Int16 value) => throw null; + public static bool IsZero(System.Int16 value) => throw null; + public static System.Int16 LeadingZeroCount(System.Int16 value) => throw null; + public static System.Int16 Log2(System.Int16 value) => throw null; + public static System.Int16 Max(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MaxMagnitude(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MaxMagnitudeNumber(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MaxNumber(System.Int16 x, System.Int16 y) => throw null; public const System.Int16 MaxValue = default; + static System.Int16 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Int16 Min(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MinMagnitude(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MinMagnitudeNumber(System.Int16 x, System.Int16 y) => throw null; + public static System.Int16 MinNumber(System.Int16 x, System.Int16 y) => throw null; public const System.Int16 MinValue = default; + static System.Int16 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Int16 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Int16 System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Int16 System.Numerics.INumberBase.One { get => throw null; } + public static System.Int16 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Int16 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Int16 Parse(string s) => throw null; public static System.Int16 Parse(string s, System.IFormatProvider provider) => throw null; public static System.Int16 Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.Int16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Int16 PopCount(System.Int16 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Int16 RotateLeft(System.Int16 value, int rotateAmount) => throw null; + public static System.Int16 RotateRight(System.Int16 value, int rotateAmount) => throw null; + public static int Sign(System.Int16 value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -2573,30 +3253,121 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.Int16 TrailingZeroCount(System.Int16 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Int16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Int16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Int16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Int16 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Int16 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Int16 value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Int16 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int16 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.Int16 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Int16 result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int16 result) => throw null; public static bool TryParse(string s, out System.Int16 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int16 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int16 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Int16 System.Numerics.INumberBase.Zero { get => throw null; } + static System.Int16 System.Numerics.IBitwiseOperators.operator ^(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IMultiplyOperators.operator checked *(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IAdditionOperators.operator checked +(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IIncrementOperators.operator checked ++(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IUnaryNegationOperators.operator checked -(System.Int16 value) => throw null; + static System.Int16 System.Numerics.ISubtractionOperators.operator checked -(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IDecrementOperators.operator checked --(System.Int16 value) => throw null; + static System.Int16 System.Numerics.IBitwiseOperators.operator |(System.Int16 left, System.Int16 right) => throw null; + static System.Int16 System.Numerics.IBitwiseOperators.operator ~(System.Int16 value) => throw null; } - // Generated from `System.Int32` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Int32 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Int32 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { + static bool System.Numerics.IEqualityOperators.operator !=(int left, int right) => throw null; + static int System.Numerics.IModulusOperators.operator %(int left, int right) => throw null; + static int System.Numerics.IBitwiseOperators.operator &(int left, int right) => throw null; + static int System.Numerics.IMultiplyOperators.operator *(int left, int right) => throw null; + static int System.Numerics.IUnaryPlusOperators.operator +(int value) => throw null; + static int System.Numerics.IAdditionOperators.operator +(int left, int right) => throw null; + static int System.Numerics.IIncrementOperators.operator ++(int value) => throw null; + static int System.Numerics.IUnaryNegationOperators.operator -(int value) => throw null; + static int System.Numerics.ISubtractionOperators.operator -(int left, int right) => throw null; + static int System.Numerics.IDecrementOperators.operator --(int value) => throw null; + static int System.Numerics.IDivisionOperators.operator /(int left, int right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(int left, int right) => throw null; + static int System.Numerics.IShiftOperators.operator <<(int value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(int left, int right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(int left, int right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(int left, int right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(int left, int right) => throw null; + static int System.Numerics.IShiftOperators.operator >>(int value, int shiftAmount) => throw null; + static int System.Numerics.IShiftOperators.operator >>>(int value, int shiftAmount) => throw null; + public static int Abs(int value) => throw null; + static int System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static int System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static int Clamp(int value, int min, int max) => throw null; public int CompareTo(int value) => throw null; public int CompareTo(object value) => throw null; + public static int CopySign(int value, int sign) => throw null; + static int System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static int System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static int System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (int, int) DivRem(int left, int right) => throw null; public bool Equals(int obj) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; // Stub generator skipped constructor + public static bool IsCanonical(int value) => throw null; + public static bool IsComplexNumber(int value) => throw null; + public static bool IsEvenInteger(int value) => throw null; + public static bool IsFinite(int value) => throw null; + public static bool IsImaginaryNumber(int value) => throw null; + public static bool IsInfinity(int value) => throw null; + public static bool IsInteger(int value) => throw null; + public static bool IsNaN(int value) => throw null; + public static bool IsNegative(int value) => throw null; + public static bool IsNegativeInfinity(int value) => throw null; + public static bool IsNormal(int value) => throw null; + public static bool IsOddInteger(int value) => throw null; + public static bool IsPositive(int value) => throw null; + public static bool IsPositiveInfinity(int value) => throw null; + public static bool IsPow2(int value) => throw null; + public static bool IsRealNumber(int value) => throw null; + public static bool IsSubnormal(int value) => throw null; + public static bool IsZero(int value) => throw null; + public static int LeadingZeroCount(int value) => throw null; + public static int Log2(int value) => throw null; + public static int Max(int x, int y) => throw null; + public static int MaxMagnitude(int x, int y) => throw null; + public static int MaxMagnitudeNumber(int x, int y) => throw null; + public static int MaxNumber(int x, int y) => throw null; public const int MaxValue = default; + static int System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static int Min(int x, int y) => throw null; + public static int MinMagnitude(int x, int y) => throw null; + public static int MinMagnitudeNumber(int x, int y) => throw null; + public static int MinNumber(int x, int y) => throw null; public const int MinValue = default; + static int System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static int System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static int System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static int System.Numerics.INumberBase.One { get => throw null; } + public static int Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static int Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static int Parse(string s) => throw null; public static int Parse(string s, System.IFormatProvider provider) => throw null; public static int Parse(string s, System.Globalization.NumberStyles style) => throw null; public static int Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static int PopCount(int value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static int RotateLeft(int value, int rotateAmount) => throw null; + public static int RotateRight(int value, int rotateAmount) => throw null; + public static int Sign(int value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -2616,30 +3387,121 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static int TrailingZeroCount(int value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out int result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out int result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out int result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(int value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(int value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(int value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out int result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out int result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out int result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out int result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out int result) => throw null; public static bool TryParse(string s, out int result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out int value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out int value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static int System.Numerics.INumberBase.Zero { get => throw null; } + static int System.Numerics.IBitwiseOperators.operator ^(int left, int right) => throw null; + static int System.Numerics.IMultiplyOperators.operator checked *(int left, int right) => throw null; + static int System.Numerics.IAdditionOperators.operator checked +(int left, int right) => throw null; + static int System.Numerics.IIncrementOperators.operator checked ++(int value) => throw null; + static int System.Numerics.IUnaryNegationOperators.operator checked -(int value) => throw null; + static int System.Numerics.ISubtractionOperators.operator checked -(int left, int right) => throw null; + static int System.Numerics.IDecrementOperators.operator checked --(int value) => throw null; + static int System.Numerics.IBitwiseOperators.operator |(int left, int right) => throw null; + static int System.Numerics.IBitwiseOperators.operator ~(int value) => throw null; } - // Generated from `System.Int64` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Int64 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Int64 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { + static bool System.Numerics.IEqualityOperators.operator !=(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IModulusOperators.operator %(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IBitwiseOperators.operator &(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IMultiplyOperators.operator *(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IUnaryPlusOperators.operator +(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IAdditionOperators.operator +(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IIncrementOperators.operator ++(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IUnaryNegationOperators.operator -(System.Int64 value) => throw null; + static System.Int64 System.Numerics.ISubtractionOperators.operator -(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IDecrementOperators.operator --(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IDivisionOperators.operator /(System.Int64 left, System.Int64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IShiftOperators.operator <<(System.Int64 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.Int64 left, System.Int64 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.Int64 left, System.Int64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.Int64 left, System.Int64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IShiftOperators.operator >>(System.Int64 value, int shiftAmount) => throw null; + static System.Int64 System.Numerics.IShiftOperators.operator >>>(System.Int64 value, int shiftAmount) => throw null; + public static System.Int64 Abs(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.Int64 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.Int64 Clamp(System.Int64 value, System.Int64 min, System.Int64 max) => throw null; public int CompareTo(System.Int64 value) => throw null; public int CompareTo(object value) => throw null; + public static System.Int64 CopySign(System.Int64 value, System.Int64 sign) => throw null; + static System.Int64 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.Int64 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.Int64 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.Int64, System.Int64) DivRem(System.Int64 left, System.Int64 right) => throw null; public bool Equals(System.Int64 obj) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; // Stub generator skipped constructor + public static bool IsCanonical(System.Int64 value) => throw null; + public static bool IsComplexNumber(System.Int64 value) => throw null; + public static bool IsEvenInteger(System.Int64 value) => throw null; + public static bool IsFinite(System.Int64 value) => throw null; + public static bool IsImaginaryNumber(System.Int64 value) => throw null; + public static bool IsInfinity(System.Int64 value) => throw null; + public static bool IsInteger(System.Int64 value) => throw null; + public static bool IsNaN(System.Int64 value) => throw null; + public static bool IsNegative(System.Int64 value) => throw null; + public static bool IsNegativeInfinity(System.Int64 value) => throw null; + public static bool IsNormal(System.Int64 value) => throw null; + public static bool IsOddInteger(System.Int64 value) => throw null; + public static bool IsPositive(System.Int64 value) => throw null; + public static bool IsPositiveInfinity(System.Int64 value) => throw null; + public static bool IsPow2(System.Int64 value) => throw null; + public static bool IsRealNumber(System.Int64 value) => throw null; + public static bool IsSubnormal(System.Int64 value) => throw null; + public static bool IsZero(System.Int64 value) => throw null; + public static System.Int64 LeadingZeroCount(System.Int64 value) => throw null; + public static System.Int64 Log2(System.Int64 value) => throw null; + public static System.Int64 Max(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MaxMagnitude(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MaxMagnitudeNumber(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MaxNumber(System.Int64 x, System.Int64 y) => throw null; public const System.Int64 MaxValue = default; + static System.Int64 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.Int64 Min(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MinMagnitude(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MinMagnitudeNumber(System.Int64 x, System.Int64 y) => throw null; + public static System.Int64 MinNumber(System.Int64 x, System.Int64 y) => throw null; public const System.Int64 MinValue = default; + static System.Int64 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.Int64 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.Int64 System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.Int64 System.Numerics.INumberBase.One { get => throw null; } + public static System.Int64 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.Int64 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.Int64 Parse(string s) => throw null; public static System.Int64 Parse(string s, System.IFormatProvider provider) => throw null; public static System.Int64 Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.Int64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.Int64 PopCount(System.Int64 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.Int64 RotateLeft(System.Int64 value, int rotateAmount) => throw null; + public static System.Int64 RotateRight(System.Int64 value, int rotateAmount) => throw null; + public static int Sign(System.Int64 value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -2659,38 +3521,127 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.Int64 TrailingZeroCount(System.Int64 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.Int64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.Int64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.Int64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.Int64 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.Int64 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.Int64 value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.Int64 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int64 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.Int64 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.Int64 result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.Int64 result) => throw null; public static bool TryParse(string s, out System.Int64 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int64 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.Int64 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.Int64 System.Numerics.INumberBase.Zero { get => throw null; } + static System.Int64 System.Numerics.IBitwiseOperators.operator ^(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IMultiplyOperators.operator checked *(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IAdditionOperators.operator checked +(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IIncrementOperators.operator checked ++(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IUnaryNegationOperators.operator checked -(System.Int64 value) => throw null; + static System.Int64 System.Numerics.ISubtractionOperators.operator checked -(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IDecrementOperators.operator checked --(System.Int64 value) => throw null; + static System.Int64 System.Numerics.IBitwiseOperators.operator |(System.Int64 left, System.Int64 right) => throw null; + static System.Int64 System.Numerics.IBitwiseOperators.operator ~(System.Int64 value) => throw null; } - // Generated from `System.IntPtr` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct IntPtr : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable, System.Runtime.Serialization.ISerializable + public struct IntPtr : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Runtime.Serialization.ISerializable { - public static bool operator !=(System.IntPtr value1, System.IntPtr value2) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.IntPtr value1, System.IntPtr value2) => throw null; + static System.IntPtr System.Numerics.IModulusOperators.operator %(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IBitwiseOperators.operator &(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IMultiplyOperators.operator *(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IUnaryPlusOperators.operator +(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.IAdditionOperators.operator +(System.IntPtr left, System.IntPtr right) => throw null; public static System.IntPtr operator +(System.IntPtr pointer, int offset) => throw null; + static System.IntPtr System.Numerics.IIncrementOperators.operator ++(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.IUnaryNegationOperators.operator -(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.ISubtractionOperators.operator -(System.IntPtr left, System.IntPtr right) => throw null; public static System.IntPtr operator -(System.IntPtr pointer, int offset) => throw null; - public static bool operator ==(System.IntPtr value1, System.IntPtr value2) => throw null; + static System.IntPtr System.Numerics.IDecrementOperators.operator --(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.IDivisionOperators.operator /(System.IntPtr left, System.IntPtr right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IShiftOperators.operator <<(System.IntPtr value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.IntPtr left, System.IntPtr right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.IntPtr value1, System.IntPtr value2) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.IntPtr left, System.IntPtr right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IShiftOperators.operator >>(System.IntPtr value, int shiftAmount) => throw null; + static System.IntPtr System.Numerics.IShiftOperators.operator >>>(System.IntPtr value, int shiftAmount) => throw null; + public static System.IntPtr Abs(System.IntPtr value) => throw null; public static System.IntPtr Add(System.IntPtr pointer, int offset) => throw null; + static System.IntPtr System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.IntPtr System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.IntPtr Clamp(System.IntPtr value, System.IntPtr min, System.IntPtr max) => throw null; public int CompareTo(System.IntPtr value) => throw null; public int CompareTo(object value) => throw null; + public static System.IntPtr CopySign(System.IntPtr value, System.IntPtr sign) => throw null; + static System.IntPtr System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.IntPtr System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.IntPtr System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.IntPtr, System.IntPtr) DivRem(System.IntPtr left, System.IntPtr right) => throw null; public bool Equals(System.IntPtr other) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; // Stub generator skipped constructor unsafe public IntPtr(void* value) => throw null; public IntPtr(int value) => throw null; public IntPtr(System.Int64 value) => throw null; + public static bool IsCanonical(System.IntPtr value) => throw null; + public static bool IsComplexNumber(System.IntPtr value) => throw null; + public static bool IsEvenInteger(System.IntPtr value) => throw null; + public static bool IsFinite(System.IntPtr value) => throw null; + public static bool IsImaginaryNumber(System.IntPtr value) => throw null; + public static bool IsInfinity(System.IntPtr value) => throw null; + public static bool IsInteger(System.IntPtr value) => throw null; + public static bool IsNaN(System.IntPtr value) => throw null; + public static bool IsNegative(System.IntPtr value) => throw null; + public static bool IsNegativeInfinity(System.IntPtr value) => throw null; + public static bool IsNormal(System.IntPtr value) => throw null; + public static bool IsOddInteger(System.IntPtr value) => throw null; + public static bool IsPositive(System.IntPtr value) => throw null; + public static bool IsPositiveInfinity(System.IntPtr value) => throw null; + public static bool IsPow2(System.IntPtr value) => throw null; + public static bool IsRealNumber(System.IntPtr value) => throw null; + public static bool IsSubnormal(System.IntPtr value) => throw null; + public static bool IsZero(System.IntPtr value) => throw null; + public static System.IntPtr LeadingZeroCount(System.IntPtr value) => throw null; + public static System.IntPtr Log2(System.IntPtr value) => throw null; + public static System.IntPtr Max(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MaxMagnitude(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MaxMagnitudeNumber(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MaxNumber(System.IntPtr x, System.IntPtr y) => throw null; public static System.IntPtr MaxValue { get => throw null; } + static System.IntPtr System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.IntPtr Min(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MinMagnitude(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MinMagnitudeNumber(System.IntPtr x, System.IntPtr y) => throw null; + public static System.IntPtr MinNumber(System.IntPtr x, System.IntPtr y) => throw null; public static System.IntPtr MinValue { get => throw null; } + static System.IntPtr System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.IntPtr System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.IntPtr System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.IntPtr System.Numerics.INumberBase.One { get => throw null; } + public static System.IntPtr Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.IntPtr Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.IntPtr Parse(string s) => throw null; public static System.IntPtr Parse(string s, System.IFormatProvider provider) => throw null; public static System.IntPtr Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.IntPtr Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.IntPtr PopCount(System.IntPtr value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.IntPtr RotateLeft(System.IntPtr value, int rotateAmount) => throw null; + public static System.IntPtr RotateRight(System.IntPtr value, int rotateAmount) => throw null; + public static int Sign(System.IntPtr value) => throw null; public static int Size { get => throw null; } public static System.IntPtr Subtract(System.IntPtr pointer, int offset) => throw null; public int ToInt32() => throw null; @@ -2700,21 +3651,43 @@ namespace System public string ToString(System.IFormatProvider provider) => throw null; public string ToString(string format) => throw null; public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.IntPtr TrailingZeroCount(System.IntPtr value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.IntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.IntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.IntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.IntPtr value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.IntPtr value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.IntPtr value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.IntPtr result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.IntPtr result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.IntPtr result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.IntPtr result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.IntPtr result) => throw null; public static bool TryParse(string s, out System.IntPtr result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.IntPtr value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.IntPtr value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; public static System.IntPtr Zero; + static System.IntPtr System.Numerics.INumberBase.Zero { get => throw null; } + static System.IntPtr System.Numerics.IBitwiseOperators.operator ^(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IMultiplyOperators.operator checked *(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IAdditionOperators.operator checked +(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IIncrementOperators.operator checked ++(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.IUnaryNegationOperators.operator checked -(System.IntPtr value) => throw null; + static System.IntPtr System.Numerics.ISubtractionOperators.operator checked -(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IDecrementOperators.operator checked --(System.IntPtr value) => throw null; public static explicit operator System.Int64(System.IntPtr value) => throw null; public static explicit operator int(System.IntPtr value) => throw null; unsafe public static explicit operator void*(System.IntPtr value) => throw null; unsafe public static explicit operator System.IntPtr(void* value) => throw null; public static explicit operator System.IntPtr(int value) => throw null; public static explicit operator System.IntPtr(System.Int64 value) => throw null; + static System.IntPtr System.Numerics.IBitwiseOperators.operator |(System.IntPtr left, System.IntPtr right) => throw null; + static System.IntPtr System.Numerics.IBitwiseOperators.operator ~(System.IntPtr value) => throw null; } - // Generated from `System.InvalidCastException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidCastException : System.SystemException { public InvalidCastException() => throw null; @@ -2724,7 +3697,6 @@ namespace System public InvalidCastException(string message, int errorCode) => throw null; } - // Generated from `System.InvalidOperationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidOperationException : System.SystemException { public InvalidOperationException() => throw null; @@ -2733,7 +3705,6 @@ namespace System public InvalidOperationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.InvalidProgramException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidProgramException : System.SystemException { public InvalidProgramException() => throw null; @@ -2741,7 +3712,6 @@ namespace System public InvalidProgramException(string message, System.Exception inner) => throw null; } - // Generated from `System.InvalidTimeZoneException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidTimeZoneException : System.Exception { public InvalidTimeZoneException() => throw null; @@ -2750,7 +3720,6 @@ namespace System public InvalidTimeZoneException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Lazy<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Lazy : System.Lazy { public Lazy(System.Func valueFactory, TMetadata metadata) => throw null; @@ -2762,7 +3731,6 @@ namespace System public TMetadata Metadata { get => throw null; } } - // Generated from `System.Lazy<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Lazy { public bool IsValueCreated { get => throw null; } @@ -2777,13 +3745,11 @@ namespace System public T Value { get => throw null; } } - // Generated from `System.LdapStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LdapStyleUriParser : System.UriParser { public LdapStyleUriParser() => throw null; } - // Generated from `System.LoaderOptimization` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LoaderOptimization : int { DisallowBindings = 4, @@ -2794,7 +3760,6 @@ namespace System SingleDomain = 1, } - // Generated from `System.LoaderOptimizationAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LoaderOptimizationAttribute : System.Attribute { public LoaderOptimizationAttribute(System.LoaderOptimization value) => throw null; @@ -2802,13 +3767,11 @@ namespace System public System.LoaderOptimization Value { get => throw null; } } - // Generated from `System.MTAThreadAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MTAThreadAttribute : System.Attribute { public MTAThreadAttribute() => throw null; } - // Generated from `System.MarshalByRefObject` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MarshalByRefObject { public object GetLifetimeService() => throw null; @@ -2817,7 +3780,6 @@ namespace System protected System.MarshalByRefObject MemberwiseClone(bool cloneIdentity) => throw null; } - // Generated from `System.Math` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Math { public static System.IntPtr Abs(System.IntPtr value) => throw null; @@ -2942,7 +3904,6 @@ namespace System public static double Truncate(double d) => throw null; } - // Generated from `System.MathF` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class MathF { public static float Abs(float x) => throw null; @@ -2994,7 +3955,6 @@ namespace System public static float Truncate(float x) => throw null; } - // Generated from `System.MemberAccessException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemberAccessException : System.SystemException { public MemberAccessException() => throw null; @@ -3003,7 +3963,6 @@ namespace System public MemberAccessException(string message, System.Exception inner) => throw null; } - // Generated from `System.Memory<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Memory : System.IEquatable> { public void CopyTo(System.Memory destination) => throw null; @@ -3028,7 +3987,6 @@ namespace System public static implicit operator System.Memory(T[] array) => throw null; } - // Generated from `System.MethodAccessException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodAccessException : System.MemberAccessException { public MethodAccessException() => throw null; @@ -3037,7 +3995,6 @@ namespace System public MethodAccessException(string message, System.Exception inner) => throw null; } - // Generated from `System.MidpointRounding` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MidpointRounding : int { AwayFromZero = 1, @@ -3047,7 +4004,6 @@ namespace System ToZero = 2, } - // Generated from `System.MissingFieldException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingFieldException : System.MissingMemberException, System.Runtime.Serialization.ISerializable { public override string Message { get => throw null; } @@ -3058,7 +4014,6 @@ namespace System public MissingFieldException(string className, string fieldName) => throw null; } - // Generated from `System.MissingMemberException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingMemberException : System.MemberAccessException, System.Runtime.Serialization.ISerializable { protected string ClassName; @@ -3073,7 +4028,6 @@ namespace System protected System.Byte[] Signature; } - // Generated from `System.MissingMethodException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingMethodException : System.MissingMemberException { public override string Message { get => throw null; } @@ -3084,8 +4038,7 @@ namespace System public MissingMethodException(string className, string methodName) => throw null; } - // Generated from `System.ModuleHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct ModuleHandle + public struct ModuleHandle : System.IEquatable { public static bool operator !=(System.ModuleHandle left, System.ModuleHandle right) => throw null; public static bool operator ==(System.ModuleHandle left, System.ModuleHandle right) => throw null; @@ -3106,7 +4059,6 @@ namespace System public System.RuntimeTypeHandle ResolveTypeHandle(int typeToken, System.RuntimeTypeHandle[] typeInstantiationContext, System.RuntimeTypeHandle[] methodInstantiationContext) => throw null; } - // Generated from `System.MulticastDelegate` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MulticastDelegate : System.Delegate { public static bool operator !=(System.MulticastDelegate d1, System.MulticastDelegate d2) => throw null; @@ -3122,7 +4074,6 @@ namespace System protected override System.Delegate RemoveImpl(System.Delegate value) => throw null; } - // Generated from `System.MulticastNotSupportedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MulticastNotSupportedException : System.SystemException { public MulticastNotSupportedException() => throw null; @@ -3130,31 +4081,26 @@ namespace System public MulticastNotSupportedException(string message, System.Exception inner) => throw null; } - // Generated from `System.NetPipeStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetPipeStyleUriParser : System.UriParser { public NetPipeStyleUriParser() => throw null; } - // Generated from `System.NetTcpStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NetTcpStyleUriParser : System.UriParser { public NetTcpStyleUriParser() => throw null; } - // Generated from `System.NewsStyleUriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NewsStyleUriParser : System.UriParser { public NewsStyleUriParser() => throw null; } - // Generated from `System.NonSerializedAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NonSerializedAttribute : System.Attribute { public NonSerializedAttribute() => throw null; } - // Generated from `System.NotFiniteNumberException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotFiniteNumberException : System.ArithmeticException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -3168,7 +4114,6 @@ namespace System public double OffendingNumber { get => throw null; } } - // Generated from `System.NotImplementedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotImplementedException : System.SystemException { public NotImplementedException() => throw null; @@ -3177,7 +4122,6 @@ namespace System public NotImplementedException(string message, System.Exception inner) => throw null; } - // Generated from `System.NotSupportedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotSupportedException : System.SystemException { public NotSupportedException() => throw null; @@ -3186,7 +4130,6 @@ namespace System public NotSupportedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.NullReferenceException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NullReferenceException : System.SystemException { public NullReferenceException() => throw null; @@ -3195,15 +4138,14 @@ namespace System public NullReferenceException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Nullable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Nullable { public static int Compare(T? n1, T? n2) where T : struct => throw null; public static bool Equals(T? n1, T? n2) where T : struct => throw null; public static System.Type GetUnderlyingType(System.Type nullableType) => throw null; + public static T GetValueRefOrDefaultRef(T? nullable) where T : struct => throw null; } - // Generated from `System.Nullable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Nullable where T : struct { public override bool Equals(object other) => throw null; @@ -3219,7 +4161,6 @@ namespace System public static implicit operator System.Nullable(T value) => throw null; } - // Generated from `System.Object` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Object { public virtual bool Equals(object obj) => throw null; @@ -3233,7 +4174,6 @@ namespace System // ERR: Stub generator didn't handle member: ~Object } - // Generated from `System.ObjectDisposedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectDisposedException : System.InvalidOperationException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -3243,9 +4183,10 @@ namespace System public ObjectDisposedException(string message, System.Exception innerException) => throw null; public ObjectDisposedException(string objectName, string message) => throw null; public string ObjectName { get => throw null; } + public static void ThrowIf(bool condition, System.Type type) => throw null; + public static void ThrowIf(bool condition, object instance) => throw null; } - // Generated from `System.ObsoleteAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObsoleteAttribute : System.Attribute { public string DiagnosticId { get => throw null; set => throw null; } @@ -3257,7 +4198,6 @@ namespace System public string UrlFormat { get => throw null; set => throw null; } } - // Generated from `System.OperatingSystem` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OperatingSystem : System.ICloneable, System.Runtime.Serialization.ISerializable { public object Clone() => throw null; @@ -3290,7 +4230,6 @@ namespace System public string VersionString { get => throw null; } } - // Generated from `System.OperationCanceledException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OperationCanceledException : System.SystemException { public System.Threading.CancellationToken CancellationToken { get => throw null; } @@ -3303,7 +4242,6 @@ namespace System public OperationCanceledException(string message, System.Exception innerException, System.Threading.CancellationToken token) => throw null; } - // Generated from `System.OutOfMemoryException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OutOfMemoryException : System.SystemException { public OutOfMemoryException() => throw null; @@ -3312,7 +4250,6 @@ namespace System public OutOfMemoryException(string message, System.Exception innerException) => throw null; } - // Generated from `System.OverflowException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OverflowException : System.ArithmeticException { public OverflowException() => throw null; @@ -3321,13 +4258,11 @@ namespace System public OverflowException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ParamArrayAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParamArrayAttribute : System.Attribute { public ParamArrayAttribute() => throw null; } - // Generated from `System.PlatformID` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PlatformID : int { MacOSX = 6, @@ -3340,7 +4275,6 @@ namespace System Xbox = 5, } - // Generated from `System.PlatformNotSupportedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PlatformNotSupportedException : System.NotSupportedException { public PlatformNotSupportedException() => throw null; @@ -3349,10 +4283,8 @@ namespace System public PlatformNotSupportedException(string message, System.Exception inner) => throw null; } - // Generated from `System.Predicate<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate bool Predicate(T obj); - // Generated from `System.Progress<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Progress : System.IProgress { protected virtual void OnReport(T value) => throw null; @@ -3362,7 +4294,6 @@ namespace System void System.IProgress.Report(T value) => throw null; } - // Generated from `System.Random` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Random { public virtual int Next() => throw null; @@ -3381,7 +4312,6 @@ namespace System public static System.Random Shared { get => throw null; } } - // Generated from `System.Range` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Range : System.IEquatable { public static System.Range All { get => throw null; } @@ -3398,7 +4328,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.RankException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RankException : System.SystemException { public RankException() => throw null; @@ -3407,7 +4336,6 @@ namespace System public RankException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ReadOnlyMemory<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ReadOnlyMemory : System.IEquatable> { public void CopyTo(System.Memory destination) => throw null; @@ -3431,10 +4359,8 @@ namespace System public static implicit operator System.ReadOnlyMemory(T[] array) => throw null; } - // Generated from `System.ReadOnlySpan<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ReadOnlySpan { - // Generated from `System.ReadOnlySpan<>+Enumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -3455,6 +4381,7 @@ namespace System public T this[int index] { get => throw null; } public int Length { get => throw null; } // Stub generator skipped constructor + public ReadOnlySpan(T reference) => throw null; public ReadOnlySpan(T[] array) => throw null; public ReadOnlySpan(T[] array, int start, int length) => throw null; unsafe public ReadOnlySpan(void* pointer, int length) => throw null; @@ -3467,7 +4394,6 @@ namespace System public static implicit operator System.ReadOnlySpan(T[] array) => throw null; } - // Generated from `System.ResolveEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResolveEventArgs : System.EventArgs { public string Name { get => throw null; } @@ -3476,44 +4402,43 @@ namespace System public ResolveEventArgs(string name, System.Reflection.Assembly requestingAssembly) => throw null; } - // Generated from `System.ResolveEventHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Reflection.Assembly ResolveEventHandler(object sender, System.ResolveEventArgs args); - // Generated from `System.RuntimeArgumentHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct RuntimeArgumentHandle { // Stub generator skipped constructor } - // Generated from `System.RuntimeFieldHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct RuntimeFieldHandle : System.Runtime.Serialization.ISerializable + public struct RuntimeFieldHandle : System.IEquatable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.RuntimeFieldHandle left, System.RuntimeFieldHandle right) => throw null; public static bool operator ==(System.RuntimeFieldHandle left, System.RuntimeFieldHandle right) => throw null; public bool Equals(System.RuntimeFieldHandle handle) => throw null; public override bool Equals(object obj) => throw null; + public static System.RuntimeFieldHandle FromIntPtr(System.IntPtr value) => throw null; public override int GetHashCode() => throw null; public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; // Stub generator skipped constructor + public static System.IntPtr ToIntPtr(System.RuntimeFieldHandle value) => throw null; public System.IntPtr Value { get => throw null; } } - // Generated from `System.RuntimeMethodHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct RuntimeMethodHandle : System.Runtime.Serialization.ISerializable + public struct RuntimeMethodHandle : System.IEquatable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.RuntimeMethodHandle left, System.RuntimeMethodHandle right) => throw null; public static bool operator ==(System.RuntimeMethodHandle left, System.RuntimeMethodHandle right) => throw null; public bool Equals(System.RuntimeMethodHandle handle) => throw null; public override bool Equals(object obj) => throw null; + public static System.RuntimeMethodHandle FromIntPtr(System.IntPtr value) => throw null; public System.IntPtr GetFunctionPointer() => throw null; public override int GetHashCode() => throw null; public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; // Stub generator skipped constructor + public static System.IntPtr ToIntPtr(System.RuntimeMethodHandle value) => throw null; public System.IntPtr Value { get => throw null; } } - // Generated from `System.RuntimeTypeHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct RuntimeTypeHandle : System.Runtime.Serialization.ISerializable + public struct RuntimeTypeHandle : System.IEquatable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.RuntimeTypeHandle left, object right) => throw null; public static bool operator !=(object left, System.RuntimeTypeHandle right) => throw null; @@ -3521,30 +4446,100 @@ namespace System public static bool operator ==(object left, System.RuntimeTypeHandle right) => throw null; public bool Equals(System.RuntimeTypeHandle handle) => throw null; public override bool Equals(object obj) => throw null; + public static System.RuntimeTypeHandle FromIntPtr(System.IntPtr value) => throw null; public override int GetHashCode() => throw null; public System.ModuleHandle GetModuleHandle() => throw null; public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; // Stub generator skipped constructor + public static System.IntPtr ToIntPtr(System.RuntimeTypeHandle value) => throw null; public System.IntPtr Value { get => throw null; } } - // Generated from `System.SByte` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct SByte : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct SByte : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { + static bool System.Numerics.IEqualityOperators.operator !=(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IModulusOperators.operator %(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IBitwiseOperators.operator &(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IMultiplyOperators.operator *(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IUnaryPlusOperators.operator +(System.SByte value) => throw null; + static System.SByte System.Numerics.IAdditionOperators.operator +(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IIncrementOperators.operator ++(System.SByte value) => throw null; + static System.SByte System.Numerics.IUnaryNegationOperators.operator -(System.SByte value) => throw null; + static System.SByte System.Numerics.ISubtractionOperators.operator -(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IDecrementOperators.operator --(System.SByte value) => throw null; + static System.SByte System.Numerics.IDivisionOperators.operator /(System.SByte left, System.SByte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IShiftOperators.operator <<(System.SByte value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.SByte left, System.SByte right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.SByte left, System.SByte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.SByte left, System.SByte right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IShiftOperators.operator >>(System.SByte value, int shiftAmount) => throw null; + static System.SByte System.Numerics.IShiftOperators.operator >>>(System.SByte value, int shiftAmount) => throw null; + public static System.SByte Abs(System.SByte value) => throw null; + static System.SByte System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.SByte System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.SByte Clamp(System.SByte value, System.SByte min, System.SByte max) => throw null; public int CompareTo(object obj) => throw null; public int CompareTo(System.SByte value) => throw null; + public static System.SByte CopySign(System.SByte value, System.SByte sign) => throw null; + static System.SByte System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.SByte System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.SByte System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.SByte, System.SByte) DivRem(System.SByte left, System.SByte right) => throw null; public override bool Equals(object obj) => throw null; public bool Equals(System.SByte obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.SByte value) => throw null; + public static bool IsComplexNumber(System.SByte value) => throw null; + public static bool IsEvenInteger(System.SByte value) => throw null; + public static bool IsFinite(System.SByte value) => throw null; + public static bool IsImaginaryNumber(System.SByte value) => throw null; + public static bool IsInfinity(System.SByte value) => throw null; + public static bool IsInteger(System.SByte value) => throw null; + public static bool IsNaN(System.SByte value) => throw null; + public static bool IsNegative(System.SByte value) => throw null; + public static bool IsNegativeInfinity(System.SByte value) => throw null; + public static bool IsNormal(System.SByte value) => throw null; + public static bool IsOddInteger(System.SByte value) => throw null; + public static bool IsPositive(System.SByte value) => throw null; + public static bool IsPositiveInfinity(System.SByte value) => throw null; + public static bool IsPow2(System.SByte value) => throw null; + public static bool IsRealNumber(System.SByte value) => throw null; + public static bool IsSubnormal(System.SByte value) => throw null; + public static bool IsZero(System.SByte value) => throw null; + public static System.SByte LeadingZeroCount(System.SByte value) => throw null; + public static System.SByte Log2(System.SByte value) => throw null; + public static System.SByte Max(System.SByte x, System.SByte y) => throw null; + public static System.SByte MaxMagnitude(System.SByte x, System.SByte y) => throw null; + public static System.SByte MaxMagnitudeNumber(System.SByte x, System.SByte y) => throw null; + public static System.SByte MaxNumber(System.SByte x, System.SByte y) => throw null; public const System.SByte MaxValue = default; + static System.SByte System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.SByte Min(System.SByte x, System.SByte y) => throw null; + public static System.SByte MinMagnitude(System.SByte x, System.SByte y) => throw null; + public static System.SByte MinMagnitudeNumber(System.SByte x, System.SByte y) => throw null; + public static System.SByte MinNumber(System.SByte x, System.SByte y) => throw null; public const System.SByte MinValue = default; + static System.SByte System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.SByte System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.SByte System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + static System.SByte System.Numerics.INumberBase.One { get => throw null; } + public static System.SByte Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.SByte Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.SByte Parse(string s) => throw null; public static System.SByte Parse(string s, System.IFormatProvider provider) => throw null; public static System.SByte Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.SByte Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.SByte PopCount(System.SByte value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.SByte RotateLeft(System.SByte value, int rotateAmount) => throw null; + public static System.SByte RotateRight(System.SByte value, int rotateAmount) => throw null; // Stub generator skipped constructor + public static int Sign(System.SByte value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -3564,60 +4559,194 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.SByte TrailingZeroCount(System.SByte value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.SByte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.SByte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.SByte result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.SByte value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.SByte value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.SByte value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.SByte result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.SByte result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.SByte result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.SByte result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.SByte result) => throw null; public static bool TryParse(string s, out System.SByte result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.SByte value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.SByte value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static System.SByte System.Numerics.INumberBase.Zero { get => throw null; } + static System.SByte System.Numerics.IBitwiseOperators.operator ^(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IMultiplyOperators.operator checked *(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IAdditionOperators.operator checked +(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IIncrementOperators.operator checked ++(System.SByte value) => throw null; + static System.SByte System.Numerics.IUnaryNegationOperators.operator checked -(System.SByte value) => throw null; + static System.SByte System.Numerics.ISubtractionOperators.operator checked -(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IDecrementOperators.operator checked --(System.SByte value) => throw null; + static System.SByte System.Numerics.IBitwiseOperators.operator |(System.SByte left, System.SByte right) => throw null; + static System.SByte System.Numerics.IBitwiseOperators.operator ~(System.SByte value) => throw null; } - // Generated from `System.STAThreadAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class STAThreadAttribute : System.Attribute { public STAThreadAttribute() => throw null; } - // Generated from `System.SerializableAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SerializableAttribute : System.Attribute { public SerializableAttribute() => throw null; } - // Generated from `System.Single` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct Single : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct Single : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryFloatingPointIeee754, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators { - public static bool operator !=(float left, float right) => throw null; - public static bool operator <(float left, float right) => throw null; - public static bool operator <=(float left, float right) => throw null; - public static bool operator ==(float left, float right) => throw null; - public static bool operator >(float left, float right) => throw null; - public static bool operator >=(float left, float right) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(float left, float right) => throw null; + static float System.Numerics.IModulusOperators.operator %(float left, float right) => throw null; + static float System.Numerics.IBitwiseOperators.operator &(float left, float right) => throw null; + static float System.Numerics.IMultiplyOperators.operator *(float left, float right) => throw null; + static float System.Numerics.IUnaryPlusOperators.operator +(float value) => throw null; + static float System.Numerics.IAdditionOperators.operator +(float left, float right) => throw null; + static float System.Numerics.IIncrementOperators.operator ++(float value) => throw null; + static float System.Numerics.IUnaryNegationOperators.operator -(float value) => throw null; + static float System.Numerics.ISubtractionOperators.operator -(float left, float right) => throw null; + static float System.Numerics.IDecrementOperators.operator --(float value) => throw null; + static float System.Numerics.IDivisionOperators.operator /(float left, float right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(float left, float right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(float left, float right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(float left, float right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(float left, float right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(float left, float right) => throw null; + public static float Abs(float value) => throw null; + public static float Acos(float x) => throw null; + public static float AcosPi(float x) => throw null; + public static float Acosh(float x) => throw null; + static float System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static float System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static float Asin(float x) => throw null; + public static float AsinPi(float x) => throw null; + public static float Asinh(float x) => throw null; + public static float Atan(float x) => throw null; + public static float Atan2(float y, float x) => throw null; + public static float Atan2Pi(float y, float x) => throw null; + public static float AtanPi(float x) => throw null; + public static float Atanh(float x) => throw null; + public static float BitDecrement(float x) => throw null; + public static float BitIncrement(float x) => throw null; + public static float Cbrt(float x) => throw null; + public static float Ceiling(float x) => throw null; + public static float Clamp(float value, float min, float max) => throw null; public int CompareTo(float value) => throw null; public int CompareTo(object value) => throw null; + public static float CopySign(float value, float sign) => throw null; + public static float Cos(float x) => throw null; + public static float CosPi(float x) => throw null; + public static float Cosh(float x) => throw null; + static float System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static float System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static float System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public const float E = default; + static float System.Numerics.IFloatingPointConstants.E { get => throw null; } public const float Epsilon = default; + static float System.Numerics.IFloatingPointIeee754.Epsilon { get => throw null; } public bool Equals(float obj) => throw null; public override bool Equals(object obj) => throw null; + public static float Exp(float x) => throw null; + public static float Exp10(float x) => throw null; + public static float Exp10M1(float x) => throw null; + public static float Exp2(float x) => throw null; + public static float Exp2M1(float x) => throw null; + public static float ExpM1(float x) => throw null; + public static float Floor(float x) => throw null; + public static float FusedMultiplyAdd(float left, float right, float addend) => throw null; + int System.Numerics.IFloatingPoint.GetExponentByteCount() => throw null; + int System.Numerics.IFloatingPoint.GetExponentShortestBitLength() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandBitLength() => throw null; + int System.Numerics.IFloatingPoint.GetSignificandByteCount() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static float Hypot(float x, float y) => throw null; + public static int ILogB(float x) => throw null; + public static float Ieee754Remainder(float left, float right) => throw null; + public static bool IsCanonical(float value) => throw null; + public static bool IsComplexNumber(float value) => throw null; + public static bool IsEvenInteger(float value) => throw null; public static bool IsFinite(float f) => throw null; + public static bool IsImaginaryNumber(float value) => throw null; public static bool IsInfinity(float f) => throw null; + public static bool IsInteger(float value) => throw null; public static bool IsNaN(float f) => throw null; public static bool IsNegative(float f) => throw null; public static bool IsNegativeInfinity(float f) => throw null; public static bool IsNormal(float f) => throw null; + public static bool IsOddInteger(float value) => throw null; + public static bool IsPositive(float value) => throw null; public static bool IsPositiveInfinity(float f) => throw null; + public static bool IsPow2(float value) => throw null; + public static bool IsRealNumber(float value) => throw null; public static bool IsSubnormal(float f) => throw null; + public static bool IsZero(float value) => throw null; + public static float Log(float x) => throw null; + public static float Log(float x, float newBase) => throw null; + public static float Log10(float x) => throw null; + public static float Log10P1(float x) => throw null; + public static float Log2(float value) => throw null; + public static float Log2P1(float x) => throw null; + public static float LogP1(float x) => throw null; + public static float Max(float x, float y) => throw null; + public static float MaxMagnitude(float x, float y) => throw null; + public static float MaxMagnitudeNumber(float x, float y) => throw null; + public static float MaxNumber(float x, float y) => throw null; public const float MaxValue = default; + static float System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static float Min(float x, float y) => throw null; + public static float MinMagnitude(float x, float y) => throw null; + public static float MinMagnitudeNumber(float x, float y) => throw null; + public static float MinNumber(float x, float y) => throw null; public const float MinValue = default; + static float System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static float System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } public const float NaN = default; + static float System.Numerics.IFloatingPointIeee754.NaN { get => throw null; } public const float NegativeInfinity = default; + static float System.Numerics.IFloatingPointIeee754.NegativeInfinity { get => throw null; } + static float System.Numerics.ISignedNumber.NegativeOne { get => throw null; } + public const float NegativeZero = default; + static float System.Numerics.IFloatingPointIeee754.NegativeZero { get => throw null; } + static float System.Numerics.INumberBase.One { get => throw null; } + public static float Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static float Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static float Parse(string s) => throw null; public static float Parse(string s, System.IFormatProvider provider) => throw null; public static float Parse(string s, System.Globalization.NumberStyles style) => throw null; public static float Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public const float Pi = default; + static float System.Numerics.IFloatingPointConstants.Pi { get => throw null; } public const float PositiveInfinity = default; + static float System.Numerics.IFloatingPointIeee754.PositiveInfinity { get => throw null; } + public static float Pow(float x, float y) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static float ReciprocalEstimate(float x) => throw null; + public static float ReciprocalSqrtEstimate(float x) => throw null; + public static float RootN(float x, int n) => throw null; + public static float Round(float x) => throw null; + public static float Round(float x, System.MidpointRounding mode) => throw null; + public static float Round(float x, int digits) => throw null; + public static float Round(float x, int digits, System.MidpointRounding mode) => throw null; + public static float ScaleB(float x, int n) => throw null; + public static int Sign(float value) => throw null; + public static float Sin(float x) => throw null; + public static (float, float) SinCos(float x) => throw null; + public static (float, float) SinCosPi(float x) => throw null; + public static float SinPi(float x) => throw null; // Stub generator skipped constructor + public static float Sinh(float x) => throw null; + public static float Sqrt(float x) => throw null; + public static float Tan(float x) => throw null; + public static float TanPi(float x) => throw null; + public static float Tanh(float x) => throw null; + public const float Tau = default; + static float System.Numerics.IFloatingPointConstants.Tau { get => throw null; } bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -3637,17 +4766,32 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static float Truncate(float x) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out float result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out float result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out float result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(float value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(float value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(float value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out float result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out float result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out float result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out float result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out float result) => throw null; public static bool TryParse(string s, out float result) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IFloatingPoint.TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten) => throw null; + static float System.Numerics.INumberBase.Zero { get => throw null; } + static float System.Numerics.IBitwiseOperators.operator ^(float left, float right) => throw null; + static float System.Numerics.IBitwiseOperators.operator |(float left, float right) => throw null; + static float System.Numerics.IBitwiseOperators.operator ~(float value) => throw null; } - // Generated from `System.Span<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Span { - // Generated from `System.Span<>+Enumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -3675,6 +4819,7 @@ namespace System public Span(T[] array) => throw null; public Span(T[] array, int start, int length) => throw null; unsafe public Span(void* pointer, int length) => throw null; + public Span(ref T reference) => throw null; public T[] ToArray() => throw null; public override string ToString() => throw null; public bool TryCopyTo(System.Span destination) => throw null; @@ -3683,7 +4828,6 @@ namespace System public static implicit operator System.Span(T[] array) => throw null; } - // Generated from `System.StackOverflowException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StackOverflowException : System.SystemException { public StackOverflowException() => throw null; @@ -3691,7 +4835,6 @@ namespace System public StackOverflowException(string message, System.Exception innerException) => throw null; } - // Generated from `System.String` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class String : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable, System.ICloneable, System.IComparable, System.IComparable, System.IConvertible, System.IEquatable { public static bool operator !=(string a, string b) => throw null; @@ -3883,7 +5026,6 @@ namespace System public static implicit operator System.ReadOnlySpan(string value) => throw null; } - // Generated from `System.StringComparer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class StringComparer : System.Collections.Generic.IComparer, System.Collections.Generic.IEqualityComparer, System.Collections.IComparer, System.Collections.IEqualityComparer { public int Compare(object x, object y) => throw null; @@ -3906,7 +5048,6 @@ namespace System protected StringComparer() => throw null; } - // Generated from `System.StringComparison` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum StringComparison : int { CurrentCulture = 0, @@ -3917,7 +5058,6 @@ namespace System OrdinalIgnoreCase = 5, } - // Generated from `System.StringNormalizationExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class StringNormalizationExtensions { public static bool IsNormalized(this string strInput) => throw null; @@ -3926,7 +5066,6 @@ namespace System public static string Normalize(this string strInput, System.Text.NormalizationForm normalizationForm) => throw null; } - // Generated from `System.StringSplitOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum StringSplitOptions : int { @@ -3935,7 +5074,6 @@ namespace System TrimEntries = 2, } - // Generated from `System.SystemException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SystemException : System.Exception { public SystemException() => throw null; @@ -3944,14 +5082,12 @@ namespace System public SystemException(string message, System.Exception innerException) => throw null; } - // Generated from `System.ThreadStaticAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadStaticAttribute : System.Attribute { public ThreadStaticAttribute() => throw null; } - // Generated from `System.TimeOnly` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct TimeOnly : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct TimeOnly : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable { public static bool operator !=(System.TimeOnly left, System.TimeOnly right) => throw null; public static System.TimeSpan operator -(System.TimeOnly t1, System.TimeOnly t2) => throw null; @@ -3976,11 +5112,15 @@ namespace System public int Hour { get => throw null; } public bool IsBetween(System.TimeOnly start, System.TimeOnly end) => throw null; public static System.TimeOnly MaxValue { get => throw null; } + public int Microsecond { get => throw null; } public int Millisecond { get => throw null; } public static System.TimeOnly MinValue { get => throw null; } public int Minute { get => throw null; } + public int Nanosecond { get => throw null; } + public static System.TimeOnly Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.TimeOnly Parse(System.ReadOnlySpan s, System.IFormatProvider provider = default(System.IFormatProvider), System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.TimeOnly Parse(string s) => throw null; + public static System.TimeOnly Parse(string s, System.IFormatProvider provider) => throw null; public static System.TimeOnly Parse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.TimeOnly ParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider provider = default(System.IFormatProvider), System.Globalization.DateTimeStyles style = default(System.Globalization.DateTimeStyles)) => throw null; public static System.TimeOnly ParseExact(System.ReadOnlySpan s, string[] formats) => throw null; @@ -3995,6 +5135,7 @@ namespace System public TimeOnly(int hour, int minute) => throw null; public TimeOnly(int hour, int minute, int second) => throw null; public TimeOnly(int hour, int minute, int second, int millisecond) => throw null; + public TimeOnly(int hour, int minute, int second, int millisecond, int microsecond) => throw null; public TimeOnly(System.Int64 ticks) => throw null; public string ToLongTimeString() => throw null; public string ToShortTimeString() => throw null; @@ -4005,8 +5146,10 @@ namespace System public System.TimeSpan ToTimeSpan() => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.TimeOnly result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.TimeOnly result) => throw null; public static bool TryParse(string s, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.TimeOnly result) => throw null; public static bool TryParse(string s, out System.TimeOnly result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, System.IFormatProvider provider, System.Globalization.DateTimeStyles style, out System.TimeOnly result) => throw null; public static bool TryParseExact(System.ReadOnlySpan s, System.ReadOnlySpan format, out System.TimeOnly result) => throw null; @@ -4018,8 +5161,7 @@ namespace System public static bool TryParseExact(string s, string format, out System.TimeOnly result) => throw null; } - // Generated from `System.TimeSpan` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct TimeSpan : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct TimeSpan : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable { public static bool operator !=(System.TimeSpan t1, System.TimeSpan t2) => throw null; public static System.TimeSpan operator *(System.TimeSpan timeSpan, double factor) => throw null; @@ -4048,6 +5190,7 @@ namespace System public override bool Equals(object value) => throw null; public static System.TimeSpan FromDays(double value) => throw null; public static System.TimeSpan FromHours(double value) => throw null; + public static System.TimeSpan FromMicroseconds(double value) => throw null; public static System.TimeSpan FromMilliseconds(double value) => throw null; public static System.TimeSpan FromMinutes(double value) => throw null; public static System.TimeSpan FromSeconds(double value) => throw null; @@ -4055,10 +5198,13 @@ namespace System public override int GetHashCode() => throw null; public int Hours { get => throw null; } public static System.TimeSpan MaxValue; + public int Microseconds { get => throw null; } public int Milliseconds { get => throw null; } public static System.TimeSpan MinValue; public int Minutes { get => throw null; } public System.TimeSpan Multiply(double factor) => throw null; + public int Nanoseconds { get => throw null; } + public const System.Int64 NanosecondsPerTick = default; public System.TimeSpan Negate() => throw null; public static System.TimeSpan Parse(System.ReadOnlySpan input, System.IFormatProvider formatProvider = default(System.IFormatProvider)) => throw null; public static System.TimeSpan Parse(string s) => throw null; @@ -4074,6 +5220,7 @@ namespace System public System.Int64 Ticks { get => throw null; } public const System.Int64 TicksPerDay = default; public const System.Int64 TicksPerHour = default; + public const System.Int64 TicksPerMicrosecond = default; public const System.Int64 TicksPerMillisecond = default; public const System.Int64 TicksPerMinute = default; public const System.Int64 TicksPerSecond = default; @@ -4081,14 +5228,17 @@ namespace System public TimeSpan(int hours, int minutes, int seconds) => throw null; public TimeSpan(int days, int hours, int minutes, int seconds) => throw null; public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds) => throw null; + public TimeSpan(int days, int hours, int minutes, int seconds, int milliseconds, int microseconds) => throw null; public TimeSpan(System.Int64 ticks) => throw null; public override string ToString() => throw null; public string ToString(string format) => throw null; public string ToString(string format, System.IFormatProvider formatProvider) => throw null; public double TotalDays { get => throw null; } public double TotalHours { get => throw null; } + public double TotalMicroseconds { get => throw null; } public double TotalMilliseconds { get => throw null; } public double TotalMinutes { get => throw null; } + public double TotalNanoseconds { get => throw null; } public double TotalSeconds { get => throw null; } public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider formatProvider = default(System.IFormatProvider)) => throw null; public static bool TryParse(System.ReadOnlySpan input, System.IFormatProvider formatProvider, out System.TimeSpan result) => throw null; @@ -4106,7 +5256,6 @@ namespace System public static System.TimeSpan Zero; } - // Generated from `System.TimeZone` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TimeZone { public static System.TimeZone CurrentTimeZone { get => throw null; } @@ -4121,10 +5270,8 @@ namespace System public virtual System.DateTime ToUniversalTime(System.DateTime time) => throw null; } - // Generated from `System.TimeZoneInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TimeZoneInfo : System.IEquatable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { - // Generated from `System.TimeZoneInfo+AdjustmentRule` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AdjustmentRule : System.IEquatable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public System.TimeSpan BaseUtcOffsetDelta { get => throw null; } @@ -4136,13 +5283,13 @@ namespace System public System.TimeZoneInfo.TransitionTime DaylightTransitionEnd { get => throw null; } public System.TimeZoneInfo.TransitionTime DaylightTransitionStart { get => throw null; } public bool Equals(System.TimeZoneInfo.AdjustmentRule other) => throw null; + public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null; } - // Generated from `System.TimeZoneInfo+TransitionTime` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TransitionTime : System.IEquatable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.TimeZoneInfo.TransitionTime t1, System.TimeZoneInfo.TransitionTime t2) => throw null; @@ -4212,7 +5359,6 @@ namespace System public static System.TimeZoneInfo Utc { get => throw null; } } - // Generated from `System.TimeZoneNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TimeZoneNotFoundException : System.Exception { public TimeZoneNotFoundException() => throw null; @@ -4221,7 +5367,6 @@ namespace System public TimeZoneNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.TimeoutException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TimeoutException : System.SystemException { public TimeoutException() => throw null; @@ -4230,7 +5375,6 @@ namespace System public TimeoutException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Tuple` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Tuple { public static System.Tuple> Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) => throw null; @@ -4243,7 +5387,6 @@ namespace System public static System.Tuple Create(T1 item1) => throw null; } - // Generated from `System.Tuple<,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4266,7 +5409,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) => throw null; } - // Generated from `System.Tuple<,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4288,7 +5430,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) => throw null; } - // Generated from `System.Tuple<,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4309,7 +5450,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) => throw null; } - // Generated from `System.Tuple<,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4329,7 +5469,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) => throw null; } - // Generated from `System.Tuple<,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4348,7 +5487,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3, T4 item4) => throw null; } - // Generated from `System.Tuple<,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4366,7 +5504,6 @@ namespace System public Tuple(T1 item1, T2 item2, T3 item3) => throw null; } - // Generated from `System.Tuple<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4383,7 +5520,6 @@ namespace System public Tuple(T1 item1, T2 item2) => throw null; } - // Generated from `System.Tuple<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Tuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.Runtime.CompilerServices.ITuple { int System.IComparable.CompareTo(object obj) => throw null; @@ -4399,7 +5535,6 @@ namespace System public Tuple(T1 item1) => throw null; } - // Generated from `System.TupleExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class TupleExtensions { public static void Deconstruct(this System.Tuple>> value, out T1 item1, out T2 item2, out T3 item3, out T4 item4, out T5 item5, out T6 item6, out T7 item7, out T8 item8, out T9 item9, out T10 item10, out T11 item11, out T12 item12, out T13 item13, out T14 item14, out T15 item15, out T16 item16, out T17 item17, out T18 item18, out T19 item19, out T20 item20, out T21 item21) => throw null; @@ -4467,7 +5602,6 @@ namespace System public static System.ValueTuple ToValueTuple(this System.Tuple value) => throw null; } - // Generated from `System.Type` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Type : System.Reflection.MemberInfo, System.Reflection.IReflect { public static bool operator !=(System.Type left, System.Type right) => throw null; @@ -4509,6 +5643,7 @@ namespace System public virtual string[] GetEnumNames() => throw null; public virtual System.Type GetEnumUnderlyingType() => throw null; public virtual System.Array GetEnumValues() => throw null; + public virtual System.Array GetEnumValuesAsUnderlyingType() => throw null; public System.Reflection.EventInfo GetEvent(string name) => throw null; public abstract System.Reflection.EventInfo GetEvent(string name, System.Reflection.BindingFlags bindingAttr); public virtual System.Reflection.EventInfo[] GetEvents() => throw null; @@ -4666,7 +5801,6 @@ namespace System public abstract System.Type UnderlyingSystemType { get; } } - // Generated from `System.TypeAccessException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeAccessException : System.TypeLoadException { public TypeAccessException() => throw null; @@ -4675,7 +5809,6 @@ namespace System public TypeAccessException(string message, System.Exception inner) => throw null; } - // Generated from `System.TypeCode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TypeCode : int { Boolean = 3, @@ -4698,7 +5831,6 @@ namespace System UInt64 = 12, } - // Generated from `System.TypeInitializationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeInitializationException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -4706,7 +5838,6 @@ namespace System public string TypeName { get => throw null; } } - // Generated from `System.TypeLoadException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeLoadException : System.SystemException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -4718,7 +5849,6 @@ namespace System public string TypeName { get => throw null; } } - // Generated from `System.TypeUnloadedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeUnloadedException : System.SystemException { public TypeUnloadedException() => throw null; @@ -4727,7 +5857,6 @@ namespace System public TypeUnloadedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.TypedReference` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TypedReference { public override bool Equals(object o) => throw null; @@ -4740,22 +5869,255 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.UInt16` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct UInt16 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct UInt128 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber { + static bool System.Numerics.IEqualityOperators.operator !=(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IModulusOperators.operator %(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IBitwiseOperators.operator &(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IMultiplyOperators.operator *(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IUnaryPlusOperators.operator +(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IAdditionOperators.operator +(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IIncrementOperators.operator ++(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IUnaryNegationOperators.operator -(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.ISubtractionOperators.operator -(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IDecrementOperators.operator --(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IDivisionOperators.operator /(System.UInt128 left, System.UInt128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IShiftOperators.operator <<(System.UInt128 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.UInt128 left, System.UInt128 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.UInt128 left, System.UInt128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.UInt128 left, System.UInt128 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IShiftOperators.operator >>(System.UInt128 value, int shiftAmount) => throw null; + static System.UInt128 System.Numerics.IShiftOperators.operator >>>(System.UInt128 value, int shiftAmount) => throw null; + public static System.UInt128 Abs(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.UInt128 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.UInt128 Clamp(System.UInt128 value, System.UInt128 min, System.UInt128 max) => throw null; + public int CompareTo(System.UInt128 value) => throw null; + public int CompareTo(object value) => throw null; + public static System.UInt128 CopySign(System.UInt128 value, System.UInt128 sign) => throw null; + static System.UInt128 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.UInt128 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.UInt128 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.UInt128, System.UInt128) DivRem(System.UInt128 left, System.UInt128 right) => throw null; + public bool Equals(System.UInt128 other) => throw null; + public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; + public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; + public static bool IsCanonical(System.UInt128 value) => throw null; + public static bool IsComplexNumber(System.UInt128 value) => throw null; + public static bool IsEvenInteger(System.UInt128 value) => throw null; + public static bool IsFinite(System.UInt128 value) => throw null; + public static bool IsImaginaryNumber(System.UInt128 value) => throw null; + public static bool IsInfinity(System.UInt128 value) => throw null; + public static bool IsInteger(System.UInt128 value) => throw null; + public static bool IsNaN(System.UInt128 value) => throw null; + public static bool IsNegative(System.UInt128 value) => throw null; + public static bool IsNegativeInfinity(System.UInt128 value) => throw null; + public static bool IsNormal(System.UInt128 value) => throw null; + public static bool IsOddInteger(System.UInt128 value) => throw null; + public static bool IsPositive(System.UInt128 value) => throw null; + public static bool IsPositiveInfinity(System.UInt128 value) => throw null; + public static bool IsPow2(System.UInt128 value) => throw null; + public static bool IsRealNumber(System.UInt128 value) => throw null; + public static bool IsSubnormal(System.UInt128 value) => throw null; + public static bool IsZero(System.UInt128 value) => throw null; + public static System.UInt128 LeadingZeroCount(System.UInt128 value) => throw null; + public static System.UInt128 Log2(System.UInt128 value) => throw null; + public static System.UInt128 Max(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MaxMagnitude(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MaxMagnitudeNumber(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MaxNumber(System.UInt128 x, System.UInt128 y) => throw null; + static System.UInt128 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.UInt128 Min(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MinMagnitude(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MinMagnitudeNumber(System.UInt128 x, System.UInt128 y) => throw null; + public static System.UInt128 MinNumber(System.UInt128 x, System.UInt128 y) => throw null; + static System.UInt128 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.UInt128 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.UInt128 System.Numerics.INumberBase.One { get => throw null; } + public static System.UInt128 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; + public static System.UInt128 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static System.UInt128 Parse(string s) => throw null; + public static System.UInt128 Parse(string s, System.IFormatProvider provider) => throw null; + public static System.UInt128 Parse(string s, System.Globalization.NumberStyles style) => throw null; + public static System.UInt128 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.UInt128 PopCount(System.UInt128 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.UInt128 RotateLeft(System.UInt128 value, int rotateAmount) => throw null; + public static System.UInt128 RotateRight(System.UInt128 value, int rotateAmount) => throw null; + public static int Sign(System.UInt128 value) => throw null; + public override string ToString() => throw null; + public string ToString(System.IFormatProvider provider) => throw null; + public string ToString(string format) => throw null; + public string ToString(string format, System.IFormatProvider provider) => throw null; + public static System.UInt128 TrailingZeroCount(System.UInt128 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt128 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt128 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt128 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt128 value, out TOther result) => throw null; + public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.UInt128 result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt128 result) => throw null; + public static bool TryParse(System.ReadOnlySpan s, out System.UInt128 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.UInt128 result) => throw null; + public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt128 result) => throw null; + public static bool TryParse(string s, out System.UInt128 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt128 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt128 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; + // Stub generator skipped constructor + public UInt128(System.UInt64 upper, System.UInt64 lower) => throw null; + static System.UInt128 System.Numerics.INumberBase.Zero { get => throw null; } + static System.UInt128 System.Numerics.IBitwiseOperators.operator ^(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IMultiplyOperators.operator checked *(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IAdditionOperators.operator checked +(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IIncrementOperators.operator checked ++(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IUnaryNegationOperators.operator checked -(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.ISubtractionOperators.operator checked -(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IDecrementOperators.operator checked --(System.UInt128 value) => throw null; + static System.UInt128 System.Numerics.IDivisionOperators.operator checked /(System.UInt128 left, System.UInt128 right) => throw null; + public static explicit operator checked System.UInt128(System.IntPtr value) => throw null; + public static explicit operator checked System.Byte(System.UInt128 value) => throw null; + public static explicit operator checked System.Char(System.UInt128 value) => throw null; + public static explicit operator checked System.Int128(System.UInt128 value) => throw null; + public static explicit operator checked System.Int16(System.UInt128 value) => throw null; + public static explicit operator checked System.Int64(System.UInt128 value) => throw null; + public static explicit operator checked System.IntPtr(System.UInt128 value) => throw null; + public static explicit operator checked System.SByte(System.UInt128 value) => throw null; + public static explicit operator checked System.UInt16(System.UInt128 value) => throw null; + public static explicit operator checked System.UInt32(System.UInt128 value) => throw null; + public static explicit operator checked System.UInt64(System.UInt128 value) => throw null; + public static explicit operator checked System.UIntPtr(System.UInt128 value) => throw null; + public static explicit operator checked int(System.UInt128 value) => throw null; + public static explicit operator checked System.UInt128(double value) => throw null; + public static explicit operator checked System.UInt128(float value) => throw null; + public static explicit operator checked System.UInt128(int value) => throw null; + public static explicit operator checked System.UInt128(System.Int64 value) => throw null; + public static explicit operator checked System.UInt128(System.SByte value) => throw null; + public static explicit operator checked System.UInt128(System.Int16 value) => throw null; + public static explicit operator System.UInt128(System.IntPtr value) => throw null; + public static explicit operator System.Byte(System.UInt128 value) => throw null; + public static explicit operator System.Char(System.UInt128 value) => throw null; + public static explicit operator System.Decimal(System.UInt128 value) => throw null; + public static explicit operator System.Half(System.UInt128 value) => throw null; + public static explicit operator System.Int128(System.UInt128 value) => throw null; + public static explicit operator System.Int16(System.UInt128 value) => throw null; + public static explicit operator System.Int64(System.UInt128 value) => throw null; + public static explicit operator System.IntPtr(System.UInt128 value) => throw null; + public static explicit operator System.SByte(System.UInt128 value) => throw null; + public static explicit operator System.UInt16(System.UInt128 value) => throw null; + public static explicit operator System.UInt32(System.UInt128 value) => throw null; + public static explicit operator System.UInt64(System.UInt128 value) => throw null; + public static explicit operator System.UIntPtr(System.UInt128 value) => throw null; + public static explicit operator double(System.UInt128 value) => throw null; + public static explicit operator float(System.UInt128 value) => throw null; + public static explicit operator int(System.UInt128 value) => throw null; + public static explicit operator System.UInt128(System.Decimal value) => throw null; + public static explicit operator System.UInt128(double value) => throw null; + public static explicit operator System.UInt128(float value) => throw null; + public static explicit operator System.UInt128(int value) => throw null; + public static explicit operator System.UInt128(System.Int64 value) => throw null; + public static explicit operator System.UInt128(System.SByte value) => throw null; + public static explicit operator System.UInt128(System.Int16 value) => throw null; + public static implicit operator System.UInt128(System.UIntPtr value) => throw null; + public static implicit operator System.UInt128(System.Byte value) => throw null; + public static implicit operator System.UInt128(System.Char value) => throw null; + public static implicit operator System.UInt128(System.UInt32 value) => throw null; + public static implicit operator System.UInt128(System.UInt64 value) => throw null; + public static implicit operator System.UInt128(System.UInt16 value) => throw null; + static System.UInt128 System.Numerics.IBitwiseOperators.operator |(System.UInt128 left, System.UInt128 right) => throw null; + static System.UInt128 System.Numerics.IBitwiseOperators.operator ~(System.UInt128 value) => throw null; + } + + public struct UInt16 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber + { + static bool System.Numerics.IEqualityOperators.operator !=(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IModulusOperators.operator %(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IBitwiseOperators.operator &(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IMultiplyOperators.operator *(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IUnaryPlusOperators.operator +(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IAdditionOperators.operator +(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IIncrementOperators.operator ++(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IUnaryNegationOperators.operator -(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.ISubtractionOperators.operator -(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IDecrementOperators.operator --(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IDivisionOperators.operator /(System.UInt16 left, System.UInt16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IShiftOperators.operator <<(System.UInt16 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.UInt16 left, System.UInt16 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.UInt16 left, System.UInt16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.UInt16 left, System.UInt16 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IShiftOperators.operator >>(System.UInt16 value, int shiftAmount) => throw null; + static System.UInt16 System.Numerics.IShiftOperators.operator >>>(System.UInt16 value, int shiftAmount) => throw null; + public static System.UInt16 Abs(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.UInt16 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.UInt16 Clamp(System.UInt16 value, System.UInt16 min, System.UInt16 max) => throw null; public int CompareTo(object value) => throw null; public int CompareTo(System.UInt16 value) => throw null; + public static System.UInt16 CopySign(System.UInt16 value, System.UInt16 sign) => throw null; + static System.UInt16 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.UInt16 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.UInt16 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.UInt16, System.UInt16) DivRem(System.UInt16 left, System.UInt16 right) => throw null; public override bool Equals(object obj) => throw null; public bool Equals(System.UInt16 obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.UInt16 value) => throw null; + public static bool IsComplexNumber(System.UInt16 value) => throw null; + public static bool IsEvenInteger(System.UInt16 value) => throw null; + public static bool IsFinite(System.UInt16 value) => throw null; + public static bool IsImaginaryNumber(System.UInt16 value) => throw null; + public static bool IsInfinity(System.UInt16 value) => throw null; + public static bool IsInteger(System.UInt16 value) => throw null; + public static bool IsNaN(System.UInt16 value) => throw null; + public static bool IsNegative(System.UInt16 value) => throw null; + public static bool IsNegativeInfinity(System.UInt16 value) => throw null; + public static bool IsNormal(System.UInt16 value) => throw null; + public static bool IsOddInteger(System.UInt16 value) => throw null; + public static bool IsPositive(System.UInt16 value) => throw null; + public static bool IsPositiveInfinity(System.UInt16 value) => throw null; + public static bool IsPow2(System.UInt16 value) => throw null; + public static bool IsRealNumber(System.UInt16 value) => throw null; + public static bool IsSubnormal(System.UInt16 value) => throw null; + public static bool IsZero(System.UInt16 value) => throw null; + public static System.UInt16 LeadingZeroCount(System.UInt16 value) => throw null; + public static System.UInt16 Log2(System.UInt16 value) => throw null; + public static System.UInt16 Max(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MaxMagnitude(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MaxMagnitudeNumber(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MaxNumber(System.UInt16 x, System.UInt16 y) => throw null; public const System.UInt16 MaxValue = default; + static System.UInt16 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.UInt16 Min(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MinMagnitude(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MinMagnitudeNumber(System.UInt16 x, System.UInt16 y) => throw null; + public static System.UInt16 MinNumber(System.UInt16 x, System.UInt16 y) => throw null; public const System.UInt16 MinValue = default; + static System.UInt16 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.UInt16 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.UInt16 System.Numerics.INumberBase.One { get => throw null; } + public static System.UInt16 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.UInt16 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.UInt16 Parse(string s) => throw null; public static System.UInt16 Parse(string s, System.IFormatProvider provider) => throw null; public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.UInt16 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.UInt16 PopCount(System.UInt16 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.UInt16 RotateLeft(System.UInt16 value, int rotateAmount) => throw null; + public static System.UInt16 RotateRight(System.UInt16 value, int rotateAmount) => throw null; + public static int Sign(System.UInt16 value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -4775,30 +6137,120 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.UInt16 TrailingZeroCount(System.UInt16 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt16 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt16 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt16 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt16 value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.UInt16 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt16 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.UInt16 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.UInt16 result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt16 result) => throw null; public static bool TryParse(string s, out System.UInt16 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt16 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt16 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; // Stub generator skipped constructor + static System.UInt16 System.Numerics.INumberBase.Zero { get => throw null; } + static System.UInt16 System.Numerics.IBitwiseOperators.operator ^(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IMultiplyOperators.operator checked *(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IAdditionOperators.operator checked +(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IIncrementOperators.operator checked ++(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IUnaryNegationOperators.operator checked -(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.ISubtractionOperators.operator checked -(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IDecrementOperators.operator checked --(System.UInt16 value) => throw null; + static System.UInt16 System.Numerics.IBitwiseOperators.operator |(System.UInt16 left, System.UInt16 right) => throw null; + static System.UInt16 System.Numerics.IBitwiseOperators.operator ~(System.UInt16 value) => throw null; } - // Generated from `System.UInt32` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct UInt32 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct UInt32 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber { + static bool System.Numerics.IEqualityOperators.operator !=(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IModulusOperators.operator %(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IBitwiseOperators.operator &(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IMultiplyOperators.operator *(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IUnaryPlusOperators.operator +(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IAdditionOperators.operator +(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IIncrementOperators.operator ++(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IUnaryNegationOperators.operator -(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.ISubtractionOperators.operator -(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IDecrementOperators.operator --(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IDivisionOperators.operator /(System.UInt32 left, System.UInt32 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IShiftOperators.operator <<(System.UInt32 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.UInt32 left, System.UInt32 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.UInt32 left, System.UInt32 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.UInt32 left, System.UInt32 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IShiftOperators.operator >>(System.UInt32 value, int shiftAmount) => throw null; + static System.UInt32 System.Numerics.IShiftOperators.operator >>>(System.UInt32 value, int shiftAmount) => throw null; + public static System.UInt32 Abs(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.UInt32 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.UInt32 Clamp(System.UInt32 value, System.UInt32 min, System.UInt32 max) => throw null; public int CompareTo(object value) => throw null; public int CompareTo(System.UInt32 value) => throw null; + public static System.UInt32 CopySign(System.UInt32 value, System.UInt32 sign) => throw null; + static System.UInt32 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.UInt32 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.UInt32 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.UInt32, System.UInt32) DivRem(System.UInt32 left, System.UInt32 right) => throw null; public override bool Equals(object obj) => throw null; public bool Equals(System.UInt32 obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.UInt32 value) => throw null; + public static bool IsComplexNumber(System.UInt32 value) => throw null; + public static bool IsEvenInteger(System.UInt32 value) => throw null; + public static bool IsFinite(System.UInt32 value) => throw null; + public static bool IsImaginaryNumber(System.UInt32 value) => throw null; + public static bool IsInfinity(System.UInt32 value) => throw null; + public static bool IsInteger(System.UInt32 value) => throw null; + public static bool IsNaN(System.UInt32 value) => throw null; + public static bool IsNegative(System.UInt32 value) => throw null; + public static bool IsNegativeInfinity(System.UInt32 value) => throw null; + public static bool IsNormal(System.UInt32 value) => throw null; + public static bool IsOddInteger(System.UInt32 value) => throw null; + public static bool IsPositive(System.UInt32 value) => throw null; + public static bool IsPositiveInfinity(System.UInt32 value) => throw null; + public static bool IsPow2(System.UInt32 value) => throw null; + public static bool IsRealNumber(System.UInt32 value) => throw null; + public static bool IsSubnormal(System.UInt32 value) => throw null; + public static bool IsZero(System.UInt32 value) => throw null; + public static System.UInt32 LeadingZeroCount(System.UInt32 value) => throw null; + public static System.UInt32 Log2(System.UInt32 value) => throw null; + public static System.UInt32 Max(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MaxMagnitude(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MaxMagnitudeNumber(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MaxNumber(System.UInt32 x, System.UInt32 y) => throw null; public const System.UInt32 MaxValue = default; + static System.UInt32 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.UInt32 Min(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MinMagnitude(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MinMagnitudeNumber(System.UInt32 x, System.UInt32 y) => throw null; + public static System.UInt32 MinNumber(System.UInt32 x, System.UInt32 y) => throw null; public const System.UInt32 MinValue = default; + static System.UInt32 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.UInt32 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.UInt32 System.Numerics.INumberBase.One { get => throw null; } + public static System.UInt32 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.UInt32 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.UInt32 Parse(string s) => throw null; public static System.UInt32 Parse(string s, System.IFormatProvider provider) => throw null; public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.UInt32 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.UInt32 PopCount(System.UInt32 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.UInt32 RotateLeft(System.UInt32 value, int rotateAmount) => throw null; + public static System.UInt32 RotateRight(System.UInt32 value, int rotateAmount) => throw null; + public static int Sign(System.UInt32 value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -4818,30 +6270,120 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.UInt32 TrailingZeroCount(System.UInt32 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt32 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt32 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt32 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt32 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt32 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt32 value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.UInt32 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt32 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.UInt32 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.UInt32 result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt32 result) => throw null; public static bool TryParse(string s, out System.UInt32 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt32 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt32 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; // Stub generator skipped constructor + static System.UInt32 System.Numerics.INumberBase.Zero { get => throw null; } + static System.UInt32 System.Numerics.IBitwiseOperators.operator ^(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IMultiplyOperators.operator checked *(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IAdditionOperators.operator checked +(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IIncrementOperators.operator checked ++(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IUnaryNegationOperators.operator checked -(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.ISubtractionOperators.operator checked -(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IDecrementOperators.operator checked --(System.UInt32 value) => throw null; + static System.UInt32 System.Numerics.IBitwiseOperators.operator |(System.UInt32 left, System.UInt32 right) => throw null; + static System.UInt32 System.Numerics.IBitwiseOperators.operator ~(System.UInt32 value) => throw null; } - // Generated from `System.UInt64` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct UInt64 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.ISpanFormattable + public struct UInt64 : System.IComparable, System.IComparable, System.IConvertible, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber { + static bool System.Numerics.IEqualityOperators.operator !=(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IModulusOperators.operator %(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IBitwiseOperators.operator &(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IMultiplyOperators.operator *(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IUnaryPlusOperators.operator +(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IAdditionOperators.operator +(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IIncrementOperators.operator ++(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IUnaryNegationOperators.operator -(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.ISubtractionOperators.operator -(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IDecrementOperators.operator --(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IDivisionOperators.operator /(System.UInt64 left, System.UInt64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IShiftOperators.operator <<(System.UInt64 value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.UInt64 left, System.UInt64 right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.UInt64 left, System.UInt64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.UInt64 left, System.UInt64 right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IShiftOperators.operator >>(System.UInt64 value, int shiftAmount) => throw null; + static System.UInt64 System.Numerics.IShiftOperators.operator >>>(System.UInt64 value, int shiftAmount) => throw null; + public static System.UInt64 Abs(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.UInt64 System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.UInt64 Clamp(System.UInt64 value, System.UInt64 min, System.UInt64 max) => throw null; public int CompareTo(object value) => throw null; public int CompareTo(System.UInt64 value) => throw null; + public static System.UInt64 CopySign(System.UInt64 value, System.UInt64 sign) => throw null; + static System.UInt64 System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.UInt64 System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.UInt64 System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.UInt64, System.UInt64) DivRem(System.UInt64 left, System.UInt64 right) => throw null; public override bool Equals(object obj) => throw null; public bool Equals(System.UInt64 obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; public System.TypeCode GetTypeCode() => throw null; + public static bool IsCanonical(System.UInt64 value) => throw null; + public static bool IsComplexNumber(System.UInt64 value) => throw null; + public static bool IsEvenInteger(System.UInt64 value) => throw null; + public static bool IsFinite(System.UInt64 value) => throw null; + public static bool IsImaginaryNumber(System.UInt64 value) => throw null; + public static bool IsInfinity(System.UInt64 value) => throw null; + public static bool IsInteger(System.UInt64 value) => throw null; + public static bool IsNaN(System.UInt64 value) => throw null; + public static bool IsNegative(System.UInt64 value) => throw null; + public static bool IsNegativeInfinity(System.UInt64 value) => throw null; + public static bool IsNormal(System.UInt64 value) => throw null; + public static bool IsOddInteger(System.UInt64 value) => throw null; + public static bool IsPositive(System.UInt64 value) => throw null; + public static bool IsPositiveInfinity(System.UInt64 value) => throw null; + public static bool IsPow2(System.UInt64 value) => throw null; + public static bool IsRealNumber(System.UInt64 value) => throw null; + public static bool IsSubnormal(System.UInt64 value) => throw null; + public static bool IsZero(System.UInt64 value) => throw null; + public static System.UInt64 LeadingZeroCount(System.UInt64 value) => throw null; + public static System.UInt64 Log2(System.UInt64 value) => throw null; + public static System.UInt64 Max(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MaxMagnitude(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MaxMagnitudeNumber(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MaxNumber(System.UInt64 x, System.UInt64 y) => throw null; public const System.UInt64 MaxValue = default; + static System.UInt64 System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.UInt64 Min(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MinMagnitude(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MinMagnitudeNumber(System.UInt64 x, System.UInt64 y) => throw null; + public static System.UInt64 MinNumber(System.UInt64 x, System.UInt64 y) => throw null; public const System.UInt64 MinValue = default; + static System.UInt64 System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.UInt64 System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.UInt64 System.Numerics.INumberBase.One { get => throw null; } + public static System.UInt64 Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.UInt64 Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.UInt64 Parse(string s) => throw null; public static System.UInt64 Parse(string s, System.IFormatProvider provider) => throw null; public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.UInt64 Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.UInt64 PopCount(System.UInt64 value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.UInt64 RotateLeft(System.UInt64 value, int rotateAmount) => throw null; + public static System.UInt64 RotateRight(System.UInt64 value, int rotateAmount) => throw null; + public static int Sign(System.UInt64 value) => throw null; bool System.IConvertible.ToBoolean(System.IFormatProvider provider) => throw null; System.Byte System.IConvertible.ToByte(System.IFormatProvider provider) => throw null; System.Char System.IConvertible.ToChar(System.IFormatProvider provider) => throw null; @@ -4861,35 +6403,123 @@ namespace System System.UInt16 System.IConvertible.ToUInt16(System.IFormatProvider provider) => throw null; System.UInt32 System.IConvertible.ToUInt32(System.IFormatProvider provider) => throw null; System.UInt64 System.IConvertible.ToUInt64(System.IFormatProvider provider) => throw null; + public static System.UInt64 TrailingZeroCount(System.UInt64 value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UInt64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UInt64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UInt64 result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UInt64 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UInt64 value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UInt64 value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.UInt64 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt64 result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.UInt64 result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.UInt64 result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UInt64 result) => throw null; public static bool TryParse(string s, out System.UInt64 result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt64 value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UInt64 value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; // Stub generator skipped constructor + static System.UInt64 System.Numerics.INumberBase.Zero { get => throw null; } + static System.UInt64 System.Numerics.IBitwiseOperators.operator ^(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IMultiplyOperators.operator checked *(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IAdditionOperators.operator checked +(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IIncrementOperators.operator checked ++(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IUnaryNegationOperators.operator checked -(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.ISubtractionOperators.operator checked -(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IDecrementOperators.operator checked --(System.UInt64 value) => throw null; + static System.UInt64 System.Numerics.IBitwiseOperators.operator |(System.UInt64 left, System.UInt64 right) => throw null; + static System.UInt64 System.Numerics.IBitwiseOperators.operator ~(System.UInt64 value) => throw null; } - // Generated from `System.UIntPtr` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct UIntPtr : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable, System.Runtime.Serialization.ISerializable + public struct UIntPtr : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryInteger, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMinMaxValue, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators, System.Numerics.IUnsignedNumber, System.Runtime.Serialization.ISerializable { - public static bool operator !=(System.UIntPtr value1, System.UIntPtr value2) => throw null; + static bool System.Numerics.IEqualityOperators.operator !=(System.UIntPtr value1, System.UIntPtr value2) => throw null; + static System.UIntPtr System.Numerics.IModulusOperators.operator %(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IBitwiseOperators.operator &(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IMultiplyOperators.operator *(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IUnaryPlusOperators.operator +(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.IAdditionOperators.operator +(System.UIntPtr left, System.UIntPtr right) => throw null; public static System.UIntPtr operator +(System.UIntPtr pointer, int offset) => throw null; + static System.UIntPtr System.Numerics.IIncrementOperators.operator ++(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.IUnaryNegationOperators.operator -(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.ISubtractionOperators.operator -(System.UIntPtr left, System.UIntPtr right) => throw null; public static System.UIntPtr operator -(System.UIntPtr pointer, int offset) => throw null; - public static bool operator ==(System.UIntPtr value1, System.UIntPtr value2) => throw null; + static System.UIntPtr System.Numerics.IDecrementOperators.operator --(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.IDivisionOperators.operator /(System.UIntPtr left, System.UIntPtr right) => throw null; + static bool System.Numerics.IComparisonOperators.operator <(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IShiftOperators.operator <<(System.UIntPtr value, int shiftAmount) => throw null; + static bool System.Numerics.IComparisonOperators.operator <=(System.UIntPtr left, System.UIntPtr right) => throw null; + static bool System.Numerics.IEqualityOperators.operator ==(System.UIntPtr value1, System.UIntPtr value2) => throw null; + static bool System.Numerics.IComparisonOperators.operator >(System.UIntPtr left, System.UIntPtr right) => throw null; + static bool System.Numerics.IComparisonOperators.operator >=(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IShiftOperators.operator >>(System.UIntPtr value, int shiftAmount) => throw null; + static System.UIntPtr System.Numerics.IShiftOperators.operator >>>(System.UIntPtr value, int shiftAmount) => throw null; + public static System.UIntPtr Abs(System.UIntPtr value) => throw null; public static System.UIntPtr Add(System.UIntPtr pointer, int offset) => throw null; + static System.UIntPtr System.Numerics.IAdditiveIdentity.AdditiveIdentity { get => throw null; } + static System.UIntPtr System.Numerics.IBinaryNumber.AllBitsSet { get => throw null; } + public static System.UIntPtr Clamp(System.UIntPtr value, System.UIntPtr min, System.UIntPtr max) => throw null; public int CompareTo(System.UIntPtr value) => throw null; public int CompareTo(object value) => throw null; + public static System.UIntPtr CopySign(System.UIntPtr value, System.UIntPtr sign) => throw null; + static System.UIntPtr System.Numerics.INumberBase.CreateChecked(TOther value) => throw null; + static System.UIntPtr System.Numerics.INumberBase.CreateSaturating(TOther value) => throw null; + static System.UIntPtr System.Numerics.INumberBase.CreateTruncating(TOther value) => throw null; + public static (System.UIntPtr, System.UIntPtr) DivRem(System.UIntPtr left, System.UIntPtr right) => throw null; public bool Equals(System.UIntPtr other) => throw null; public override bool Equals(object obj) => throw null; + int System.Numerics.IBinaryInteger.GetByteCount() => throw null; public override int GetHashCode() => throw null; void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + int System.Numerics.IBinaryInteger.GetShortestBitLength() => throw null; + public static bool IsCanonical(System.UIntPtr value) => throw null; + public static bool IsComplexNumber(System.UIntPtr value) => throw null; + public static bool IsEvenInteger(System.UIntPtr value) => throw null; + public static bool IsFinite(System.UIntPtr value) => throw null; + public static bool IsImaginaryNumber(System.UIntPtr value) => throw null; + public static bool IsInfinity(System.UIntPtr value) => throw null; + public static bool IsInteger(System.UIntPtr value) => throw null; + public static bool IsNaN(System.UIntPtr value) => throw null; + public static bool IsNegative(System.UIntPtr value) => throw null; + public static bool IsNegativeInfinity(System.UIntPtr value) => throw null; + public static bool IsNormal(System.UIntPtr value) => throw null; + public static bool IsOddInteger(System.UIntPtr value) => throw null; + public static bool IsPositive(System.UIntPtr value) => throw null; + public static bool IsPositiveInfinity(System.UIntPtr value) => throw null; + public static bool IsPow2(System.UIntPtr value) => throw null; + public static bool IsRealNumber(System.UIntPtr value) => throw null; + public static bool IsSubnormal(System.UIntPtr value) => throw null; + public static bool IsZero(System.UIntPtr value) => throw null; + public static System.UIntPtr LeadingZeroCount(System.UIntPtr value) => throw null; + public static System.UIntPtr Log2(System.UIntPtr value) => throw null; + public static System.UIntPtr Max(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MaxMagnitude(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MaxMagnitudeNumber(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MaxNumber(System.UIntPtr x, System.UIntPtr y) => throw null; public static System.UIntPtr MaxValue { get => throw null; } + static System.UIntPtr System.Numerics.IMinMaxValue.MaxValue { get => throw null; } + public static System.UIntPtr Min(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MinMagnitude(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MinMagnitudeNumber(System.UIntPtr x, System.UIntPtr y) => throw null; + public static System.UIntPtr MinNumber(System.UIntPtr x, System.UIntPtr y) => throw null; public static System.UIntPtr MinValue { get => throw null; } + static System.UIntPtr System.Numerics.IMinMaxValue.MinValue { get => throw null; } + static System.UIntPtr System.Numerics.IMultiplicativeIdentity.MultiplicativeIdentity { get => throw null; } + static System.UIntPtr System.Numerics.INumberBase.One { get => throw null; } + public static System.UIntPtr Parse(System.ReadOnlySpan s, System.IFormatProvider provider) => throw null; public static System.UIntPtr Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style = default(System.Globalization.NumberStyles), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; public static System.UIntPtr Parse(string s) => throw null; public static System.UIntPtr Parse(string s, System.IFormatProvider provider) => throw null; public static System.UIntPtr Parse(string s, System.Globalization.NumberStyles style) => throw null; public static System.UIntPtr Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider) => throw null; + public static System.UIntPtr PopCount(System.UIntPtr value) => throw null; + static int System.Numerics.INumberBase.Radix { get => throw null; } + public static System.UIntPtr RotateLeft(System.UIntPtr value, int rotateAmount) => throw null; + public static System.UIntPtr RotateRight(System.UIntPtr value, int rotateAmount) => throw null; + public static int Sign(System.UIntPtr value) => throw null; public static int Size { get => throw null; } public static System.UIntPtr Subtract(System.UIntPtr pointer, int offset) => throw null; unsafe public void* ToPointer() => throw null; @@ -4899,25 +6529,47 @@ namespace System public string ToString(string format, System.IFormatProvider provider) => throw null; public System.UInt32 ToUInt32() => throw null; public System.UInt64 ToUInt64() => throw null; + public static System.UIntPtr TrailingZeroCount(System.UIntPtr value) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromChecked(TOther value, out System.UIntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromSaturating(TOther value, out System.UIntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertFromTruncating(TOther value, out System.UIntPtr result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToChecked(System.UIntPtr value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToSaturating(System.UIntPtr value, out TOther result) => throw null; + static bool System.Numerics.INumberBase.TryConvertToTruncating(System.UIntPtr value, out TOther result) => throw null; public bool TryFormat(System.Span destination, out int charsWritten, System.ReadOnlySpan format = default(System.ReadOnlySpan), System.IFormatProvider provider = default(System.IFormatProvider)) => throw null; + public static bool TryParse(System.ReadOnlySpan s, System.IFormatProvider provider, out System.UIntPtr result) => throw null; public static bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UIntPtr result) => throw null; public static bool TryParse(System.ReadOnlySpan s, out System.UIntPtr result) => throw null; + public static bool TryParse(string s, System.IFormatProvider provider, out System.UIntPtr result) => throw null; public static bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out System.UIntPtr result) => throw null; public static bool TryParse(string s, out System.UIntPtr result) => throw null; + public static bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UIntPtr value) => throw null; + public static bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out System.UIntPtr value) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteBigEndian(System.Span destination, out int bytesWritten) => throw null; + bool System.Numerics.IBinaryInteger.TryWriteLittleEndian(System.Span destination, out int bytesWritten) => throw null; // Stub generator skipped constructor unsafe public UIntPtr(void* value) => throw null; public UIntPtr(System.UInt32 value) => throw null; public UIntPtr(System.UInt64 value) => throw null; public static System.UIntPtr Zero; + static System.UIntPtr System.Numerics.INumberBase.Zero { get => throw null; } + static System.UIntPtr System.Numerics.IBitwiseOperators.operator ^(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IMultiplyOperators.operator checked *(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IAdditionOperators.operator checked +(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IIncrementOperators.operator checked ++(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.IUnaryNegationOperators.operator checked -(System.UIntPtr value) => throw null; + static System.UIntPtr System.Numerics.ISubtractionOperators.operator checked -(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IDecrementOperators.operator checked --(System.UIntPtr value) => throw null; public static explicit operator System.UInt32(System.UIntPtr value) => throw null; public static explicit operator System.UInt64(System.UIntPtr value) => throw null; unsafe public static explicit operator void*(System.UIntPtr value) => throw null; unsafe public static explicit operator System.UIntPtr(void* value) => throw null; public static explicit operator System.UIntPtr(System.UInt32 value) => throw null; public static explicit operator System.UIntPtr(System.UInt64 value) => throw null; + static System.UIntPtr System.Numerics.IBitwiseOperators.operator |(System.UIntPtr left, System.UIntPtr right) => throw null; + static System.UIntPtr System.Numerics.IBitwiseOperators.operator ~(System.UIntPtr value) => throw null; } - // Generated from `System.UnauthorizedAccessException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnauthorizedAccessException : System.SystemException { public UnauthorizedAccessException() => throw null; @@ -4926,7 +6578,6 @@ namespace System public UnauthorizedAccessException(string message, System.Exception inner) => throw null; } - // Generated from `System.UnhandledExceptionEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnhandledExceptionEventArgs : System.EventArgs { public object ExceptionObject { get => throw null; } @@ -4934,10 +6585,8 @@ namespace System public UnhandledExceptionEventArgs(object exception, bool isTerminating) => throw null; } - // Generated from `System.UnhandledExceptionEventHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void UnhandledExceptionEventHandler(object sender, System.UnhandledExceptionEventArgs e); - // Generated from `System.Uri` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Uri : System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Uri uri1, System.Uri uri2) => throw null; @@ -5027,7 +6676,6 @@ namespace System public string UserInfo { get => throw null; } } - // Generated from `System.UriBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UriBuilder { public override bool Equals(object rparam) => throw null; @@ -5051,7 +6699,6 @@ namespace System public string UserName { get => throw null; set => throw null; } } - // Generated from `System.UriComponents` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum UriComponents : int { @@ -5074,14 +6721,12 @@ namespace System UserInfo = 2, } - // Generated from `System.UriCreationOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct UriCreationOptions { public bool DangerousDisablePathAndQueryCanonicalization { get => throw null; set => throw null; } // Stub generator skipped constructor } - // Generated from `System.UriFormat` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UriFormat : int { SafeUnescaped = 3, @@ -5089,7 +6734,6 @@ namespace System UriEscaped = 1, } - // Generated from `System.UriFormatException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UriFormatException : System.FormatException, System.Runtime.Serialization.ISerializable { void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -5099,7 +6743,6 @@ namespace System public UriFormatException(string textString, System.Exception e) => throw null; } - // Generated from `System.UriHostNameType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UriHostNameType : int { Basic = 1, @@ -5109,7 +6752,6 @@ namespace System Unknown = 0, } - // Generated from `System.UriKind` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UriKind : int { Absolute = 1, @@ -5117,7 +6759,6 @@ namespace System RelativeOrAbsolute = 0, } - // Generated from `System.UriParser` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class UriParser { protected virtual string GetComponents(System.Uri uri, System.UriComponents components, System.UriFormat format) => throw null; @@ -5132,7 +6773,6 @@ namespace System protected UriParser() => throw null; } - // Generated from `System.UriPartial` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UriPartial : int { Authority = 1, @@ -5141,7 +6781,6 @@ namespace System Scheme = 0, } - // Generated from `System.ValueTuple` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable, System.IEquatable, System.Runtime.CompilerServices.ITuple { public int CompareTo(System.ValueTuple other) => throw null; @@ -5167,7 +6806,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.ValueTuple<,,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable>, System.IEquatable>, System.Runtime.CompilerServices.ITuple where TRest : struct { public int CompareTo(System.ValueTuple other) => throw null; @@ -5193,7 +6831,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, TRest rest) => throw null; } - // Generated from `System.ValueTuple<,,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5, T6, T7)>, System.IEquatable<(T1, T2, T3, T4, T5, T6, T7)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2, T3, T4, T5, T6, T7) other) => throw null; @@ -5218,7 +6855,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7) => throw null; } - // Generated from `System.ValueTuple<,,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5, T6)>, System.IEquatable<(T1, T2, T3, T4, T5, T6)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2, T3, T4, T5, T6) other) => throw null; @@ -5242,7 +6878,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6) => throw null; } - // Generated from `System.ValueTuple<,,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4, T5)>, System.IEquatable<(T1, T2, T3, T4, T5)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2, T3, T4, T5) other) => throw null; @@ -5265,7 +6900,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5) => throw null; } - // Generated from `System.ValueTuple<,,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3, T4)>, System.IEquatable<(T1, T2, T3, T4)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2, T3, T4) other) => throw null; @@ -5287,7 +6921,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3, T4 item4) => throw null; } - // Generated from `System.ValueTuple<,,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2, T3)>, System.IEquatable<(T1, T2, T3)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2, T3) other) => throw null; @@ -5308,7 +6941,6 @@ namespace System public ValueTuple(T1 item1, T2 item2, T3 item3) => throw null; } - // Generated from `System.ValueTuple<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable<(T1, T2)>, System.IEquatable<(T1, T2)>, System.Runtime.CompilerServices.ITuple { public int CompareTo((T1, T2) other) => throw null; @@ -5328,7 +6960,6 @@ namespace System public ValueTuple(T1 item1, T2 item2) => throw null; } - // Generated from `System.ValueTuple<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTuple : System.Collections.IStructuralComparable, System.Collections.IStructuralEquatable, System.IComparable, System.IComparable>, System.IEquatable>, System.Runtime.CompilerServices.ITuple { public int CompareTo(System.ValueTuple other) => throw null; @@ -5347,7 +6978,6 @@ namespace System public ValueTuple(T1 item1) => throw null; } - // Generated from `System.ValueType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ValueType { public override bool Equals(object obj) => throw null; @@ -5356,7 +6986,6 @@ namespace System protected ValueType() => throw null; } - // Generated from `System.Version` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Version : System.ICloneable, System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable { public static bool operator !=(System.Version v1, System.Version v2) => throw null; @@ -5394,12 +7023,10 @@ namespace System public Version(string version) => throw null; } - // Generated from `System.Void` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Void { } - // Generated from `System.WeakReference` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WeakReference : System.Runtime.Serialization.ISerializable { public virtual void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -5412,7 +7039,6 @@ namespace System // ERR: Stub generator didn't handle member: ~WeakReference } - // Generated from `System.WeakReference<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WeakReference : System.Runtime.Serialization.ISerializable where T : class { public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -5425,7 +7051,6 @@ namespace System namespace Buffers { - // Generated from `System.Buffers.ArrayPool<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ArrayPool { protected ArrayPool() => throw null; @@ -5436,20 +7061,17 @@ namespace System public static System.Buffers.ArrayPool Shared { get => throw null; } } - // Generated from `System.Buffers.IMemoryOwner<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IMemoryOwner : System.IDisposable { System.Memory Memory { get; } } - // Generated from `System.Buffers.IPinnable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IPinnable { System.Buffers.MemoryHandle Pin(int elementIndex); void Unpin(); } - // Generated from `System.Buffers.MemoryHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct MemoryHandle : System.IDisposable { public void Dispose() => throw null; @@ -5458,7 +7080,6 @@ namespace System unsafe public void* Pointer { get => throw null; } } - // Generated from `System.Buffers.MemoryManager<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MemoryManager : System.Buffers.IMemoryOwner, System.Buffers.IPinnable, System.IDisposable { protected System.Memory CreateMemory(int length) => throw null; @@ -5473,7 +7094,6 @@ namespace System public abstract void Unpin(); } - // Generated from `System.Buffers.OperationStatus` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum OperationStatus : int { DestinationTooSmall = 1, @@ -5482,18 +7102,28 @@ namespace System NeedMoreData = 2, } - // Generated from `System.Buffers.ReadOnlySpanAction<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ReadOnlySpanAction(System.ReadOnlySpan span, TArg arg); - // Generated from `System.Buffers.SpanAction<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void SpanAction(System.Span span, TArg arg); + namespace Text + { + public static class Base64 + { + public static System.Buffers.OperationStatus DecodeFromUtf8(System.ReadOnlySpan utf8, System.Span bytes, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = default(bool)) => throw null; + public static System.Buffers.OperationStatus DecodeFromUtf8InPlace(System.Span buffer, out int bytesWritten) => throw null; + public static System.Buffers.OperationStatus EncodeToUtf8(System.ReadOnlySpan bytes, System.Span utf8, out int bytesConsumed, out int bytesWritten, bool isFinalBlock = default(bool)) => throw null; + public static System.Buffers.OperationStatus EncodeToUtf8InPlace(System.Span buffer, int dataLength, out int bytesWritten) => throw null; + public static int GetMaxDecodedFromUtf8Length(int length) => throw null; + public static int GetMaxEncodedToUtf8Length(int length) => throw null; + } + + } } namespace CodeDom { namespace Compiler { - // Generated from `System.CodeDom.Compiler.GeneratedCodeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GeneratedCodeAttribute : System.Attribute { public GeneratedCodeAttribute(string tool, string version) => throw null; @@ -5501,7 +7131,6 @@ namespace System public string Version { get => throw null; } } - // Generated from `System.CodeDom.Compiler.IndentedTextWriter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IndentedTextWriter : System.IO.TextWriter { public override void Close() => throw null; @@ -5564,7 +7193,6 @@ namespace System } namespace Collections { - // Generated from `System.Collections.ArrayList` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ArrayList : System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList, System.ICloneable { public static System.Collections.ArrayList Adapter(System.Collections.IList list) => throw null; @@ -5621,7 +7249,6 @@ namespace System public virtual void TrimToSize() => throw null; } - // Generated from `System.Collections.Comparer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Comparer : System.Collections.IComparer, System.Runtime.Serialization.ISerializable { public int Compare(object a, object b) => throw null; @@ -5631,7 +7258,6 @@ namespace System public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; } - // Generated from `System.Collections.DictionaryEntry` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DictionaryEntry { public void Deconstruct(out object key, out object value) => throw null; @@ -5641,7 +7267,6 @@ namespace System public object Value { get => throw null; set => throw null; } } - // Generated from `System.Collections.Hashtable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Hashtable : System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable, System.ICloneable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public virtual void Add(object key, object value) => throw null; @@ -5688,7 +7313,6 @@ namespace System protected System.Collections.IHashCodeProvider hcp { get => throw null; set => throw null; } } - // Generated from `System.Collections.ICollection` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICollection : System.Collections.IEnumerable { void CopyTo(System.Array array, int index); @@ -5697,13 +7321,11 @@ namespace System object SyncRoot { get; } } - // Generated from `System.Collections.IComparer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComparer { int Compare(object x, object y); } - // Generated from `System.Collections.IDictionary` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDictionary : System.Collections.ICollection, System.Collections.IEnumerable { void Add(object key, object value); @@ -5718,7 +7340,6 @@ namespace System System.Collections.ICollection Values { get; } } - // Generated from `System.Collections.IDictionaryEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDictionaryEnumerator : System.Collections.IEnumerator { System.Collections.DictionaryEntry Entry { get; } @@ -5726,13 +7347,11 @@ namespace System object Value { get; } } - // Generated from `System.Collections.IEnumerable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumerable { System.Collections.IEnumerator GetEnumerator(); } - // Generated from `System.Collections.IEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumerator { object Current { get; } @@ -5740,20 +7359,17 @@ namespace System void Reset(); } - // Generated from `System.Collections.IEqualityComparer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEqualityComparer { bool Equals(object x, object y); int GetHashCode(object obj); } - // Generated from `System.Collections.IHashCodeProvider` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IHashCodeProvider { int GetHashCode(object obj); } - // Generated from `System.Collections.IList` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IList : System.Collections.ICollection, System.Collections.IEnumerable { int Add(object value); @@ -5768,13 +7384,11 @@ namespace System void RemoveAt(int index); } - // Generated from `System.Collections.IStructuralComparable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStructuralComparable { int CompareTo(object other, System.Collections.IComparer comparer); } - // Generated from `System.Collections.IStructuralEquatable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStructuralEquatable { bool Equals(object other, System.Collections.IEqualityComparer comparer); @@ -5783,20 +7397,17 @@ namespace System namespace Generic { - // Generated from `System.Collections.Generic.IAsyncEnumerable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAsyncEnumerable { System.Collections.Generic.IAsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `System.Collections.Generic.IAsyncEnumerator<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAsyncEnumerator : System.IAsyncDisposable { T Current { get; } System.Threading.Tasks.ValueTask MoveNextAsync(); } - // Generated from `System.Collections.Generic.ICollection<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { void Add(T item); @@ -5808,13 +7419,11 @@ namespace System bool Remove(T item); } - // Generated from `System.Collections.Generic.IComparer<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IComparer { int Compare(T x, T y); } - // Generated from `System.Collections.Generic.IDictionary<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { void Add(TKey key, TValue value); @@ -5826,26 +7435,22 @@ namespace System System.Collections.Generic.ICollection Values { get; } } - // Generated from `System.Collections.Generic.IEnumerable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumerable : System.Collections.IEnumerable { System.Collections.Generic.IEnumerator GetEnumerator(); } - // Generated from `System.Collections.Generic.IEnumerator<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEnumerator : System.Collections.IEnumerator, System.IDisposable { T Current { get; } } - // Generated from `System.Collections.Generic.IEqualityComparer<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IEqualityComparer { bool Equals(T x, T y); int GetHashCode(T obj); } - // Generated from `System.Collections.Generic.IList<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IList : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { int IndexOf(T item); @@ -5854,13 +7459,11 @@ namespace System void RemoveAt(int index); } - // Generated from `System.Collections.Generic.IReadOnlyCollection<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReadOnlyCollection : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { int Count { get; } } - // Generated from `System.Collections.Generic.IReadOnlyDictionary<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReadOnlyDictionary : System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.IEnumerable { bool ContainsKey(TKey key); @@ -5870,13 +7473,11 @@ namespace System System.Collections.Generic.IEnumerable Values { get; } } - // Generated from `System.Collections.Generic.IReadOnlyList<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReadOnlyList : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { T this[int index] { get; } } - // Generated from `System.Collections.Generic.IReadOnlySet<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReadOnlySet : System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.IEnumerable { bool Contains(T item); @@ -5888,7 +7489,6 @@ namespace System bool SetEquals(System.Collections.Generic.IEnumerable other); } - // Generated from `System.Collections.Generic.ISet<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISet : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { bool Add(T item); @@ -5904,7 +7504,6 @@ namespace System void UnionWith(System.Collections.Generic.IEnumerable other); } - // Generated from `System.Collections.Generic.KeyNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KeyNotFoundException : System.SystemException { public KeyNotFoundException() => throw null; @@ -5913,13 +7512,11 @@ namespace System public KeyNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Collections.Generic.KeyValuePair` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class KeyValuePair { public static System.Collections.Generic.KeyValuePair Create(TKey key, TValue value) => throw null; } - // Generated from `System.Collections.Generic.KeyValuePair<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct KeyValuePair { public void Deconstruct(out TKey key, out TValue value) => throw null; @@ -5933,7 +7530,6 @@ namespace System } namespace ObjectModel { - // Generated from `System.Collections.ObjectModel.Collection<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Collection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { public void Add(T item) => throw null; @@ -5969,7 +7565,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Collections.ObjectModel.ReadOnlyCollection<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReadOnlyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { void System.Collections.Generic.ICollection.Add(T value) => throw null; @@ -6003,11 +7598,84 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } + public class ReadOnlyDictionary : System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyDictionary, System.Collections.ICollection, System.Collections.IDictionary, System.Collections.IEnumerable + { + public class KeyCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable + { + void System.Collections.Generic.ICollection.Add(TKey item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + bool System.Collections.Generic.ICollection.Contains(TKey item) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(TKey[] array, int arrayIndex) => throw null; + public int Count { get => throw null; } + public System.Collections.Generic.IEnumerator GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.ICollection.IsSynchronized { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(TKey item) => throw null; + object System.Collections.ICollection.SyncRoot { get => throw null; } + } + + + public class ValueCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IReadOnlyCollection, System.Collections.ICollection, System.Collections.IEnumerable + { + void System.Collections.Generic.ICollection.Add(TValue item) => throw null; + void System.Collections.Generic.ICollection.Clear() => throw null; + bool System.Collections.Generic.ICollection.Contains(TValue item) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(TValue[] array, int arrayIndex) => throw null; + public int Count { get => throw null; } + public System.Collections.Generic.IEnumerator GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.Generic.ICollection.IsReadOnly { get => throw null; } + bool System.Collections.ICollection.IsSynchronized { get => throw null; } + bool System.Collections.Generic.ICollection.Remove(TValue item) => throw null; + object System.Collections.ICollection.SyncRoot { get => throw null; } + } + + + void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair item) => throw null; + void System.Collections.Generic.IDictionary.Add(TKey key, TValue value) => throw null; + void System.Collections.IDictionary.Add(object key, object value) => throw null; + void System.Collections.Generic.ICollection>.Clear() => throw null; + void System.Collections.IDictionary.Clear() => throw null; + bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair item) => throw null; + bool System.Collections.IDictionary.Contains(object key) => throw null; + public bool ContainsKey(TKey key) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int arrayIndex) => throw null; + public int Count { get => throw null; } + protected System.Collections.Generic.IDictionary Dictionary { get => throw null; } + public System.Collections.Generic.IEnumerator> GetEnumerator() => throw null; + System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + bool System.Collections.IDictionary.IsFixedSize { get => throw null; } + bool System.Collections.Generic.ICollection>.IsReadOnly { get => throw null; } + bool System.Collections.IDictionary.IsReadOnly { get => throw null; } + bool System.Collections.ICollection.IsSynchronized { get => throw null; } + public TValue this[TKey key] { get => throw null; } + TValue System.Collections.Generic.IDictionary.this[TKey key] { get => throw null; set => throw null; } + object System.Collections.IDictionary.this[object key] { get => throw null; set => throw null; } + public System.Collections.ObjectModel.ReadOnlyDictionary.KeyCollection Keys { get => throw null; } + System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Keys { get => throw null; } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Keys { get => throw null; } + System.Collections.ICollection System.Collections.IDictionary.Keys { get => throw null; } + public ReadOnlyDictionary(System.Collections.Generic.IDictionary dictionary) => throw null; + bool System.Collections.Generic.ICollection>.Remove(System.Collections.Generic.KeyValuePair item) => throw null; + bool System.Collections.Generic.IDictionary.Remove(TKey key) => throw null; + void System.Collections.IDictionary.Remove(object key) => throw null; + object System.Collections.ICollection.SyncRoot { get => throw null; } + public bool TryGetValue(TKey key, out TValue value) => throw null; + public System.Collections.ObjectModel.ReadOnlyDictionary.ValueCollection Values { get => throw null; } + System.Collections.Generic.ICollection System.Collections.Generic.IDictionary.Values { get => throw null; } + System.Collections.Generic.IEnumerable System.Collections.Generic.IReadOnlyDictionary.Values { get => throw null; } + System.Collections.ICollection System.Collections.IDictionary.Values { get => throw null; } + } + } } namespace ComponentModel { - // Generated from `System.ComponentModel.DefaultValueAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultValueAttribute : System.Attribute { public DefaultValueAttribute(System.Type type, string value) => throw null; @@ -6031,7 +7699,6 @@ namespace System public virtual object Value { get => throw null; } } - // Generated from `System.ComponentModel.EditorBrowsableAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EditorBrowsableAttribute : System.Attribute { public EditorBrowsableAttribute() => throw null; @@ -6041,7 +7708,6 @@ namespace System public System.ComponentModel.EditorBrowsableState State { get => throw null; } } - // Generated from `System.ComponentModel.EditorBrowsableState` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EditorBrowsableState : int { Advanced = 2, @@ -6054,7 +7720,6 @@ namespace System { namespace Assemblies { - // Generated from `System.Configuration.Assemblies.AssemblyHashAlgorithm` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AssemblyHashAlgorithm : int { MD5 = 32771, @@ -6065,7 +7730,6 @@ namespace System SHA512 = 32782, } - // Generated from `System.Configuration.Assemblies.AssemblyVersionCompatibility` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AssemblyVersionCompatibility : int { SameDomain = 3, @@ -6077,17 +7741,14 @@ namespace System } namespace Diagnostics { - // Generated from `System.Diagnostics.ConditionalAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConditionalAttribute : System.Attribute { public string ConditionString { get => throw null; } public ConditionalAttribute(string conditionString) => throw null; } - // Generated from `System.Diagnostics.Debug` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Debug { - // Generated from `System.Diagnostics.Debug+AssertInterpolatedStringHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AssertInterpolatedStringHandler { public void AppendFormatted(System.ReadOnlySpan value) => throw null; @@ -6105,7 +7766,6 @@ namespace System } - // Generated from `System.Diagnostics.Debug+WriteIfInterpolatedStringHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct WriteIfInterpolatedStringHandler { public void AppendFormatted(System.ReadOnlySpan value) => throw null; @@ -6163,10 +7823,8 @@ namespace System public static void WriteLineIf(bool condition, string message, string category) => throw null; } - // Generated from `System.Diagnostics.DebuggableAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggableAttribute : System.Attribute { - // Generated from `System.Diagnostics.DebuggableAttribute+DebuggingModes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DebuggingModes : int { @@ -6185,7 +7843,6 @@ namespace System public bool IsJITTrackingEnabled { get => throw null; } } - // Generated from `System.Diagnostics.Debugger` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Debugger { public static void Break() => throw null; @@ -6197,14 +7854,12 @@ namespace System public static void NotifyOfCrossThreadDependency() => throw null; } - // Generated from `System.Diagnostics.DebuggerBrowsableAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerBrowsableAttribute : System.Attribute { public DebuggerBrowsableAttribute(System.Diagnostics.DebuggerBrowsableState state) => throw null; public System.Diagnostics.DebuggerBrowsableState State { get => throw null; } } - // Generated from `System.Diagnostics.DebuggerBrowsableState` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DebuggerBrowsableState : int { Collapsed = 2, @@ -6212,7 +7867,6 @@ namespace System RootHidden = 3, } - // Generated from `System.Diagnostics.DebuggerDisplayAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerDisplayAttribute : System.Attribute { public DebuggerDisplayAttribute(string value) => throw null; @@ -6223,31 +7877,26 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Diagnostics.DebuggerHiddenAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerHiddenAttribute : System.Attribute { public DebuggerHiddenAttribute() => throw null; } - // Generated from `System.Diagnostics.DebuggerNonUserCodeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerNonUserCodeAttribute : System.Attribute { public DebuggerNonUserCodeAttribute() => throw null; } - // Generated from `System.Diagnostics.DebuggerStepThroughAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerStepThroughAttribute : System.Attribute { public DebuggerStepThroughAttribute() => throw null; } - // Generated from `System.Diagnostics.DebuggerStepperBoundaryAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerStepperBoundaryAttribute : System.Attribute { public DebuggerStepperBoundaryAttribute() => throw null; } - // Generated from `System.Diagnostics.DebuggerTypeProxyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerTypeProxyAttribute : System.Attribute { public DebuggerTypeProxyAttribute(System.Type type) => throw null; @@ -6257,7 +7906,6 @@ namespace System public string TargetTypeName { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.DebuggerVisualizerAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DebuggerVisualizerAttribute : System.Attribute { public DebuggerVisualizerAttribute(System.Type visualizer) => throw null; @@ -6273,19 +7921,19 @@ namespace System public string VisualizerTypeName { get => throw null; } } - // Generated from `System.Diagnostics.StackTraceHiddenAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StackTraceHiddenAttribute : System.Attribute { public StackTraceHiddenAttribute() => throw null; } - // Generated from `System.Diagnostics.Stopwatch` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Stopwatch { public System.TimeSpan Elapsed { get => throw null; } public System.Int64 ElapsedMilliseconds { get => throw null; } public System.Int64 ElapsedTicks { get => throw null; } public static System.Int64 Frequency; + public static System.TimeSpan GetElapsedTime(System.Int64 startingTimestamp) => throw null; + public static System.TimeSpan GetElapsedTime(System.Int64 startingTimestamp, System.Int64 endingTimestamp) => throw null; public static System.Int64 GetTimestamp() => throw null; public static bool IsHighResolution; public bool IsRunning { get => throw null; } @@ -6297,34 +7945,43 @@ namespace System public Stopwatch() => throw null; } + public class UnreachableException : System.Exception + { + public UnreachableException() => throw null; + public UnreachableException(string message) => throw null; + public UnreachableException(string message, System.Exception innerException) => throw null; + } + namespace CodeAnalysis { - // Generated from `System.Diagnostics.CodeAnalysis.AllowNullAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AllowNullAttribute : System.Attribute + public partial class AllowNullAttribute : System.Attribute { public AllowNullAttribute() => throw null; } - // Generated from `System.Diagnostics.CodeAnalysis.DisallowNullAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class ConstantExpectedAttribute : System.Attribute + { + public ConstantExpectedAttribute() => throw null; + public object Max { get => throw null; set => throw null; } + public object Min { get => throw null; set => throw null; } + } + public class DisallowNullAttribute : System.Attribute { public DisallowNullAttribute() => throw null; } - // Generated from `System.Diagnostics.CodeAnalysis.DoesNotReturnAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DoesNotReturnAttribute : System.Attribute { public DoesNotReturnAttribute() => throw null; } - // Generated from `System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DoesNotReturnIfAttribute : System.Attribute + public partial class DoesNotReturnIfAttribute : System.Attribute { public DoesNotReturnIfAttribute(bool parameterValue) => throw null; public bool ParameterValue { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.DynamicDependencyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DynamicDependencyAttribute : System.Attribute { public string AssemblyName { get => throw null; } @@ -6340,7 +7997,6 @@ namespace System public string TypeName { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes` in `Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DynamicallyAccessedMemberTypes : int { @@ -6362,43 +8018,37 @@ namespace System PublicProperties = 512, } - // Generated from `System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute` in `Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Hosting.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Http, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class DynamicallyAccessedMembersAttribute : System.Attribute + public class DynamicallyAccessedMembersAttribute : System.Attribute { public DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes memberTypes) => throw null; public System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes MemberTypes { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExcludeFromCodeCoverageAttribute : System.Attribute { public ExcludeFromCodeCoverageAttribute() => throw null; public string Justification { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.MaybeNullAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class MaybeNullAttribute : System.Attribute + public partial class MaybeNullAttribute : System.Attribute { public MaybeNullAttribute() => throw null; } - // Generated from `System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MaybeNullWhenAttribute : System.Attribute { public MaybeNullWhenAttribute(bool returnValue) => throw null; public bool ReturnValue { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.MemberNotNullAttribute` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class MemberNotNullAttribute : System.Attribute + public class MemberNotNullAttribute : System.Attribute { public MemberNotNullAttribute(params string[] members) => throw null; public MemberNotNullAttribute(string member) => throw null; public string[] Members { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.MemberNotNullWhenAttribute` in `Microsoft.Extensions.DependencyInjection.Abstractions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class MemberNotNullWhenAttribute : System.Attribute + public class MemberNotNullWhenAttribute : System.Attribute { public MemberNotNullWhenAttribute(bool returnValue, params string[] members) => throw null; public MemberNotNullWhenAttribute(bool returnValue, string member) => throw null; @@ -6406,27 +8056,23 @@ namespace System public bool ReturnValue { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.NotNullAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class NotNullAttribute : System.Attribute + public partial class NotNullAttribute : System.Attribute { public NotNullAttribute() => throw null; } - // Generated from `System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NotNullIfNotNullAttribute : System.Attribute { public NotNullIfNotNullAttribute(string parameterName) => throw null; public string ParameterName { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.NotNullWhenAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class NotNullWhenAttribute : System.Attribute + public partial class NotNullWhenAttribute : System.Attribute { public NotNullWhenAttribute(bool returnValue) => throw null; public bool ReturnValue { get => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RequiresAssemblyFilesAttribute : System.Attribute { public string Message { get => throw null; } @@ -6435,15 +8081,45 @@ namespace System public string Url { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute` in `Microsoft.Extensions.Configuration.Binder, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Logging.Configuration, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.ConfigurationExtensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; Microsoft.Extensions.Options.DataAnnotations, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class RequiresUnreferencedCodeAttribute : System.Attribute + public class RequiresDynamicCodeAttribute : System.Attribute + { + public string Message { get => throw null; } + public RequiresDynamicCodeAttribute(string message) => throw null; + public string Url { get => throw null; set => throw null; } + } + + public class RequiresUnreferencedCodeAttribute : System.Attribute { public string Message { get => throw null; } public RequiresUnreferencedCodeAttribute(string message) => throw null; public string Url { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.SuppressMessageAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class SetsRequiredMembersAttribute : System.Attribute + { + public SetsRequiredMembersAttribute() => throw null; + } + + public class StringSyntaxAttribute : System.Attribute + { + public object[] Arguments { get => throw null; } + public const string CompositeFormat = default; + public const string DateOnlyFormat = default; + public const string DateTimeFormat = default; + public const string EnumFormat = default; + public const string GuidFormat = default; + public const string Json = default; + public const string NumericFormat = default; + public const string Regex = default; + public StringSyntaxAttribute(string syntax) => throw null; + public StringSyntaxAttribute(string syntax, params object[] arguments) => throw null; + public string Syntax { get => throw null; } + public const string TimeOnlyFormat = default; + public const string TimeSpanFormat = default; + public const string Uri = default; + public const string Xml = default; + } + public class SuppressMessageAttribute : System.Attribute { public string Category { get => throw null; } @@ -6455,7 +8131,6 @@ namespace System public string Target { get => throw null; set => throw null; } } - // Generated from `System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessageAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnconditionalSuppressMessageAttribute : System.Attribute { public string Category { get => throw null; } @@ -6467,11 +8142,15 @@ namespace System public UnconditionalSuppressMessageAttribute(string category, string checkId) => throw null; } + public class UnscopedRefAttribute : System.Attribute + { + public UnscopedRefAttribute() => throw null; + } + } } namespace Globalization { - // Generated from `System.Globalization.Calendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Calendar : System.ICloneable { public virtual System.DateTime AddDays(System.DateTime time, int days) => throw null; @@ -6523,7 +8202,6 @@ namespace System public virtual int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.CalendarAlgorithmType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CalendarAlgorithmType : int { LunarCalendar = 2, @@ -6532,7 +8210,6 @@ namespace System Unknown = 0, } - // Generated from `System.Globalization.CalendarWeekRule` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CalendarWeekRule : int { FirstDay = 0, @@ -6540,7 +8217,6 @@ namespace System FirstFullWeek = 1, } - // Generated from `System.Globalization.CharUnicodeInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CharUnicodeInfo { public static int GetDecimalDigitValue(System.Char ch) => throw null; @@ -6554,7 +8230,6 @@ namespace System public static System.Globalization.UnicodeCategory GetUnicodeCategory(string s, int index) => throw null; } - // Generated from `System.Globalization.ChineseLunisolarCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ChineseLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar { public const int ChineseEra = default; @@ -6566,7 +8241,6 @@ namespace System public override System.DateTime MinSupportedDateTime { get => throw null; } } - // Generated from `System.Globalization.CompareInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompareInfo : System.Runtime.Serialization.IDeserializationCallback { public int Compare(System.ReadOnlySpan string1, System.ReadOnlySpan string2, System.Globalization.CompareOptions options = default(System.Globalization.CompareOptions)) => throw null; @@ -6637,7 +8311,6 @@ namespace System public System.Globalization.SortVersion Version { get => throw null; } } - // Generated from `System.Globalization.CompareOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CompareOptions : int { @@ -6652,7 +8325,6 @@ namespace System StringSort = 536870912, } - // Generated from `System.Globalization.CultureInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CultureInfo : System.ICloneable, System.IFormatProvider { public virtual System.Globalization.Calendar Calendar { get => throw null; } @@ -6703,7 +8375,6 @@ namespace System public bool UseUserOverride { get => throw null; } } - // Generated from `System.Globalization.CultureNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CultureNotFoundException : System.ArgumentException { public CultureNotFoundException() => throw null; @@ -6721,7 +8392,6 @@ namespace System public override string Message { get => throw null; } } - // Generated from `System.Globalization.CultureTypes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CultureTypes : int { @@ -6735,7 +8405,6 @@ namespace System WindowsOnlyCultures = 32, } - // Generated from `System.Globalization.DateTimeFormatInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateTimeFormatInfo : System.ICloneable, System.IFormatProvider { public string AMDesignator { get => throw null; set => throw null; } @@ -6784,7 +8453,6 @@ namespace System public string YearMonthPattern { get => throw null; set => throw null; } } - // Generated from `System.Globalization.DateTimeStyles` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum DateTimeStyles : int { @@ -6800,7 +8468,6 @@ namespace System RoundtripKind = 128, } - // Generated from `System.Globalization.DaylightTime` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DaylightTime { public DaylightTime(System.DateTime start, System.DateTime end, System.TimeSpan delta) => throw null; @@ -6809,7 +8476,6 @@ namespace System public System.DateTime Start { get => throw null; } } - // Generated from `System.Globalization.DigitShapes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DigitShapes : int { Context = 0, @@ -6817,7 +8483,6 @@ namespace System None = 1, } - // Generated from `System.Globalization.EastAsianLunisolarCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EastAsianLunisolarCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -6844,13 +8509,11 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.GlobalizationExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class GlobalizationExtensions { public static System.StringComparer GetStringComparer(this System.Globalization.CompareInfo compareInfo, System.Globalization.CompareOptions options) => throw null; } - // Generated from `System.Globalization.GregorianCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GregorianCalendar : System.Globalization.Calendar { public const int ADEra = default; @@ -6881,7 +8544,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.GregorianCalendarTypes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GregorianCalendarTypes : int { Arabic = 10, @@ -6892,7 +8554,6 @@ namespace System USEnglish = 2, } - // Generated from `System.Globalization.HebrewCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HebrewCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -6921,7 +8582,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.HijriCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HijriCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -6952,7 +8612,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.ISOWeek` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ISOWeek { public static int GetWeekOfYear(System.DateTime date) => throw null; @@ -6963,7 +8622,6 @@ namespace System public static System.DateTime ToDateTime(int year, int week, System.DayOfWeek dayOfWeek) => throw null; } - // Generated from `System.Globalization.IdnMapping` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IdnMapping { public bool AllowUnassigned { get => throw null; set => throw null; } @@ -6979,7 +8637,6 @@ namespace System public bool UseStd3AsciiRules { get => throw null; set => throw null; } } - // Generated from `System.Globalization.JapaneseCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class JapaneseCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7008,7 +8665,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.JapaneseLunisolarCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class JapaneseLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar { protected override int DaysInYearBeforeMinSupportedYear { get => throw null; } @@ -7020,7 +8676,6 @@ namespace System public override System.DateTime MinSupportedDateTime { get => throw null; } } - // Generated from `System.Globalization.JulianCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class JulianCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7049,7 +8704,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.KoreanCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KoreanCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7079,7 +8733,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.KoreanLunisolarCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class KoreanLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar { protected override int DaysInYearBeforeMinSupportedYear { get => throw null; } @@ -7091,7 +8744,6 @@ namespace System public override System.DateTime MinSupportedDateTime { get => throw null; } } - // Generated from `System.Globalization.NumberFormatInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NumberFormatInfo : System.ICloneable, System.IFormatProvider { public object Clone() => throw null; @@ -7131,7 +8783,6 @@ namespace System public static System.Globalization.NumberFormatInfo ReadOnly(System.Globalization.NumberFormatInfo nfi) => throw null; } - // Generated from `System.Globalization.NumberStyles` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum NumberStyles : int { @@ -7154,7 +8805,6 @@ namespace System Number = 111, } - // Generated from `System.Globalization.PersianCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PersianCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7183,7 +8833,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.RegionInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegionInfo { public virtual string CurrencyEnglishName { get => throw null; } @@ -7207,7 +8856,6 @@ namespace System public virtual string TwoLetterISORegionName { get => throw null; } } - // Generated from `System.Globalization.SortKey` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortKey { public static int Compare(System.Globalization.SortKey sortkey1, System.Globalization.SortKey sortkey2) => throw null; @@ -7218,7 +8866,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Globalization.SortVersion` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SortVersion : System.IEquatable { public static bool operator !=(System.Globalization.SortVersion left, System.Globalization.SortVersion right) => throw null; @@ -7231,7 +8878,6 @@ namespace System public SortVersion(int fullVersion, System.Guid sortId) => throw null; } - // Generated from `System.Globalization.StringInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringInfo { public override bool Equals(object value) => throw null; @@ -7252,7 +8898,6 @@ namespace System public string SubstringByTextElements(int startingTextElement, int lengthInTextElements) => throw null; } - // Generated from `System.Globalization.TaiwanCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaiwanCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7281,7 +8926,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.TaiwanLunisolarCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaiwanLunisolarCalendar : System.Globalization.EastAsianLunisolarCalendar { protected override int DaysInYearBeforeMinSupportedYear { get => throw null; } @@ -7292,7 +8936,6 @@ namespace System public TaiwanLunisolarCalendar() => throw null; } - // Generated from `System.Globalization.TextElementEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TextElementEnumerator : System.Collections.IEnumerator { public object Current { get => throw null; } @@ -7302,7 +8945,6 @@ namespace System public void Reset() => throw null; } - // Generated from `System.Globalization.TextInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TextInfo : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback { public int ANSICodePage { get => throw null; } @@ -7327,7 +8969,6 @@ namespace System public string ToUpper(string str) => throw null; } - // Generated from `System.Globalization.ThaiBuddhistCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThaiBuddhistCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7357,7 +8998,6 @@ namespace System public override int TwoDigitYearMax { get => throw null; set => throw null; } } - // Generated from `System.Globalization.TimeSpanStyles` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TimeSpanStyles : int { @@ -7365,7 +9005,6 @@ namespace System None = 0, } - // Generated from `System.Globalization.UmAlQuraCalendar` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UmAlQuraCalendar : System.Globalization.Calendar { public override System.DateTime AddMonths(System.DateTime time, int months) => throw null; @@ -7395,7 +9034,6 @@ namespace System public const int UmAlQuraEra = default; } - // Generated from `System.Globalization.UnicodeCategory` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UnicodeCategory : int { ClosePunctuation = 21, @@ -7433,7 +9071,6 @@ namespace System } namespace IO { - // Generated from `System.IO.BinaryReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BinaryReader : System.IDisposable { public virtual System.IO.Stream BaseStream { get => throw null; } @@ -7471,7 +9108,6 @@ namespace System public virtual System.UInt64 ReadUInt64() => throw null; } - // Generated from `System.IO.BinaryWriter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BinaryWriter : System.IAsyncDisposable, System.IDisposable { public virtual System.IO.Stream BaseStream { get => throw null; } @@ -7512,7 +9148,6 @@ namespace System public void Write7BitEncodedInt64(System.Int64 value) => throw null; } - // Generated from `System.IO.BufferedStream` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BufferedStream : System.IO.Stream { public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -7548,11 +9183,12 @@ namespace System public override void WriteByte(System.Byte value) => throw null; } - // Generated from `System.IO.Directory` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Directory { public static System.IO.DirectoryInfo CreateDirectory(string path) => throw null; + public static System.IO.DirectoryInfo CreateDirectory(string path, System.IO.UnixFileMode unixCreateMode) => throw null; public static System.IO.FileSystemInfo CreateSymbolicLink(string path, string pathToTarget) => throw null; + public static System.IO.DirectoryInfo CreateTempSubdirectory(string prefix = default(string)) => throw null; public static void Delete(string path) => throw null; public static void Delete(string path, bool recursive) => throw null; public static System.Collections.Generic.IEnumerable EnumerateDirectories(string path) => throw null; @@ -7601,7 +9237,6 @@ namespace System public static void SetLastWriteTimeUtc(string path, System.DateTime lastWriteTimeUtc) => throw null; } - // Generated from `System.IO.DirectoryInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DirectoryInfo : System.IO.FileSystemInfo { public void Create() => throw null; @@ -7641,7 +9276,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.IO.DirectoryNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DirectoryNotFoundException : System.IO.IOException { public DirectoryNotFoundException() => throw null; @@ -7650,7 +9284,6 @@ namespace System public DirectoryNotFoundException(string message, System.Exception innerException) => throw null; } - // Generated from `System.IO.EndOfStreamException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EndOfStreamException : System.IO.IOException { public EndOfStreamException() => throw null; @@ -7659,7 +9292,6 @@ namespace System public EndOfStreamException(string message, System.Exception innerException) => throw null; } - // Generated from `System.IO.EnumerationOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumerationOptions { public System.IO.FileAttributes AttributesToSkip { get => throw null; set => throw null; } @@ -7673,7 +9305,6 @@ namespace System public bool ReturnSpecialDirectories { get => throw null; set => throw null; } } - // Generated from `System.IO.File` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class File { public static void AppendAllLines(string path, System.Collections.Generic.IEnumerable contents) => throw null; @@ -7696,13 +9327,22 @@ namespace System public static void Delete(string path) => throw null; public static void Encrypt(string path) => throw null; public static bool Exists(string path) => throw null; + public static System.IO.FileAttributes GetAttributes(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.IO.FileAttributes GetAttributes(string path) => throw null; + public static System.DateTime GetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetCreationTime(string path) => throw null; + public static System.DateTime GetCreationTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetCreationTimeUtc(string path) => throw null; + public static System.DateTime GetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetLastAccessTime(string path) => throw null; + public static System.DateTime GetLastAccessTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetLastAccessTimeUtc(string path) => throw null; + public static System.DateTime GetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetLastWriteTime(string path) => throw null; + public static System.DateTime GetLastWriteTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; public static System.DateTime GetLastWriteTimeUtc(string path) => throw null; + public static System.IO.UnixFileMode GetUnixFileMode(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle) => throw null; + public static System.IO.UnixFileMode GetUnixFileMode(string path) => throw null; public static void Move(string sourceFileName, string destFileName) => throw null; public static void Move(string sourceFileName, string destFileName, bool overwrite) => throw null; public static System.IO.FileStream Open(string path, System.IO.FileMode mode) => throw null; @@ -7725,16 +9365,27 @@ namespace System public static System.Threading.Tasks.Task ReadAllTextAsync(string path, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Collections.Generic.IEnumerable ReadLines(string path) => throw null; public static System.Collections.Generic.IEnumerable ReadLines(string path, System.Text.Encoding encoding) => throw null; + public static System.Collections.Generic.IAsyncEnumerable ReadLinesAsync(string path, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Collections.Generic.IAsyncEnumerable ReadLinesAsync(string path, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName) => throw null; public static void Replace(string sourceFileName, string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) => throw null; public static System.IO.FileSystemInfo ResolveLinkTarget(string linkPath, bool returnFinalTarget) => throw null; + public static void SetAttributes(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.IO.FileAttributes fileAttributes) => throw null; public static void SetAttributes(string path, System.IO.FileAttributes fileAttributes) => throw null; + public static void SetCreationTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime creationTime) => throw null; public static void SetCreationTime(string path, System.DateTime creationTime) => throw null; + public static void SetCreationTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime creationTimeUtc) => throw null; public static void SetCreationTimeUtc(string path, System.DateTime creationTimeUtc) => throw null; + public static void SetLastAccessTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime lastAccessTime) => throw null; public static void SetLastAccessTime(string path, System.DateTime lastAccessTime) => throw null; + public static void SetLastAccessTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime lastAccessTimeUtc) => throw null; public static void SetLastAccessTimeUtc(string path, System.DateTime lastAccessTimeUtc) => throw null; + public static void SetLastWriteTime(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime lastWriteTime) => throw null; public static void SetLastWriteTime(string path, System.DateTime lastWriteTime) => throw null; + public static void SetLastWriteTimeUtc(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.DateTime lastWriteTimeUtc) => throw null; public static void SetLastWriteTimeUtc(string path, System.DateTime lastWriteTimeUtc) => throw null; + public static void SetUnixFileMode(Microsoft.Win32.SafeHandles.SafeFileHandle fileHandle, System.IO.UnixFileMode mode) => throw null; + public static void SetUnixFileMode(string path, System.IO.UnixFileMode mode) => throw null; public static void WriteAllBytes(string path, System.Byte[] bytes) => throw null; public static System.Threading.Tasks.Task WriteAllBytesAsync(string path, System.Byte[] bytes, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static void WriteAllLines(string path, System.Collections.Generic.IEnumerable contents) => throw null; @@ -7749,7 +9400,6 @@ namespace System public static System.Threading.Tasks.Task WriteAllTextAsync(string path, string contents, System.Text.Encoding encoding, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.IO.FileAccess` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileAccess : int { @@ -7758,7 +9408,6 @@ namespace System Write = 2, } - // Generated from `System.IO.FileAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileAttributes : int { @@ -7780,7 +9429,6 @@ namespace System Temporary = 256, } - // Generated from `System.IO.FileInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileInfo : System.IO.FileSystemInfo { public System.IO.StreamWriter AppendText() => throw null; @@ -7809,10 +9457,8 @@ namespace System public System.IO.FileStream OpenWrite() => throw null; public System.IO.FileInfo Replace(string destinationFileName, string destinationBackupFileName) => throw null; public System.IO.FileInfo Replace(string destinationFileName, string destinationBackupFileName, bool ignoreMetadataErrors) => throw null; - public override string ToString() => throw null; } - // Generated from `System.IO.FileLoadException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileLoadException : System.IO.IOException { public FileLoadException() => throw null; @@ -7828,7 +9474,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.IO.FileMode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum FileMode : int { Append = 6, @@ -7839,7 +9484,6 @@ namespace System Truncate = 5, } - // Generated from `System.IO.FileNotFoundException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileNotFoundException : System.IO.IOException { public string FileName { get => throw null; } @@ -7855,7 +9499,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.IO.FileOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileOptions : int { @@ -7868,7 +9511,6 @@ namespace System WriteThrough = -2147483648, } - // Generated from `System.IO.FileShare` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FileShare : int { @@ -7880,7 +9522,6 @@ namespace System Write = 2, } - // Generated from `System.IO.FileStream` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileStream : System.IO.Stream { public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -7933,7 +9574,6 @@ namespace System // ERR: Stub generator didn't handle member: ~FileStream } - // Generated from `System.IO.FileStreamOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileStreamOptions { public System.IO.FileAccess Access { get => throw null; set => throw null; } @@ -7943,9 +9583,9 @@ namespace System public System.IO.FileOptions Options { get => throw null; set => throw null; } public System.Int64 PreallocationSize { get => throw null; set => throw null; } public System.IO.FileShare Share { get => throw null; set => throw null; } + public System.IO.UnixFileMode? UnixCreateMode { get => throw null; set => throw null; } } - // Generated from `System.IO.FileSystemInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class FileSystemInfo : System.MarshalByRefObject, System.Runtime.Serialization.ISerializable { public System.IO.FileAttributes Attributes { get => throw null; set => throw null; } @@ -7970,16 +9610,15 @@ namespace System public void Refresh() => throw null; public System.IO.FileSystemInfo ResolveLinkTarget(bool returnFinalTarget) => throw null; public override string ToString() => throw null; + public System.IO.UnixFileMode UnixFileMode { get => throw null; set => throw null; } } - // Generated from `System.IO.HandleInheritability` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum HandleInheritability : int { Inheritable = 1, None = 0, } - // Generated from `System.IO.IOException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IOException : System.SystemException { public IOException() => throw null; @@ -7989,7 +9628,6 @@ namespace System public IOException(string message, int hresult) => throw null; } - // Generated from `System.IO.InvalidDataException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidDataException : System.SystemException { public InvalidDataException() => throw null; @@ -7997,7 +9635,6 @@ namespace System public InvalidDataException(string message, System.Exception innerException) => throw null; } - // Generated from `System.IO.MatchCasing` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MatchCasing : int { CaseInsensitive = 2, @@ -8005,14 +9642,12 @@ namespace System PlatformDefault = 0, } - // Generated from `System.IO.MatchType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MatchType : int { Simple = 0, Win32 = 1, } - // Generated from `System.IO.MemoryStream` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemoryStream : System.IO.Stream { public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -8055,7 +9690,6 @@ namespace System public virtual void WriteTo(System.IO.Stream stream) => throw null; } - // Generated from `System.IO.Path` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Path { public static System.Char AltDirectorySeparatorChar; @@ -8067,6 +9701,7 @@ namespace System public static System.Char DirectorySeparatorChar; public static bool EndsInDirectorySeparator(System.ReadOnlySpan path) => throw null; public static bool EndsInDirectorySeparator(string path) => throw null; + public static bool Exists(string path) => throw null; public static System.ReadOnlySpan GetDirectoryName(System.ReadOnlySpan path) => throw null; public static string GetDirectoryName(string path) => throw null; public static System.ReadOnlySpan GetExtension(System.ReadOnlySpan path) => throw null; @@ -8107,7 +9742,6 @@ namespace System public static System.Char VolumeSeparatorChar; } - // Generated from `System.IO.PathTooLongException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PathTooLongException : System.IO.IOException { public PathTooLongException() => throw null; @@ -8116,7 +9750,6 @@ namespace System public PathTooLongException(string message, System.Exception innerException) => throw null; } - // Generated from `System.IO.RandomAccess` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class RandomAccess { public static System.Int64 GetLength(Microsoft.Win32.SafeHandles.SafeFileHandle handle) => throw null; @@ -8124,20 +9757,19 @@ namespace System public static int Read(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Span buffer, System.Int64 fileOffset) => throw null; public static System.Threading.Tasks.ValueTask ReadAsync(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Collections.Generic.IReadOnlyList> buffers, System.Int64 fileOffset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask ReadAsync(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Memory buffer, System.Int64 fileOffset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static void SetLength(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Int64 length) => throw null; public static void Write(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Collections.Generic.IReadOnlyList> buffers, System.Int64 fileOffset) => throw null; public static void Write(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.ReadOnlySpan buffer, System.Int64 fileOffset) => throw null; public static System.Threading.Tasks.ValueTask WriteAsync(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.Collections.Generic.IReadOnlyList> buffers, System.Int64 fileOffset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask WriteAsync(Microsoft.Win32.SafeHandles.SafeFileHandle handle, System.ReadOnlyMemory buffer, System.Int64 fileOffset, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.IO.SearchOption` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SearchOption : int { AllDirectories = 1, TopDirectoryOnly = 0, } - // Generated from `System.IO.SeekOrigin` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SeekOrigin : int { Begin = 0, @@ -8145,7 +9777,6 @@ namespace System End = 2, } - // Generated from `System.IO.Stream` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Stream : System.MarshalByRefObject, System.IAsyncDisposable, System.IDisposable { public virtual System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; @@ -8179,7 +9810,13 @@ namespace System public System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count) => throw null; public virtual System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; public virtual System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public int ReadAtLeast(System.Span buffer, int minimumBytes, bool throwOnEndOfStream = default(bool)) => throw null; + public System.Threading.Tasks.ValueTask ReadAtLeastAsync(System.Memory buffer, int minimumBytes, bool throwOnEndOfStream = default(bool), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public virtual int ReadByte() => throw null; + public void ReadExactly(System.Byte[] buffer, int offset, int count) => throw null; + public void ReadExactly(System.Span buffer) => throw null; + public System.Threading.Tasks.ValueTask ReadExactlyAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public System.Threading.Tasks.ValueTask ReadExactlyAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public virtual int ReadTimeout { get => throw null; set => throw null; } public abstract System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin); public abstract void SetLength(System.Int64 value); @@ -8196,7 +9833,6 @@ namespace System public virtual int WriteTimeout { get => throw null; set => throw null; } } - // Generated from `System.IO.StreamReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StreamReader : System.IO.TextReader { public virtual System.IO.Stream BaseStream { get => throw null; } @@ -8218,8 +9854,10 @@ namespace System public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public override string ReadLine() => throw null; public override System.Threading.Tasks.Task ReadLineAsync() => throw null; + public override System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) => throw null; public override string ReadToEnd() => throw null; public override System.Threading.Tasks.Task ReadToEndAsync() => throw null; + public override System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) => throw null; public StreamReader(System.IO.Stream stream) => throw null; public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding) => throw null; public StreamReader(System.IO.Stream stream, System.Text.Encoding encoding, bool detectEncodingFromByteOrderMarks) => throw null; @@ -8235,7 +9873,6 @@ namespace System public StreamReader(string path, bool detectEncodingFromByteOrderMarks) => throw null; } - // Generated from `System.IO.StreamWriter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StreamWriter : System.IO.TextWriter { public virtual bool AutoFlush { get => throw null; set => throw null; } @@ -8283,7 +9920,6 @@ namespace System public override System.Threading.Tasks.Task WriteLineAsync(string value) => throw null; } - // Generated from `System.IO.StringReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringReader : System.IO.TextReader { public override void Close() => throw null; @@ -8299,12 +9935,13 @@ namespace System public override System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public override string ReadLine() => throw null; public override System.Threading.Tasks.Task ReadLineAsync() => throw null; + public override System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) => throw null; public override string ReadToEnd() => throw null; public override System.Threading.Tasks.Task ReadToEndAsync() => throw null; + public override System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) => throw null; public StringReader(string s) => throw null; } - // Generated from `System.IO.StringWriter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringWriter : System.IO.TextWriter { public override void Close() => throw null; @@ -8336,7 +9973,6 @@ namespace System public override System.Threading.Tasks.Task WriteLineAsync(string value) => throw null; } - // Generated from `System.IO.TextReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TextReader : System.MarshalByRefObject, System.IDisposable { public virtual void Close() => throw null; @@ -8355,13 +9991,14 @@ namespace System public virtual System.Threading.Tasks.ValueTask ReadBlockAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public virtual string ReadLine() => throw null; public virtual System.Threading.Tasks.Task ReadLineAsync() => throw null; + public virtual System.Threading.Tasks.ValueTask ReadLineAsync(System.Threading.CancellationToken cancellationToken) => throw null; public virtual string ReadToEnd() => throw null; public virtual System.Threading.Tasks.Task ReadToEndAsync() => throw null; + public virtual System.Threading.Tasks.Task ReadToEndAsync(System.Threading.CancellationToken cancellationToken) => throw null; public static System.IO.TextReader Synchronized(System.IO.TextReader reader) => throw null; protected TextReader() => throw null; } - // Generated from `System.IO.TextWriter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TextWriter : System.MarshalByRefObject, System.IAsyncDisposable, System.IDisposable { public virtual void Close() => throw null; @@ -8432,7 +10069,24 @@ namespace System public virtual System.Threading.Tasks.Task WriteLineAsync(string value) => throw null; } - // Generated from `System.IO.UnmanagedMemoryStream` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + [System.Flags] + public enum UnixFileMode : int + { + GroupExecute = 8, + GroupRead = 32, + GroupWrite = 16, + None = 0, + OtherExecute = 1, + OtherRead = 4, + OtherWrite = 2, + SetGroup = 1024, + SetUser = 2048, + StickyBit = 512, + UserExecute = 64, + UserRead = 256, + UserWrite = 128, + } + public class UnmanagedMemoryStream : System.IO.Stream { public override bool CanRead { get => throw null; } @@ -8468,7 +10122,6 @@ namespace System namespace Enumeration { - // Generated from `System.IO.Enumeration.FileSystemEntry` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct FileSystemEntry { public System.IO.FileAttributes Attributes { get => throw null; } @@ -8488,14 +10141,11 @@ namespace System public string ToSpecifiedFullPath() => throw null; } - // Generated from `System.IO.Enumeration.FileSystemEnumerable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FileSystemEnumerable : System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { - // Generated from `System.IO.Enumeration.FileSystemEnumerable<>+FindPredicate` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate bool FindPredicate(ref System.IO.Enumeration.FileSystemEntry entry); - // Generated from `System.IO.Enumeration.FileSystemEnumerable<>+FindTransform` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TResult FindTransform(ref System.IO.Enumeration.FileSystemEntry entry); @@ -8506,7 +10156,6 @@ namespace System public System.IO.Enumeration.FileSystemEnumerable.FindPredicate ShouldRecursePredicate { get => throw null; set => throw null; } } - // Generated from `System.IO.Enumeration.FileSystemEnumerator<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class FileSystemEnumerator : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { protected virtual bool ContinueOnError(int error) => throw null; @@ -8523,7 +10172,6 @@ namespace System protected abstract TResult TransformEntry(ref System.IO.Enumeration.FileSystemEntry entry); } - // Generated from `System.IO.Enumeration.FileSystemName` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class FileSystemName { public static bool MatchesSimpleExpression(System.ReadOnlySpan expression, System.ReadOnlySpan name, bool ignoreCase = default(bool)) => throw null; @@ -8535,7 +10183,6 @@ namespace System } namespace Net { - // Generated from `System.Net.WebUtility` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class WebUtility { public static string HtmlDecode(string value) => throw null; @@ -8551,35 +10198,360 @@ namespace System } namespace Numerics { - // Generated from `System.Numerics.BitOperations` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class BitOperations { + public static bool IsPow2(System.IntPtr value) => throw null; + public static bool IsPow2(System.UIntPtr value) => throw null; public static bool IsPow2(int value) => throw null; public static bool IsPow2(System.Int64 value) => throw null; public static bool IsPow2(System.UInt32 value) => throw null; public static bool IsPow2(System.UInt64 value) => throw null; + public static int LeadingZeroCount(System.UIntPtr value) => throw null; public static int LeadingZeroCount(System.UInt32 value) => throw null; public static int LeadingZeroCount(System.UInt64 value) => throw null; + public static int Log2(System.UIntPtr value) => throw null; public static int Log2(System.UInt32 value) => throw null; public static int Log2(System.UInt64 value) => throw null; + public static int PopCount(System.UIntPtr value) => throw null; public static int PopCount(System.UInt32 value) => throw null; public static int PopCount(System.UInt64 value) => throw null; + public static System.UIntPtr RotateLeft(System.UIntPtr value, int offset) => throw null; public static System.UInt32 RotateLeft(System.UInt32 value, int offset) => throw null; public static System.UInt64 RotateLeft(System.UInt64 value, int offset) => throw null; + public static System.UIntPtr RotateRight(System.UIntPtr value, int offset) => throw null; public static System.UInt32 RotateRight(System.UInt32 value, int offset) => throw null; public static System.UInt64 RotateRight(System.UInt64 value, int offset) => throw null; + public static System.UIntPtr RoundUpToPowerOf2(System.UIntPtr value) => throw null; public static System.UInt32 RoundUpToPowerOf2(System.UInt32 value) => throw null; public static System.UInt64 RoundUpToPowerOf2(System.UInt64 value) => throw null; + public static int TrailingZeroCount(System.IntPtr value) => throw null; + public static int TrailingZeroCount(System.UIntPtr value) => throw null; public static int TrailingZeroCount(int value) => throw null; public static int TrailingZeroCount(System.Int64 value) => throw null; public static int TrailingZeroCount(System.UInt32 value) => throw null; public static int TrailingZeroCount(System.UInt64 value) => throw null; } + public interface IAdditionOperators where TSelf : System.Numerics.IAdditionOperators + { + static abstract TResult operator +(TSelf left, TOther right); + static virtual TResult operator checked +(TSelf left, TOther right) => throw null; + } + + public interface IAdditiveIdentity where TSelf : System.Numerics.IAdditiveIdentity + { + static abstract TResult AdditiveIdentity { get; } + } + + public interface IBinaryFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IFloatingPointIeee754, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryFloatingPointIeee754 + { + } + + public interface IBinaryInteger : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBinaryNumber, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IShiftOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryInteger + { + static virtual (TSelf, TSelf) DivRem(TSelf left, TSelf right) => throw null; + int GetByteCount(); + int GetShortestBitLength(); + static virtual TSelf LeadingZeroCount(TSelf value) => throw null; + static abstract TSelf PopCount(TSelf value); + static virtual TSelf ReadBigEndian(System.Byte[] source, bool isUnsigned) => throw null; + static virtual TSelf ReadBigEndian(System.Byte[] source, int startIndex, bool isUnsigned) => throw null; + static virtual TSelf ReadBigEndian(System.ReadOnlySpan source, bool isUnsigned) => throw null; + static virtual TSelf ReadLittleEndian(System.Byte[] source, bool isUnsigned) => throw null; + static virtual TSelf ReadLittleEndian(System.Byte[] source, int startIndex, bool isUnsigned) => throw null; + static virtual TSelf ReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned) => throw null; + static virtual TSelf RotateLeft(TSelf value, int rotateAmount) => throw null; + static virtual TSelf RotateRight(TSelf value, int rotateAmount) => throw null; + static abstract TSelf TrailingZeroCount(TSelf value); + static abstract bool TryReadBigEndian(System.ReadOnlySpan source, bool isUnsigned, out TSelf value); + static abstract bool TryReadLittleEndian(System.ReadOnlySpan source, bool isUnsigned, out TSelf value); + bool TryWriteBigEndian(System.Span destination, out int bytesWritten); + bool TryWriteLittleEndian(System.Span destination, out int bytesWritten); + int WriteBigEndian(System.Byte[] destination) => throw null; + int WriteBigEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteBigEndian(System.Span destination) => throw null; + int WriteLittleEndian(System.Byte[] destination) => throw null; + int WriteLittleEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteLittleEndian(System.Span destination) => throw null; + } + + public interface IBinaryNumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IBitwiseOperators, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IBinaryNumber + { + static virtual TSelf AllBitsSet { get => throw null; } + static abstract bool IsPow2(TSelf value); + static abstract TSelf Log2(TSelf value); + } + + public interface IBitwiseOperators where TSelf : System.Numerics.IBitwiseOperators + { + static abstract TResult operator &(TSelf left, TOther right); + static abstract TResult operator ^(TSelf left, TOther right); + static abstract TResult operator |(TSelf left, TOther right); + static abstract TResult operator ~(TSelf value); + } + + public interface IComparisonOperators : System.Numerics.IEqualityOperators where TSelf : System.Numerics.IComparisonOperators + { + static abstract TResult operator <(TSelf left, TOther right); + static abstract TResult operator <=(TSelf left, TOther right); + static abstract TResult operator >(TSelf left, TOther right); + static abstract TResult operator >=(TSelf left, TOther right); + } + + public interface IDecrementOperators where TSelf : System.Numerics.IDecrementOperators + { + static abstract TSelf operator --(TSelf value); + static virtual TSelf operator checked --(TSelf value) => throw null; + } + + public interface IDivisionOperators where TSelf : System.Numerics.IDivisionOperators + { + static abstract TResult operator /(TSelf left, TOther right); + static virtual TResult operator checked /(TSelf left, TOther right) => throw null; + } + + public interface IEqualityOperators where TSelf : System.Numerics.IEqualityOperators + { + static abstract TResult operator !=(TSelf left, TOther right); + static abstract TResult operator ==(TSelf left, TOther right); + } + + public interface IExponentialFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IExponentialFunctions + { + static abstract TSelf Exp(TSelf x); + static abstract TSelf Exp10(TSelf x); + static virtual TSelf Exp10M1(TSelf x) => throw null; + static abstract TSelf Exp2(TSelf x); + static virtual TSelf Exp2M1(TSelf x) => throw null; + static virtual TSelf ExpM1(TSelf x) => throw null; + } + + public interface IFloatingPoint : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPoint + { + static virtual TSelf Ceiling(TSelf x) => throw null; + static virtual TSelf Floor(TSelf x) => throw null; + int GetExponentByteCount(); + int GetExponentShortestBitLength(); + int GetSignificandBitLength(); + int GetSignificandByteCount(); + static virtual TSelf Round(TSelf x) => throw null; + static virtual TSelf Round(TSelf x, System.MidpointRounding mode) => throw null; + static virtual TSelf Round(TSelf x, int digits) => throw null; + static abstract TSelf Round(TSelf x, int digits, System.MidpointRounding mode); + static virtual TSelf Truncate(TSelf x) => throw null; + bool TryWriteExponentBigEndian(System.Span destination, out int bytesWritten); + bool TryWriteExponentLittleEndian(System.Span destination, out int bytesWritten); + bool TryWriteSignificandBigEndian(System.Span destination, out int bytesWritten); + bool TryWriteSignificandLittleEndian(System.Span destination, out int bytesWritten); + int WriteExponentBigEndian(System.Byte[] destination) => throw null; + int WriteExponentBigEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteExponentBigEndian(System.Span destination) => throw null; + int WriteExponentLittleEndian(System.Byte[] destination) => throw null; + int WriteExponentLittleEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteExponentLittleEndian(System.Span destination) => throw null; + int WriteSignificandBigEndian(System.Byte[] destination) => throw null; + int WriteSignificandBigEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteSignificandBigEndian(System.Span destination) => throw null; + int WriteSignificandLittleEndian(System.Byte[] destination) => throw null; + int WriteSignificandLittleEndian(System.Byte[] destination, int startIndex) => throw null; + int WriteSignificandLittleEndian(System.Span destination) => throw null; + } + + public interface IFloatingPointConstants : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPointConstants + { + static abstract TSelf E { get; } + static abstract TSelf Pi { get; } + static abstract TSelf Tau { get; } + } + + public interface IFloatingPointIeee754 : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IExponentialFunctions, System.Numerics.IFloatingPoint, System.Numerics.IFloatingPointConstants, System.Numerics.IHyperbolicFunctions, System.Numerics.IIncrementOperators, System.Numerics.ILogarithmicFunctions, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumber, System.Numerics.INumberBase, System.Numerics.IPowerFunctions, System.Numerics.IRootFunctions, System.Numerics.ISignedNumber, System.Numerics.ISubtractionOperators, System.Numerics.ITrigonometricFunctions, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IFloatingPointIeee754 + { + static abstract TSelf Atan2(TSelf y, TSelf x); + static abstract TSelf Atan2Pi(TSelf y, TSelf x); + static abstract TSelf BitDecrement(TSelf x); + static abstract TSelf BitIncrement(TSelf x); + static abstract TSelf Epsilon { get; } + static abstract TSelf FusedMultiplyAdd(TSelf left, TSelf right, TSelf addend); + static abstract int ILogB(TSelf x); + static abstract TSelf Ieee754Remainder(TSelf left, TSelf right); + static abstract TSelf NaN { get; } + static abstract TSelf NegativeInfinity { get; } + static abstract TSelf NegativeZero { get; } + static abstract TSelf PositiveInfinity { get; } + static virtual TSelf ReciprocalEstimate(TSelf x) => throw null; + static virtual TSelf ReciprocalSqrtEstimate(TSelf x) => throw null; + static abstract TSelf ScaleB(TSelf x, int n); + } + + public interface IHyperbolicFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IHyperbolicFunctions + { + static abstract TSelf Acosh(TSelf x); + static abstract TSelf Asinh(TSelf x); + static abstract TSelf Atanh(TSelf x); + static abstract TSelf Cosh(TSelf x); + static abstract TSelf Sinh(TSelf x); + static abstract TSelf Tanh(TSelf x); + } + + public interface IIncrementOperators where TSelf : System.Numerics.IIncrementOperators + { + static abstract TSelf operator ++(TSelf value); + static virtual TSelf operator checked ++(TSelf value) => throw null; + } + + public interface ILogarithmicFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.ILogarithmicFunctions + { + static abstract TSelf Log(TSelf x); + static abstract TSelf Log(TSelf x, TSelf newBase); + static abstract TSelf Log10(TSelf x); + static virtual TSelf Log10P1(TSelf x) => throw null; + static abstract TSelf Log2(TSelf x); + static virtual TSelf Log2P1(TSelf x) => throw null; + static virtual TSelf LogP1(TSelf x) => throw null; + } + + public interface IMinMaxValue where TSelf : System.Numerics.IMinMaxValue + { + static abstract TSelf MaxValue { get; } + static abstract TSelf MinValue { get; } + } + + public interface IModulusOperators where TSelf : System.Numerics.IModulusOperators + { + static abstract TResult operator %(TSelf left, TOther right); + } + + public interface IMultiplicativeIdentity where TSelf : System.Numerics.IMultiplicativeIdentity + { + static abstract TResult MultiplicativeIdentity { get; } + } + + public interface IMultiplyOperators where TSelf : System.Numerics.IMultiplyOperators + { + static abstract TResult operator *(TSelf left, TOther right); + static virtual TResult operator checked *(TSelf left, TOther right) => throw null; + } + + public interface INumber : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IComparisonOperators, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IModulusOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumber + { + static virtual TSelf Clamp(TSelf value, TSelf min, TSelf max) => throw null; + static virtual TSelf CopySign(TSelf value, TSelf sign) => throw null; + static virtual TSelf Max(TSelf x, TSelf y) => throw null; + static virtual TSelf MaxNumber(TSelf x, TSelf y) => throw null; + static virtual TSelf Min(TSelf x, TSelf y) => throw null; + static virtual TSelf MinNumber(TSelf x, TSelf y) => throw null; + static virtual int Sign(TSelf value) => throw null; + } + + public interface INumberBase : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.INumberBase + { + static abstract TSelf Abs(TSelf value); + static virtual TSelf CreateChecked(TOther value) where TOther : System.Numerics.INumberBase => throw null; + static virtual TSelf CreateSaturating(TOther value) where TOther : System.Numerics.INumberBase => throw null; + static virtual TSelf CreateTruncating(TOther value) where TOther : System.Numerics.INumberBase => throw null; + static abstract bool IsCanonical(TSelf value); + static abstract bool IsComplexNumber(TSelf value); + static abstract bool IsEvenInteger(TSelf value); + static abstract bool IsFinite(TSelf value); + static abstract bool IsImaginaryNumber(TSelf value); + static abstract bool IsInfinity(TSelf value); + static abstract bool IsInteger(TSelf value); + static abstract bool IsNaN(TSelf value); + static abstract bool IsNegative(TSelf value); + static abstract bool IsNegativeInfinity(TSelf value); + static abstract bool IsNormal(TSelf value); + static abstract bool IsOddInteger(TSelf value); + static abstract bool IsPositive(TSelf value); + static abstract bool IsPositiveInfinity(TSelf value); + static abstract bool IsRealNumber(TSelf value); + static abstract bool IsSubnormal(TSelf value); + static abstract bool IsZero(TSelf value); + static abstract TSelf MaxMagnitude(TSelf x, TSelf y); + static abstract TSelf MaxMagnitudeNumber(TSelf x, TSelf y); + static abstract TSelf MinMagnitude(TSelf x, TSelf y); + static abstract TSelf MinMagnitudeNumber(TSelf x, TSelf y); + static abstract TSelf One { get; } + static abstract TSelf Parse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider); + static abstract TSelf Parse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider); + static abstract int Radix { get; } + static abstract bool TryConvertFromChecked(TOther value, out TSelf result) where TOther : System.Numerics.INumberBase; + static abstract bool TryConvertFromSaturating(TOther value, out TSelf result) where TOther : System.Numerics.INumberBase; + static abstract bool TryConvertFromTruncating(TOther value, out TSelf result) where TOther : System.Numerics.INumberBase; + static abstract bool TryConvertToChecked(TSelf value, out TOther result) where TOther : System.Numerics.INumberBase; + static abstract bool TryConvertToSaturating(TSelf value, out TOther result) where TOther : System.Numerics.INumberBase; + static abstract bool TryConvertToTruncating(TSelf value, out TOther result) where TOther : System.Numerics.INumberBase; + static abstract bool TryParse(System.ReadOnlySpan s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out TSelf result); + static abstract bool TryParse(string s, System.Globalization.NumberStyles style, System.IFormatProvider provider, out TSelf result); + static abstract TSelf Zero { get; } + } + + public interface IPowerFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IPowerFunctions + { + static abstract TSelf Pow(TSelf x, TSelf y); + } + + public interface IRootFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IRootFunctions + { + static abstract TSelf Cbrt(TSelf x); + static abstract TSelf Hypot(TSelf x, TSelf y); + static abstract TSelf RootN(TSelf x, int n); + static abstract TSelf Sqrt(TSelf x); + } + + public interface IShiftOperators where TSelf : System.Numerics.IShiftOperators + { + static abstract TResult operator <<(TSelf value, TOther shiftAmount); + static abstract TResult operator >>(TSelf value, TOther shiftAmount); + static abstract TResult operator >>>(TSelf value, TOther shiftAmount); + } + + public interface ISignedNumber : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.ISignedNumber + { + static abstract TSelf NegativeOne { get; } + } + + public interface ISubtractionOperators where TSelf : System.Numerics.ISubtractionOperators + { + static abstract TResult operator -(TSelf left, TOther right); + static virtual TResult operator checked -(TSelf left, TOther right) => throw null; + } + + public interface ITrigonometricFunctions : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IFloatingPointConstants, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.ITrigonometricFunctions + { + static abstract TSelf Acos(TSelf x); + static abstract TSelf AcosPi(TSelf x); + static abstract TSelf Asin(TSelf x); + static abstract TSelf AsinPi(TSelf x); + static abstract TSelf Atan(TSelf x); + static abstract TSelf AtanPi(TSelf x); + static abstract TSelf Cos(TSelf x); + static abstract TSelf CosPi(TSelf x); + static abstract TSelf Sin(TSelf x); + static abstract (TSelf, TSelf) SinCos(TSelf x); + static abstract (TSelf, TSelf) SinCosPi(TSelf x); + static abstract TSelf SinPi(TSelf x); + static abstract TSelf Tan(TSelf x); + static abstract TSelf TanPi(TSelf x); + } + + public interface IUnaryNegationOperators where TSelf : System.Numerics.IUnaryNegationOperators + { + static abstract TResult operator -(TSelf value); + static virtual TResult operator checked -(TSelf value) => throw null; + } + + public interface IUnaryPlusOperators where TSelf : System.Numerics.IUnaryPlusOperators + { + static abstract TResult operator +(TSelf value); + } + + public interface IUnsignedNumber : System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.Numerics.IAdditionOperators, System.Numerics.IAdditiveIdentity, System.Numerics.IDecrementOperators, System.Numerics.IDivisionOperators, System.Numerics.IEqualityOperators, System.Numerics.IIncrementOperators, System.Numerics.IMultiplicativeIdentity, System.Numerics.IMultiplyOperators, System.Numerics.INumberBase, System.Numerics.ISubtractionOperators, System.Numerics.IUnaryNegationOperators, System.Numerics.IUnaryPlusOperators where TSelf : System.Numerics.IUnsignedNumber + { + } + } namespace Reflection { - // Generated from `System.Reflection.AmbiguousMatchException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AmbiguousMatchException : System.SystemException { public AmbiguousMatchException() => throw null; @@ -8587,7 +10559,6 @@ namespace System public AmbiguousMatchException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.Assembly` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Assembly : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Reflection.Assembly left, System.Reflection.Assembly right) => throw null; @@ -8667,7 +10638,6 @@ namespace System public static System.Reflection.Assembly UnsafeLoadFrom(string assemblyFile) => throw null; } - // Generated from `System.Reflection.AssemblyAlgorithmIdAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyAlgorithmIdAttribute : System.Attribute { public System.UInt32 AlgorithmId { get => throw null; } @@ -8675,70 +10645,60 @@ namespace System public AssemblyAlgorithmIdAttribute(System.UInt32 algorithmId) => throw null; } - // Generated from `System.Reflection.AssemblyCompanyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyCompanyAttribute : System.Attribute { public AssemblyCompanyAttribute(string company) => throw null; public string Company { get => throw null; } } - // Generated from `System.Reflection.AssemblyConfigurationAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyConfigurationAttribute : System.Attribute { public AssemblyConfigurationAttribute(string configuration) => throw null; public string Configuration { get => throw null; } } - // Generated from `System.Reflection.AssemblyContentType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AssemblyContentType : int { Default = 0, WindowsRuntime = 1, } - // Generated from `System.Reflection.AssemblyCopyrightAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyCopyrightAttribute : System.Attribute { public AssemblyCopyrightAttribute(string copyright) => throw null; public string Copyright { get => throw null; } } - // Generated from `System.Reflection.AssemblyCultureAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyCultureAttribute : System.Attribute { public AssemblyCultureAttribute(string culture) => throw null; public string Culture { get => throw null; } } - // Generated from `System.Reflection.AssemblyDefaultAliasAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyDefaultAliasAttribute : System.Attribute { public AssemblyDefaultAliasAttribute(string defaultAlias) => throw null; public string DefaultAlias { get => throw null; } } - // Generated from `System.Reflection.AssemblyDelaySignAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyDelaySignAttribute : System.Attribute { public AssemblyDelaySignAttribute(bool delaySign) => throw null; public bool DelaySign { get => throw null; } } - // Generated from `System.Reflection.AssemblyDescriptionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyDescriptionAttribute : System.Attribute { public AssemblyDescriptionAttribute(string description) => throw null; public string Description { get => throw null; } } - // Generated from `System.Reflection.AssemblyFileVersionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyFileVersionAttribute : System.Attribute { public AssemblyFileVersionAttribute(string version) => throw null; public string Version { get => throw null; } } - // Generated from `System.Reflection.AssemblyFlagsAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyFlagsAttribute : System.Attribute { public int AssemblyFlags { get => throw null; } @@ -8748,28 +10708,24 @@ namespace System public System.UInt32 Flags { get => throw null; } } - // Generated from `System.Reflection.AssemblyInformationalVersionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyInformationalVersionAttribute : System.Attribute { public AssemblyInformationalVersionAttribute(string informationalVersion) => throw null; public string InformationalVersion { get => throw null; } } - // Generated from `System.Reflection.AssemblyKeyFileAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyKeyFileAttribute : System.Attribute { public AssemblyKeyFileAttribute(string keyFile) => throw null; public string KeyFile { get => throw null; } } - // Generated from `System.Reflection.AssemblyKeyNameAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyKeyNameAttribute : System.Attribute { public AssemblyKeyNameAttribute(string keyName) => throw null; public string KeyName { get => throw null; } } - // Generated from `System.Reflection.AssemblyMetadataAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyMetadataAttribute : System.Attribute { public AssemblyMetadataAttribute(string key, string value) => throw null; @@ -8777,7 +10733,6 @@ namespace System public string Value { get => throw null; } } - // Generated from `System.Reflection.AssemblyName` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyName : System.ICloneable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public AssemblyName() => throw null; @@ -8807,7 +10762,6 @@ namespace System public System.Configuration.Assemblies.AssemblyVersionCompatibility VersionCompatibility { get => throw null; set => throw null; } } - // Generated from `System.Reflection.AssemblyNameFlags` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AssemblyNameFlags : int { @@ -8818,21 +10772,18 @@ namespace System Retargetable = 256, } - // Generated from `System.Reflection.AssemblyNameProxy` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyNameProxy : System.MarshalByRefObject { public AssemblyNameProxy() => throw null; public System.Reflection.AssemblyName GetAssemblyName(string assemblyFile) => throw null; } - // Generated from `System.Reflection.AssemblyProductAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyProductAttribute : System.Attribute { public AssemblyProductAttribute(string product) => throw null; public string Product { get => throw null; } } - // Generated from `System.Reflection.AssemblySignatureKeyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblySignatureKeyAttribute : System.Attribute { public AssemblySignatureKeyAttribute(string publicKey, string countersignature) => throw null; @@ -8840,28 +10791,24 @@ namespace System public string PublicKey { get => throw null; } } - // Generated from `System.Reflection.AssemblyTitleAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyTitleAttribute : System.Attribute { public AssemblyTitleAttribute(string title) => throw null; public string Title { get => throw null; } } - // Generated from `System.Reflection.AssemblyTrademarkAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyTrademarkAttribute : System.Attribute { public AssemblyTrademarkAttribute(string trademark) => throw null; public string Trademark { get => throw null; } } - // Generated from `System.Reflection.AssemblyVersionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyVersionAttribute : System.Attribute { public AssemblyVersionAttribute(string version) => throw null; public string Version { get => throw null; } } - // Generated from `System.Reflection.Binder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Binder { public abstract System.Reflection.FieldInfo BindToField(System.Reflection.BindingFlags bindingAttr, System.Reflection.FieldInfo[] match, object value, System.Globalization.CultureInfo culture); @@ -8873,7 +10820,6 @@ namespace System public abstract System.Reflection.PropertyInfo SelectProperty(System.Reflection.BindingFlags bindingAttr, System.Reflection.PropertyInfo[] match, System.Type returnType, System.Type[] indexes, System.Reflection.ParameterModifier[] modifiers); } - // Generated from `System.Reflection.BindingFlags` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum BindingFlags : int { @@ -8900,7 +10846,6 @@ namespace System SuppressChangeType = 131072, } - // Generated from `System.Reflection.CallingConventions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CallingConventions : int { @@ -8911,7 +10856,6 @@ namespace System VarArgs = 2, } - // Generated from `System.Reflection.ConstructorInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ConstructorInfo : System.Reflection.MethodBase { public static bool operator !=(System.Reflection.ConstructorInfo left, System.Reflection.ConstructorInfo right) => throw null; @@ -8926,7 +10870,6 @@ namespace System public static string TypeConstructorName; } - // Generated from `System.Reflection.CustomAttributeData` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CustomAttributeData { public virtual System.Type AttributeType { get => throw null; } @@ -8943,7 +10886,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.CustomAttributeExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class CustomAttributeExtensions { public static System.Attribute GetCustomAttribute(this System.Reflection.Assembly element, System.Type attributeType) => throw null; @@ -8984,7 +10926,6 @@ namespace System public static bool IsDefined(this System.Reflection.ParameterInfo element, System.Type attributeType, bool inherit) => throw null; } - // Generated from `System.Reflection.CustomAttributeFormatException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CustomAttributeFormatException : System.FormatException { public CustomAttributeFormatException() => throw null; @@ -8993,14 +10934,14 @@ namespace System public CustomAttributeFormatException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.CustomAttributeNamedArgument` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct CustomAttributeNamedArgument + public struct CustomAttributeNamedArgument : System.IEquatable { public static bool operator !=(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) => throw null; public static bool operator ==(System.Reflection.CustomAttributeNamedArgument left, System.Reflection.CustomAttributeNamedArgument right) => throw null; // Stub generator skipped constructor public CustomAttributeNamedArgument(System.Reflection.MemberInfo memberInfo, System.Reflection.CustomAttributeTypedArgument typedArgument) => throw null; public CustomAttributeNamedArgument(System.Reflection.MemberInfo memberInfo, object value) => throw null; + public bool Equals(System.Reflection.CustomAttributeNamedArgument other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; public bool IsField { get => throw null; } @@ -9010,8 +10951,7 @@ namespace System public System.Reflection.CustomAttributeTypedArgument TypedValue { get => throw null; } } - // Generated from `System.Reflection.CustomAttributeTypedArgument` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct CustomAttributeTypedArgument + public struct CustomAttributeTypedArgument : System.IEquatable { public static bool operator !=(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) => throw null; public static bool operator ==(System.Reflection.CustomAttributeTypedArgument left, System.Reflection.CustomAttributeTypedArgument right) => throw null; @@ -9019,20 +10959,19 @@ namespace System // Stub generator skipped constructor public CustomAttributeTypedArgument(System.Type argumentType, object value) => throw null; public CustomAttributeTypedArgument(object value) => throw null; + public bool Equals(System.Reflection.CustomAttributeTypedArgument other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; public override string ToString() => throw null; public object Value { get => throw null; } } - // Generated from `System.Reflection.DefaultMemberAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultMemberAttribute : System.Attribute { public DefaultMemberAttribute(string memberName) => throw null; public string MemberName { get => throw null; } } - // Generated from `System.Reflection.EventAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum EventAttributes : int { @@ -9042,7 +10981,6 @@ namespace System SpecialName = 512, } - // Generated from `System.Reflection.EventInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EventInfo : System.Reflection.MemberInfo { public static bool operator !=(System.Reflection.EventInfo left, System.Reflection.EventInfo right) => throw null; @@ -9070,7 +11008,6 @@ namespace System public virtual System.Reflection.MethodInfo RemoveMethod { get => throw null; } } - // Generated from `System.Reflection.ExceptionHandlingClause` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExceptionHandlingClause { public virtual System.Type CatchType { get => throw null; } @@ -9084,7 +11021,6 @@ namespace System public virtual int TryOffset { get => throw null; } } - // Generated from `System.Reflection.ExceptionHandlingClauseOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ExceptionHandlingClauseOptions : int { @@ -9094,7 +11030,6 @@ namespace System Finally = 2, } - // Generated from `System.Reflection.FieldAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum FieldAttributes : int { @@ -9119,7 +11054,6 @@ namespace System Static = 16, } - // Generated from `System.Reflection.FieldInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class FieldInfo : System.Reflection.MemberInfo { public static bool operator !=(System.Reflection.FieldInfo left, System.Reflection.FieldInfo right) => throw null; @@ -9158,7 +11092,6 @@ namespace System public virtual void SetValueDirect(System.TypedReference obj, object value) => throw null; } - // Generated from `System.Reflection.GenericParameterAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum GenericParameterAttributes : int { @@ -9172,7 +11105,6 @@ namespace System VarianceMask = 3, } - // Generated from `System.Reflection.ICustomAttributeProvider` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICustomAttributeProvider { object[] GetCustomAttributes(System.Type attributeType, bool inherit); @@ -9180,7 +11112,6 @@ namespace System bool IsDefined(System.Type attributeType, bool inherit); } - // Generated from `System.Reflection.IReflect` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReflect { System.Reflection.FieldInfo GetField(string name, System.Reflection.BindingFlags bindingAttr); @@ -9197,13 +11128,11 @@ namespace System System.Type UnderlyingSystemType { get; } } - // Generated from `System.Reflection.IReflectableType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReflectableType { System.Reflection.TypeInfo GetTypeInfo(); } - // Generated from `System.Reflection.ImageFileMachine` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ImageFileMachine : int { AMD64 = 34404, @@ -9212,7 +11141,6 @@ namespace System IA64 = 512, } - // Generated from `System.Reflection.InterfaceMapping` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct InterfaceMapping { // Stub generator skipped constructor @@ -9222,13 +11150,11 @@ namespace System public System.Type TargetType; } - // Generated from `System.Reflection.IntrospectionExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IntrospectionExtensions { public static System.Reflection.TypeInfo GetTypeInfo(this System.Type type) => throw null; } - // Generated from `System.Reflection.InvalidFilterCriteriaException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InvalidFilterCriteriaException : System.ApplicationException { public InvalidFilterCriteriaException() => throw null; @@ -9237,7 +11163,6 @@ namespace System public InvalidFilterCriteriaException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.LocalVariableInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LocalVariableInfo { public virtual bool IsPinned { get => throw null; } @@ -9247,7 +11172,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.ManifestResourceInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ManifestResourceInfo { public virtual string FileName { get => throw null; } @@ -9256,10 +11180,8 @@ namespace System public virtual System.Reflection.ResourceLocation ResourceLocation { get => throw null; } } - // Generated from `System.Reflection.MemberFilter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate bool MemberFilter(System.Reflection.MemberInfo m, object filterCriteria); - // Generated from `System.Reflection.MemberInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MemberInfo : System.Reflection.ICustomAttributeProvider { public static bool operator !=(System.Reflection.MemberInfo left, System.Reflection.MemberInfo right) => throw null; @@ -9282,7 +11204,6 @@ namespace System public abstract System.Type ReflectedType { get; } } - // Generated from `System.Reflection.MemberTypes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MemberTypes : int { @@ -9297,7 +11218,6 @@ namespace System TypeInfo = 32, } - // Generated from `System.Reflection.MethodAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MethodAttributes : int { @@ -9327,7 +11247,6 @@ namespace System VtableLayoutMask = 256, } - // Generated from `System.Reflection.MethodBase` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MethodBase : System.Reflection.MemberInfo { public static bool operator !=(System.Reflection.MethodBase left, System.Reflection.MethodBase right) => throw null; @@ -9370,7 +11289,6 @@ namespace System public virtual System.Reflection.MethodImplAttributes MethodImplementationFlags { get => throw null; } } - // Generated from `System.Reflection.MethodBody` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodBody { public virtual System.Collections.Generic.IList ExceptionHandlingClauses { get => throw null; } @@ -9382,7 +11300,6 @@ namespace System protected MethodBody() => throw null; } - // Generated from `System.Reflection.MethodImplAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MethodImplAttributes : int { AggressiveInlining = 256, @@ -9404,7 +11321,6 @@ namespace System Unmanaged = 4, } - // Generated from `System.Reflection.MethodInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class MethodInfo : System.Reflection.MethodBase { public static bool operator !=(System.Reflection.MethodInfo left, System.Reflection.MethodInfo right) => throw null; @@ -9426,14 +11342,12 @@ namespace System public abstract System.Reflection.ICustomAttributeProvider ReturnTypeCustomAttributes { get; } } - // Generated from `System.Reflection.Missing` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Missing : System.Runtime.Serialization.ISerializable { void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; public static System.Reflection.Missing Value; } - // Generated from `System.Reflection.Module` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Module : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Reflection.Module left, System.Reflection.Module right) => throw null; @@ -9487,10 +11401,8 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.ModuleResolveEventHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate System.Reflection.Module ModuleResolveEventHandler(object sender, System.ResolveEventArgs e); - // Generated from `System.Reflection.NullabilityInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NullabilityInfo { public System.Reflection.NullabilityInfo ElementType { get => throw null; } @@ -9500,7 +11412,6 @@ namespace System public System.Reflection.NullabilityState WriteState { get => throw null; } } - // Generated from `System.Reflection.NullabilityInfoContext` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NullabilityInfoContext { public System.Reflection.NullabilityInfo Create(System.Reflection.EventInfo eventInfo) => throw null; @@ -9510,7 +11421,6 @@ namespace System public NullabilityInfoContext() => throw null; } - // Generated from `System.Reflection.NullabilityState` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NullabilityState : int { NotNull = 1, @@ -9518,7 +11428,6 @@ namespace System Unknown = 0, } - // Generated from `System.Reflection.ObfuscateAssemblyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObfuscateAssemblyAttribute : System.Attribute { public bool AssemblyIsPrivate { get => throw null; } @@ -9526,7 +11435,6 @@ namespace System public bool StripAfterObfuscation { get => throw null; set => throw null; } } - // Generated from `System.Reflection.ObfuscationAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObfuscationAttribute : System.Attribute { public bool ApplyToMembers { get => throw null; set => throw null; } @@ -9536,7 +11444,6 @@ namespace System public bool StripAfterObfuscation { get => throw null; set => throw null; } } - // Generated from `System.Reflection.ParameterAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ParameterAttributes : int { @@ -9553,7 +11460,6 @@ namespace System Retval = 8, } - // Generated from `System.Reflection.ParameterInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParameterInfo : System.Reflection.ICustomAttributeProvider, System.Runtime.Serialization.IObjectReference { public virtual System.Reflection.ParameterAttributes Attributes { get => throw null; } @@ -9588,7 +11494,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Reflection.ParameterModifier` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParameterModifier { public bool this[int index] { get => throw null; set => throw null; } @@ -9596,7 +11501,6 @@ namespace System public ParameterModifier(int parameterCount) => throw null; } - // Generated from `System.Reflection.Pointer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Pointer : System.Runtime.Serialization.ISerializable { unsafe public static object Box(void* ptr, System.Type type) => throw null; @@ -9606,7 +11510,6 @@ namespace System unsafe public static void* Unbox(object ptr) => throw null; } - // Generated from `System.Reflection.PortableExecutableKinds` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PortableExecutableKinds : int { @@ -9618,7 +11521,6 @@ namespace System Unmanaged32Bit = 8, } - // Generated from `System.Reflection.ProcessorArchitecture` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ProcessorArchitecture : int { Amd64 = 4, @@ -9629,7 +11531,6 @@ namespace System X86 = 2, } - // Generated from `System.Reflection.PropertyAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PropertyAttributes : int { @@ -9643,7 +11544,6 @@ namespace System SpecialName = 512, } - // Generated from `System.Reflection.PropertyInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class PropertyInfo : System.Reflection.MemberInfo { public static bool operator !=(System.Reflection.PropertyInfo left, System.Reflection.PropertyInfo right) => throw null; @@ -9678,7 +11578,6 @@ namespace System public virtual void SetValue(object obj, object value, object[] index) => throw null; } - // Generated from `System.Reflection.ReflectionContext` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ReflectionContext { public virtual System.Reflection.TypeInfo GetTypeForObject(object value) => throw null; @@ -9687,7 +11586,6 @@ namespace System protected ReflectionContext() => throw null; } - // Generated from `System.Reflection.ReflectionTypeLoadException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReflectionTypeLoadException : System.SystemException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -9699,7 +11597,6 @@ namespace System public System.Type[] Types { get => throw null; } } - // Generated from `System.Reflection.ResourceAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ResourceAttributes : int { @@ -9707,7 +11604,6 @@ namespace System Public = 1, } - // Generated from `System.Reflection.ResourceLocation` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ResourceLocation : int { @@ -9716,7 +11612,6 @@ namespace System Embedded = 1, } - // Generated from `System.Reflection.RuntimeReflectionExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class RuntimeReflectionExtensions { public static System.Reflection.MethodInfo GetMethodInfo(this System.Delegate del) => throw null; @@ -9732,7 +11627,6 @@ namespace System public static System.Reflection.PropertyInfo GetRuntimeProperty(this System.Type type, string name) => throw null; } - // Generated from `System.Reflection.StrongNameKeyPair` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StrongNameKeyPair : System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -9744,7 +11638,6 @@ namespace System public StrongNameKeyPair(string keyPairContainer) => throw null; } - // Generated from `System.Reflection.TargetException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TargetException : System.ApplicationException { public TargetException() => throw null; @@ -9753,14 +11646,12 @@ namespace System public TargetException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.TargetInvocationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TargetInvocationException : System.ApplicationException { public TargetInvocationException(System.Exception inner) => throw null; public TargetInvocationException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.TargetParameterCountException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TargetParameterCountException : System.ApplicationException { public TargetParameterCountException() => throw null; @@ -9768,7 +11659,6 @@ namespace System public TargetParameterCountException(string message, System.Exception inner) => throw null; } - // Generated from `System.Reflection.TypeAttributes` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TypeAttributes : int { @@ -9806,7 +11696,6 @@ namespace System WindowsRuntime = 16384, } - // Generated from `System.Reflection.TypeDelegator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeDelegator : System.Reflection.TypeInfo { public override System.Reflection.Assembly Assembly { get => throw null; } @@ -9829,6 +11718,7 @@ namespace System public override System.Reflection.InterfaceMapping GetInterfaceMap(System.Type interfaceType) => throw null; public override System.Type[] GetInterfaces() => throw null; public override System.Reflection.MemberInfo[] GetMember(string name, System.Reflection.MemberTypes type, System.Reflection.BindingFlags bindingAttr) => throw null; + public override System.Reflection.MemberInfo GetMemberWithSameMetadataDefinitionAs(System.Reflection.MemberInfo member) => throw null; public override System.Reflection.MemberInfo[] GetMembers(System.Reflection.BindingFlags bindingAttr) => throw null; protected override System.Reflection.MethodInfo GetMethodImpl(string name, System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, System.Reflection.CallingConventions callConvention, System.Type[] types, System.Reflection.ParameterModifier[] modifiers) => throw null; public override System.Reflection.MethodInfo[] GetMethods(System.Reflection.BindingFlags bindingAttr) => throw null; @@ -9865,10 +11755,8 @@ namespace System protected System.Type typeImpl; } - // Generated from `System.Reflection.TypeFilter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate bool TypeFilter(System.Type m, object filterCriteria); - // Generated from `System.Reflection.TypeInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TypeInfo : System.Type, System.Reflection.IReflectableType { public virtual System.Type AsType() => throw null; @@ -9895,14 +11783,12 @@ namespace System } namespace Resources { - // Generated from `System.Resources.IResourceReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IResourceReader : System.Collections.IEnumerable, System.IDisposable { void Close(); System.Collections.IDictionaryEnumerator GetEnumerator(); } - // Generated from `System.Resources.MissingManifestResourceException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingManifestResourceException : System.SystemException { public MissingManifestResourceException() => throw null; @@ -9911,7 +11797,6 @@ namespace System public MissingManifestResourceException(string message, System.Exception inner) => throw null; } - // Generated from `System.Resources.MissingSatelliteAssemblyException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MissingSatelliteAssemblyException : System.SystemException { public string CultureName { get => throw null; } @@ -9922,7 +11807,6 @@ namespace System public MissingSatelliteAssemblyException(string message, string cultureName) => throw null; } - // Generated from `System.Resources.NeutralResourcesLanguageAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NeutralResourcesLanguageAttribute : System.Attribute { public string CultureName { get => throw null; } @@ -9931,7 +11815,6 @@ namespace System public NeutralResourcesLanguageAttribute(string cultureName, System.Resources.UltimateResourceFallbackLocation location) => throw null; } - // Generated from `System.Resources.ResourceManager` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceManager { public virtual string BaseName { get => throw null; } @@ -9960,7 +11843,6 @@ namespace System public virtual System.Type ResourceSetType { get => throw null; } } - // Generated from `System.Resources.ResourceReader` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceReader : System.Collections.IEnumerable, System.IDisposable, System.Resources.IResourceReader { public void Close() => throw null; @@ -9972,7 +11854,6 @@ namespace System public ResourceReader(string fileName) => throw null; } - // Generated from `System.Resources.ResourceSet` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceSet : System.Collections.IEnumerable, System.IDisposable { public virtual void Close() => throw null; @@ -9993,14 +11874,12 @@ namespace System public ResourceSet(string fileName) => throw null; } - // Generated from `System.Resources.SatelliteContractVersionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SatelliteContractVersionAttribute : System.Attribute { public SatelliteContractVersionAttribute(string version) => throw null; public string Version { get => throw null; } } - // Generated from `System.Resources.UltimateResourceFallbackLocation` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum UltimateResourceFallbackLocation : int { MainAssembly = 0, @@ -10010,7 +11889,6 @@ namespace System } namespace Runtime { - // Generated from `System.Runtime.AmbiguousImplementationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AmbiguousImplementationException : System.Exception { public AmbiguousImplementationException() => throw null; @@ -10018,14 +11896,17 @@ namespace System public AmbiguousImplementationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Runtime.AssemblyTargetedPatchBandAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AssemblyTargetedPatchBandAttribute : System.Attribute { public AssemblyTargetedPatchBandAttribute(string targetedPatchBand) => throw null; public string TargetedPatchBand { get => throw null; } } - // Generated from `System.Runtime.DependentHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public static class ControlledExecution + { + public static void Run(System.Action action, System.Threading.CancellationToken cancellationToken) => throw null; + } + public struct DependentHandle : System.IDisposable { public object Dependent { get => throw null; set => throw null; } @@ -10037,14 +11918,12 @@ namespace System public (object, object) TargetAndDependent { get => throw null; } } - // Generated from `System.Runtime.GCLargeObjectHeapCompactionMode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCLargeObjectHeapCompactionMode : int { CompactOnce = 2, Default = 1, } - // Generated from `System.Runtime.GCLatencyMode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCLatencyMode : int { Batch = 0, @@ -10054,7 +11933,6 @@ namespace System SustainedLowLatency = 3, } - // Generated from `System.Runtime.GCSettings` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class GCSettings { public static bool IsServerGC { get => throw null; } @@ -10062,7 +11940,6 @@ namespace System public static System.Runtime.GCLatencyMode LatencyMode { get => throw null; set => throw null; } } - // Generated from `System.Runtime.JitInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class JitInfo { public static System.TimeSpan GetCompilationTime(bool currentThread = default(bool)) => throw null; @@ -10070,7 +11947,6 @@ namespace System public static System.Int64 GetCompiledMethodCount(bool currentThread = default(bool)) => throw null; } - // Generated from `System.Runtime.MemoryFailPoint` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MemoryFailPoint : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable { public void Dispose() => throw null; @@ -10078,14 +11954,12 @@ namespace System // ERR: Stub generator didn't handle member: ~MemoryFailPoint } - // Generated from `System.Runtime.ProfileOptimization` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ProfileOptimization { public static void SetProfileRoot(string directoryPath) => throw null; public static void StartProfile(string profile) => throw null; } - // Generated from `System.Runtime.TargetedPatchingOptOutAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TargetedPatchingOptOutAttribute : System.Attribute { public string Reason { get => throw null; } @@ -10094,14 +11968,12 @@ namespace System namespace CompilerServices { - // Generated from `System.Runtime.CompilerServices.AccessedThroughPropertyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AccessedThroughPropertyAttribute : System.Attribute { public AccessedThroughPropertyAttribute(string propertyName) => throw null; public string PropertyName { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncIteratorMethodBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncIteratorMethodBuilder { // Stub generator skipped constructor @@ -10112,26 +11984,22 @@ namespace System public void MoveNext(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine => throw null; } - // Generated from `System.Runtime.CompilerServices.AsyncIteratorStateMachineAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncIteratorStateMachineAttribute : System.Runtime.CompilerServices.StateMachineAttribute { public AsyncIteratorStateMachineAttribute(System.Type stateMachineType) : base(default(System.Type)) => throw null; } - // Generated from `System.Runtime.CompilerServices.AsyncMethodBuilderAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncMethodBuilderAttribute : System.Attribute { public AsyncMethodBuilderAttribute(System.Type builderType) => throw null; public System.Type BuilderType { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncStateMachineAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncStateMachineAttribute : System.Runtime.CompilerServices.StateMachineAttribute { public AsyncStateMachineAttribute(System.Type stateMachineType) : base(default(System.Type)) => throw null; } - // Generated from `System.Runtime.CompilerServices.AsyncTaskMethodBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncTaskMethodBuilder { // Stub generator skipped constructor @@ -10145,7 +12013,6 @@ namespace System public System.Threading.Tasks.Task Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncTaskMethodBuilder<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncTaskMethodBuilder { // Stub generator skipped constructor @@ -10159,7 +12026,6 @@ namespace System public System.Threading.Tasks.Task Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncValueTaskMethodBuilder { // Stub generator skipped constructor @@ -10173,7 +12039,6 @@ namespace System public System.Threading.Tasks.ValueTask Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncValueTaskMethodBuilder<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncValueTaskMethodBuilder { // Stub generator skipped constructor @@ -10187,7 +12052,6 @@ namespace System public System.Threading.Tasks.ValueTask Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.AsyncVoidMethodBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncVoidMethodBuilder { // Stub generator skipped constructor @@ -10200,75 +12064,63 @@ namespace System public void Start(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvCdecl` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvCdecl { public CallConvCdecl() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvFastcall` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvFastcall { public CallConvFastcall() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvMemberFunction` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvMemberFunction { public CallConvMemberFunction() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvStdcall` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvStdcall { public CallConvStdcall() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvSuppressGCTransition` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvSuppressGCTransition { public CallConvSuppressGCTransition() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallConvThiscall` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallConvThiscall { public CallConvThiscall() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallerArgumentExpressionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallerArgumentExpressionAttribute : System.Attribute { public CallerArgumentExpressionAttribute(string parameterName) => throw null; public string ParameterName { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.CallerFilePathAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallerFilePathAttribute : System.Attribute { public CallerFilePathAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallerLineNumberAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallerLineNumberAttribute : System.Attribute { public CallerLineNumberAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.CallerMemberNameAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CallerMemberNameAttribute : System.Attribute { public CallerMemberNameAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.CompilationRelaxations` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CompilationRelaxations : int { NoStringInterning = 8, } - // Generated from `System.Runtime.CompilerServices.CompilationRelaxationsAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompilationRelaxationsAttribute : System.Attribute { public int CompilationRelaxations { get => throw null; } @@ -10276,22 +12128,27 @@ namespace System public CompilationRelaxationsAttribute(int relaxations) => throw null; } - // Generated from `System.Runtime.CompilerServices.CompilerGeneratedAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class CompilerFeatureRequiredAttribute : System.Attribute + { + public CompilerFeatureRequiredAttribute(string featureName) => throw null; + public string FeatureName { get => throw null; } + public bool IsOptional { get => throw null; set => throw null; } + public const string RefStructs = default; + public const string RequiredMembers = default; + } + public class CompilerGeneratedAttribute : System.Attribute { public CompilerGeneratedAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.CompilerGlobalScopeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompilerGlobalScopeAttribute : System.Attribute { public CompilerGlobalScopeAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.ConditionalWeakTable<,>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConditionalWeakTable : System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable where TKey : class where TValue : class { - // Generated from `System.Runtime.CompilerServices.ConditionalWeakTable<,>+CreateValueCallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate TValue CreateValueCallback(TKey key); @@ -10304,20 +12161,18 @@ namespace System public TValue GetOrCreateValue(TKey key) => throw null; public TValue GetValue(TKey key, System.Runtime.CompilerServices.ConditionalWeakTable.CreateValueCallback createValueCallback) => throw null; public bool Remove(TKey key) => throw null; + public bool TryAdd(TKey key, TValue value) => throw null; public bool TryGetValue(TKey key, out TValue value) => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredAsyncDisposable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredAsyncDisposable { // Stub generator skipped constructor public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable DisposeAsync() => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredCancelableAsyncEnumerable { - // Generated from `System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<>+Enumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Enumerator { public T Current { get => throw null; } @@ -10333,10 +12188,8 @@ namespace System public System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable WithCancellation(System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredTaskAwaitable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredTaskAwaitable { - // Generated from `System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { // Stub generator skipped constructor @@ -10351,10 +12204,8 @@ namespace System public System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredTaskAwaitable { - // Generated from `System.Runtime.CompilerServices.ConfiguredTaskAwaitable<>+ConfiguredTaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { // Stub generator skipped constructor @@ -10369,10 +12220,8 @@ namespace System public System.Runtime.CompilerServices.ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredValueTaskAwaitable { - // Generated from `System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable+ConfiguredValueTaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { // Stub generator skipped constructor @@ -10387,10 +12236,8 @@ namespace System public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter GetAwaiter() => throw null; } - // Generated from `System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredValueTaskAwaitable { - // Generated from `System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable<>+ConfiguredValueTaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ConfiguredValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { // Stub generator skipped constructor @@ -10405,21 +12252,18 @@ namespace System public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter GetAwaiter() => throw null; } - // Generated from `System.Runtime.CompilerServices.CustomConstantAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CustomConstantAttribute : System.Attribute { protected CustomConstantAttribute() => throw null; public abstract object Value { get; } } - // Generated from `System.Runtime.CompilerServices.DateTimeConstantAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DateTimeConstantAttribute : System.Runtime.CompilerServices.CustomConstantAttribute { public DateTimeConstantAttribute(System.Int64 ticks) => throw null; public override object Value { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.DecimalConstantAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecimalConstantAttribute : System.Attribute { public DecimalConstantAttribute(System.Byte scale, System.Byte sign, int hi, int mid, int low) => throw null; @@ -10427,14 +12271,12 @@ namespace System public System.Decimal Value { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.DefaultDependencyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DefaultDependencyAttribute : System.Attribute { public DefaultDependencyAttribute(System.Runtime.CompilerServices.LoadHint loadHintArgument) => throw null; public System.Runtime.CompilerServices.LoadHint LoadHint { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.DefaultInterpolatedStringHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DefaultInterpolatedStringHandler { public void AppendFormatted(System.ReadOnlySpan value) => throw null; @@ -10455,7 +12297,6 @@ namespace System public string ToStringAndClear() => throw null; } - // Generated from `System.Runtime.CompilerServices.DependencyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DependencyAttribute : System.Attribute { public DependencyAttribute(string dependentAssemblyArgument, System.Runtime.CompilerServices.LoadHint loadHintArgument) => throw null; @@ -10463,37 +12304,36 @@ namespace System public System.Runtime.CompilerServices.LoadHint LoadHint { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.DisablePrivateReflectionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DisablePrivateReflectionAttribute : System.Attribute { public DisablePrivateReflectionAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.DiscardableAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class DisableRuntimeMarshallingAttribute : System.Attribute + { + public DisableRuntimeMarshallingAttribute() => throw null; + } + public class DiscardableAttribute : System.Attribute { public DiscardableAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.EnumeratorCancellationAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EnumeratorCancellationAttribute : System.Attribute { public EnumeratorCancellationAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.ExtensionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExtensionAttribute : System.Attribute { public ExtensionAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.FixedAddressValueTypeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FixedAddressValueTypeAttribute : System.Attribute { public FixedAddressValueTypeAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.FixedBufferAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FixedBufferAttribute : System.Attribute { public System.Type ElementType { get => throw null; } @@ -10501,51 +12341,43 @@ namespace System public int Length { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.FormattableStringFactory` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class FormattableStringFactory { public static System.FormattableString Create(string format, params object[] arguments) => throw null; } - // Generated from `System.Runtime.CompilerServices.IAsyncStateMachine` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IAsyncStateMachine { void MoveNext(); void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine); } - // Generated from `System.Runtime.CompilerServices.ICriticalNotifyCompletion` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ICriticalNotifyCompletion : System.Runtime.CompilerServices.INotifyCompletion { void UnsafeOnCompleted(System.Action continuation); } - // Generated from `System.Runtime.CompilerServices.INotifyCompletion` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface INotifyCompletion { void OnCompleted(System.Action continuation); } - // Generated from `System.Runtime.CompilerServices.IStrongBox` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStrongBox { object Value { get; set; } } - // Generated from `System.Runtime.CompilerServices.ITuple` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITuple { object this[int index] { get; } int Length { get; } } - // Generated from `System.Runtime.CompilerServices.IndexerNameAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IndexerNameAttribute : System.Attribute { public IndexerNameAttribute(string indexerName) => throw null; } - // Generated from `System.Runtime.CompilerServices.InternalsVisibleToAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InternalsVisibleToAttribute : System.Attribute { public bool AllInternalsVisible { get => throw null; set => throw null; } @@ -10553,7 +12385,6 @@ namespace System public InternalsVisibleToAttribute(string assemblyName) => throw null; } - // Generated from `System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InterpolatedStringHandlerArgumentAttribute : System.Attribute { public string[] Arguments { get => throw null; } @@ -10561,46 +12392,38 @@ namespace System public InterpolatedStringHandlerArgumentAttribute(string argument) => throw null; } - // Generated from `System.Runtime.CompilerServices.InterpolatedStringHandlerAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InterpolatedStringHandlerAttribute : System.Attribute { public InterpolatedStringHandlerAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.IsByRefLikeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IsByRefLikeAttribute : System.Attribute { public IsByRefLikeAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.IsConst` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsConst { } - // Generated from `System.Runtime.CompilerServices.IsExternalInit` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsExternalInit { } - // Generated from `System.Runtime.CompilerServices.IsReadOnlyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class IsReadOnlyAttribute : System.Attribute + public partial class IsReadOnlyAttribute : System.Attribute { public IsReadOnlyAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.IsVolatile` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class IsVolatile { } - // Generated from `System.Runtime.CompilerServices.IteratorStateMachineAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IteratorStateMachineAttribute : System.Runtime.CompilerServices.StateMachineAttribute { public IteratorStateMachineAttribute(System.Type stateMachineType) : base(default(System.Type)) => throw null; } - // Generated from `System.Runtime.CompilerServices.LoadHint` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LoadHint : int { Always = 1, @@ -10608,7 +12431,6 @@ namespace System Sometimes = 2, } - // Generated from `System.Runtime.CompilerServices.MethodCodeType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum MethodCodeType : int { IL = 0, @@ -10617,7 +12439,6 @@ namespace System Runtime = 3, } - // Generated from `System.Runtime.CompilerServices.MethodImplAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MethodImplAttribute : System.Attribute { public System.Runtime.CompilerServices.MethodCodeType MethodCodeType; @@ -10627,7 +12448,6 @@ namespace System public System.Runtime.CompilerServices.MethodImplOptions Value { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.MethodImplOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum MethodImplOptions : int { @@ -10642,13 +12462,11 @@ namespace System Unmanaged = 4, } - // Generated from `System.Runtime.CompilerServices.ModuleInitializerAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ModuleInitializerAttribute : System.Attribute { public ModuleInitializerAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PoolingAsyncValueTaskMethodBuilder { public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine => throw null; @@ -10662,7 +12480,6 @@ namespace System public System.Threading.Tasks.ValueTask Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct PoolingAsyncValueTaskMethodBuilder { public void AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : System.Runtime.CompilerServices.INotifyCompletion where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine => throw null; @@ -10676,13 +12493,11 @@ namespace System public System.Threading.Tasks.ValueTask Task { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.PreserveBaseOverridesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PreserveBaseOverridesAttribute : System.Attribute { public PreserveBaseOverridesAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.ReferenceAssemblyAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReferenceAssemblyAttribute : System.Attribute { public string Description { get => throw null; } @@ -10690,38 +12505,41 @@ namespace System public ReferenceAssemblyAttribute(string description) => throw null; } - // Generated from `System.Runtime.CompilerServices.RuntimeCompatibilityAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class RequiredMemberAttribute : System.Attribute + { + public RequiredMemberAttribute() => throw null; + } + public class RuntimeCompatibilityAttribute : System.Attribute { public RuntimeCompatibilityAttribute() => throw null; public bool WrapNonExceptionThrows { get => throw null; set => throw null; } } - // Generated from `System.Runtime.CompilerServices.RuntimeFeature` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class RuntimeFeature { + public const string ByRefFields = default; public const string CovariantReturnsOfClasses = default; public const string DefaultImplementationsOfInterfaces = default; public static bool IsDynamicCodeCompiled { get => throw null; } public static bool IsDynamicCodeSupported { get => throw null; } public static bool IsSupported(string feature) => throw null; + public const string NumericIntPtr = default; public const string PortablePdb = default; public const string UnmanagedSignatureCallingConvention = default; public const string VirtualStaticsInInterfaces = default; } - // Generated from `System.Runtime.CompilerServices.RuntimeHelpers` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class RuntimeHelpers { - // Generated from `System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void CleanupCode(object userData, bool exceptionThrown); - // Generated from `System.Runtime.CompilerServices.RuntimeHelpers+TryCode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void TryCode(object userData); public static System.IntPtr AllocateTypeAssociatedMemory(System.Type type, int size) => throw null; + public static System.ReadOnlySpan CreateSpan(System.RuntimeFieldHandle fldHandle) => throw null; public static void EnsureSufficientExecutionStack() => throw null; public static bool Equals(object o1, object o2) => throw null; public static void ExecuteCodeWithGuaranteedCleanup(System.Runtime.CompilerServices.RuntimeHelpers.TryCode code, System.Runtime.CompilerServices.RuntimeHelpers.CleanupCode backoutCode, object userData) => throw null; @@ -10744,7 +12562,6 @@ namespace System public static bool TryEnsureSufficientExecutionStack() => throw null; } - // Generated from `System.Runtime.CompilerServices.RuntimeWrappedException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RuntimeWrappedException : System.Exception { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -10752,32 +12569,27 @@ namespace System public object WrappedException { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.SkipLocalsInitAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SkipLocalsInitAttribute : System.Attribute { public SkipLocalsInitAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.SpecialNameAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SpecialNameAttribute : System.Attribute { public SpecialNameAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.StateMachineAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StateMachineAttribute : System.Attribute { public StateMachineAttribute(System.Type stateMachineType) => throw null; public System.Type StateMachineType { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.StringFreezingAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringFreezingAttribute : System.Attribute { public StringFreezingAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.StrongBox<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StrongBox : System.Runtime.CompilerServices.IStrongBox { public StrongBox() => throw null; @@ -10786,13 +12598,11 @@ namespace System object System.Runtime.CompilerServices.IStrongBox.Value { get => throw null; set => throw null; } } - // Generated from `System.Runtime.CompilerServices.SuppressIldasmAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SuppressIldasmAttribute : System.Attribute { public SuppressIldasmAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.SwitchExpressionException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SwitchExpressionException : System.InvalidOperationException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -10805,7 +12615,6 @@ namespace System public object UnmatchedValue { get => throw null; } } - // Generated from `System.Runtime.CompilerServices.TaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { public void GetResult() => throw null; @@ -10815,7 +12624,6 @@ namespace System public void UnsafeOnCompleted(System.Action continuation) => throw null; } - // Generated from `System.Runtime.CompilerServices.TaskAwaiter<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct TaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { public TResult GetResult() => throw null; @@ -10825,34 +12633,75 @@ namespace System public void UnsafeOnCompleted(System.Action continuation) => throw null; } - // Generated from `System.Runtime.CompilerServices.TupleElementNamesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TupleElementNamesAttribute : System.Attribute { public System.Collections.Generic.IList TransformNames { get => throw null; } public TupleElementNamesAttribute(string[] transformNames) => throw null; } - // Generated from `System.Runtime.CompilerServices.TypeForwardedFromAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeForwardedFromAttribute : System.Attribute { public string AssemblyFullName { get => throw null; } public TypeForwardedFromAttribute(string assemblyFullName) => throw null; } - // Generated from `System.Runtime.CompilerServices.TypeForwardedToAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TypeForwardedToAttribute : System.Attribute { public System.Type Destination { get => throw null; } public TypeForwardedToAttribute(System.Type destination) => throw null; } - // Generated from `System.Runtime.CompilerServices.UnsafeValueTypeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public static class Unsafe + { + unsafe public static void* Add(void* source, int elementOffset) => throw null; + public static T Add(ref T source, System.IntPtr elementOffset) => throw null; + public static T Add(ref T source, System.UIntPtr elementOffset) => throw null; + public static T Add(ref T source, int elementOffset) => throw null; + public static T AddByteOffset(ref T source, System.IntPtr byteOffset) => throw null; + public static T AddByteOffset(ref T source, System.UIntPtr byteOffset) => throw null; + public static bool AreSame(ref T left, ref T right) => throw null; + public static T As(object o) where T : class => throw null; + public static TTo As(ref TFrom source) => throw null; + unsafe public static void* AsPointer(ref T value) => throw null; + public static T AsRef(T source) => throw null; + unsafe public static T AsRef(void* source) => throw null; + public static System.IntPtr ByteOffset(ref T origin, ref T target) => throw null; + unsafe public static void Copy(void* destination, ref T source) => throw null; + unsafe public static void Copy(ref T destination, void* source) => throw null; + unsafe public static void CopyBlock(void* destination, void* source, System.UInt32 byteCount) => throw null; + public static void CopyBlock(ref System.Byte destination, ref System.Byte source, System.UInt32 byteCount) => throw null; + unsafe public static void CopyBlockUnaligned(void* destination, void* source, System.UInt32 byteCount) => throw null; + public static void CopyBlockUnaligned(ref System.Byte destination, ref System.Byte source, System.UInt32 byteCount) => throw null; + unsafe public static void InitBlock(void* startAddress, System.Byte value, System.UInt32 byteCount) => throw null; + public static void InitBlock(ref System.Byte startAddress, System.Byte value, System.UInt32 byteCount) => throw null; + unsafe public static void InitBlockUnaligned(void* startAddress, System.Byte value, System.UInt32 byteCount) => throw null; + public static void InitBlockUnaligned(ref System.Byte startAddress, System.Byte value, System.UInt32 byteCount) => throw null; + public static bool IsAddressGreaterThan(ref T left, ref T right) => throw null; + public static bool IsAddressLessThan(ref T left, ref T right) => throw null; + public static bool IsNullRef(ref T source) => throw null; + public static T NullRef() => throw null; + unsafe public static T Read(void* source) => throw null; + unsafe public static T ReadUnaligned(void* source) => throw null; + public static T ReadUnaligned(ref System.Byte source) => throw null; + public static int SizeOf() => throw null; + public static void SkipInit(out T value) => throw null; + unsafe public static void* Subtract(void* source, int elementOffset) => throw null; + public static T Subtract(ref T source, System.IntPtr elementOffset) => throw null; + public static T Subtract(ref T source, System.UIntPtr elementOffset) => throw null; + public static T Subtract(ref T source, int elementOffset) => throw null; + public static T SubtractByteOffset(ref T source, System.IntPtr byteOffset) => throw null; + public static T SubtractByteOffset(ref T source, System.UIntPtr byteOffset) => throw null; + public static T Unbox(object box) where T : struct => throw null; + unsafe public static void Write(void* destination, T value) => throw null; + unsafe public static void WriteUnaligned(void* destination, T value) => throw null; + public static void WriteUnaligned(ref System.Byte destination, T value) => throw null; + } + public class UnsafeValueTypeAttribute : System.Attribute { public UnsafeValueTypeAttribute() => throw null; } - // Generated from `System.Runtime.CompilerServices.ValueTaskAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { public void GetResult() => throw null; @@ -10862,7 +12711,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Runtime.CompilerServices.ValueTaskAwaiter<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { public TResult GetResult() => throw null; @@ -10872,10 +12720,8 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Runtime.CompilerServices.YieldAwaitable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct YieldAwaitable { - // Generated from `System.Runtime.CompilerServices.YieldAwaitable+YieldAwaiter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct YieldAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion { public void GetResult() => throw null; @@ -10893,7 +12739,6 @@ namespace System } namespace ConstrainedExecution { - // Generated from `System.Runtime.ConstrainedExecution.Cer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Cer : int { MayFail = 1, @@ -10901,7 +12746,6 @@ namespace System Success = 2, } - // Generated from `System.Runtime.ConstrainedExecution.Consistency` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Consistency : int { MayCorruptAppDomain = 1, @@ -10910,20 +12754,17 @@ namespace System WillNotCorruptState = 3, } - // Generated from `System.Runtime.ConstrainedExecution.CriticalFinalizerObject` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CriticalFinalizerObject { protected CriticalFinalizerObject() => throw null; // ERR: Stub generator didn't handle member: ~CriticalFinalizerObject } - // Generated from `System.Runtime.ConstrainedExecution.PrePrepareMethodAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PrePrepareMethodAttribute : System.Attribute { public PrePrepareMethodAttribute() => throw null; } - // Generated from `System.Runtime.ConstrainedExecution.ReliabilityContractAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReliabilityContractAttribute : System.Attribute { public System.Runtime.ConstrainedExecution.Cer Cer { get => throw null; } @@ -10934,7 +12775,6 @@ namespace System } namespace ExceptionServices { - // Generated from `System.Runtime.ExceptionServices.ExceptionDispatchInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExceptionDispatchInfo { public static System.Runtime.ExceptionServices.ExceptionDispatchInfo Capture(System.Exception source) => throw null; @@ -10945,14 +12785,12 @@ namespace System public static void Throw(System.Exception source) => throw null; } - // Generated from `System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FirstChanceExceptionEventArgs : System.EventArgs { public System.Exception Exception { get => throw null; } public FirstChanceExceptionEventArgs(System.Exception exception) => throw null; } - // Generated from `System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HandleProcessCorruptedStateExceptionsAttribute : System.Attribute { public HandleProcessCorruptedStateExceptionsAttribute() => throw null; @@ -10961,7 +12799,19 @@ namespace System } namespace InteropServices { - // Generated from `System.Runtime.InteropServices.CharSet` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public enum Architecture : int + { + Arm = 2, + Arm64 = 3, + Armv6 = 7, + LoongArch64 = 6, + Ppc64le = 8, + S390x = 5, + Wasm = 4, + X64 = 1, + X86 = 0, + } + public enum CharSet : int { Ansi = 2, @@ -10970,14 +12820,12 @@ namespace System Unicode = 3, } - // Generated from `System.Runtime.InteropServices.ComVisibleAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComVisibleAttribute : System.Attribute { public ComVisibleAttribute(bool visibility) => throw null; public bool Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.CriticalHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CriticalHandle : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable { public void Close() => throw null; @@ -10993,7 +12841,6 @@ namespace System // ERR: Stub generator didn't handle member: ~CriticalHandle } - // Generated from `System.Runtime.InteropServices.ExternalException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExternalException : System.SystemException { public virtual int ErrorCode { get => throw null; } @@ -11005,21 +12852,20 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Runtime.InteropServices.FieldOffsetAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FieldOffsetAttribute : System.Attribute { public FieldOffsetAttribute(int offset) => throw null; public int Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.GCHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct GCHandle + public struct GCHandle : System.IEquatable { public static bool operator !=(System.Runtime.InteropServices.GCHandle a, System.Runtime.InteropServices.GCHandle b) => throw null; public static bool operator ==(System.Runtime.InteropServices.GCHandle a, System.Runtime.InteropServices.GCHandle b) => throw null; public System.IntPtr AddrOfPinnedObject() => throw null; public static System.Runtime.InteropServices.GCHandle Alloc(object value) => throw null; public static System.Runtime.InteropServices.GCHandle Alloc(object value, System.Runtime.InteropServices.GCHandleType type) => throw null; + public bool Equals(System.Runtime.InteropServices.GCHandle other) => throw null; public override bool Equals(object o) => throw null; public void Free() => throw null; public static System.Runtime.InteropServices.GCHandle FromIntPtr(System.IntPtr value) => throw null; @@ -11032,7 +12878,6 @@ namespace System public static explicit operator System.Runtime.InteropServices.GCHandle(System.IntPtr value) => throw null; } - // Generated from `System.Runtime.InteropServices.GCHandleType` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum GCHandleType : int { Normal = 2, @@ -11041,13 +12886,11 @@ namespace System WeakTrackResurrection = 1, } - // Generated from `System.Runtime.InteropServices.InAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class InAttribute : System.Attribute { public InAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.LayoutKind` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LayoutKind : int { Auto = 3, @@ -11055,13 +12898,37 @@ namespace System Sequential = 0, } - // Generated from `System.Runtime.InteropServices.OutAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public struct OSPlatform : System.IEquatable + { + public static bool operator !=(System.Runtime.InteropServices.OSPlatform left, System.Runtime.InteropServices.OSPlatform right) => throw null; + public static bool operator ==(System.Runtime.InteropServices.OSPlatform left, System.Runtime.InteropServices.OSPlatform right) => throw null; + public static System.Runtime.InteropServices.OSPlatform Create(string osPlatform) => throw null; + public bool Equals(System.Runtime.InteropServices.OSPlatform other) => throw null; + public override bool Equals(object obj) => throw null; + public static System.Runtime.InteropServices.OSPlatform FreeBSD { get => throw null; } + public override int GetHashCode() => throw null; + public static System.Runtime.InteropServices.OSPlatform Linux { get => throw null; } + // Stub generator skipped constructor + public static System.Runtime.InteropServices.OSPlatform OSX { get => throw null; } + public override string ToString() => throw null; + public static System.Runtime.InteropServices.OSPlatform Windows { get => throw null; } + } + public class OutAttribute : System.Attribute { public OutAttribute() => throw null; } - // Generated from `System.Runtime.InteropServices.SafeBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public static class RuntimeInformation + { + public static string FrameworkDescription { get => throw null; } + public static bool IsOSPlatform(System.Runtime.InteropServices.OSPlatform osPlatform) => throw null; + public static System.Runtime.InteropServices.Architecture OSArchitecture { get => throw null; } + public static string OSDescription { get => throw null; } + public static System.Runtime.InteropServices.Architecture ProcessArchitecture { get => throw null; } + public static string RuntimeIdentifier { get => throw null; } + } + public abstract class SafeBuffer : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { unsafe public void AcquirePointer(ref System.Byte* pointer) => throw null; @@ -11079,7 +12946,6 @@ namespace System public void WriteSpan(System.UInt64 byteOffset, System.ReadOnlySpan data) where T : struct => throw null; } - // Generated from `System.Runtime.InteropServices.SafeHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SafeHandle : System.Runtime.ConstrainedExecution.CriticalFinalizerObject, System.IDisposable { public void Close() => throw null; @@ -11098,7 +12964,6 @@ namespace System // ERR: Stub generator didn't handle member: ~SafeHandle } - // Generated from `System.Runtime.InteropServices.StructLayoutAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StructLayoutAttribute : System.Attribute { public System.Runtime.InteropServices.CharSet CharSet; @@ -11109,16 +12974,149 @@ namespace System public System.Runtime.InteropServices.LayoutKind Value { get => throw null; } } - // Generated from `System.Runtime.InteropServices.SuppressGCTransitionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SuppressGCTransitionAttribute : System.Attribute { public SuppressGCTransitionAttribute() => throw null; } + public enum UnmanagedType : int + { + AnsiBStr = 35, + AsAny = 40, + BStr = 19, + Bool = 2, + ByValArray = 30, + ByValTStr = 23, + Currency = 15, + CustomMarshaler = 44, + Error = 45, + FunctionPtr = 38, + HString = 47, + I1 = 3, + I2 = 5, + I4 = 7, + I8 = 9, + IDispatch = 26, + IInspectable = 46, + IUnknown = 25, + Interface = 28, + LPArray = 42, + LPStr = 20, + LPStruct = 43, + LPTStr = 22, + LPUTF8Str = 48, + LPWStr = 21, + R4 = 11, + R8 = 12, + SafeArray = 29, + Struct = 27, + SysInt = 31, + SysUInt = 32, + TBStr = 36, + U1 = 4, + U2 = 6, + U4 = 8, + U8 = 10, + VBByRefStr = 34, + VariantBool = 37, + } + + namespace Marshalling + { + public class ContiguousCollectionMarshallerAttribute : System.Attribute + { + public ContiguousCollectionMarshallerAttribute() => throw null; + } + + public class CustomMarshallerAttribute : System.Attribute + { + public struct GenericPlaceholder + { + // Stub generator skipped constructor + } + + + public CustomMarshallerAttribute(System.Type managedType, System.Runtime.InteropServices.Marshalling.MarshalMode marshalMode, System.Type marshallerType) => throw null; + public System.Type ManagedType { get => throw null; } + public System.Runtime.InteropServices.Marshalling.MarshalMode MarshalMode { get => throw null; } + public System.Type MarshallerType { get => throw null; } + } + + public enum MarshalMode : int + { + Default = 0, + ElementIn = 7, + ElementOut = 9, + ElementRef = 8, + ManagedToUnmanagedIn = 1, + ManagedToUnmanagedOut = 3, + ManagedToUnmanagedRef = 2, + UnmanagedToManagedIn = 4, + UnmanagedToManagedOut = 6, + UnmanagedToManagedRef = 5, + } + + public class NativeMarshallingAttribute : System.Attribute + { + public NativeMarshallingAttribute(System.Type nativeType) => throw null; + public System.Type NativeType { get => throw null; } + } + + public static class ReadOnlySpanMarshaller where TUnmanagedElement : unmanaged + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(System.ReadOnlySpan managed, System.Span buffer) => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public TUnmanagedElement GetPinnableReference() => throw null; + public static T GetPinnableReference(System.ReadOnlySpan managed) => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + // Stub generator skipped constructor + unsafe public TUnmanagedElement* ToUnmanaged() => throw null; + } + + + public static class UnmanagedToManagedOut + { + unsafe public static TUnmanagedElement* AllocateContainerForUnmanagedElements(System.ReadOnlySpan managed, out int numElements) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(System.ReadOnlySpan managed) => throw null; + unsafe public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) => throw null; + } + + + } + + public static class SpanMarshaller where TUnmanagedElement : unmanaged + { + public struct ManagedToUnmanagedIn + { + public static int BufferSize { get => throw null; } + public void Free() => throw null; + public void FromManaged(System.Span managed, System.Span buffer) => throw null; + public System.ReadOnlySpan GetManagedValuesSource() => throw null; + public TUnmanagedElement GetPinnableReference() => throw null; + public static T GetPinnableReference(System.Span managed) => throw null; + public System.Span GetUnmanagedValuesDestination() => throw null; + // Stub generator skipped constructor + unsafe public TUnmanagedElement* ToUnmanaged() => throw null; + } + + + unsafe public static System.Span AllocateContainerForManagedElements(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static TUnmanagedElement* AllocateContainerForUnmanagedElements(System.Span managed, out int numElements) => throw null; + unsafe public static void Free(TUnmanagedElement* unmanaged) => throw null; + public static System.Span GetManagedValuesDestination(System.Span managed) => throw null; + public static System.ReadOnlySpan GetManagedValuesSource(System.Span managed) => throw null; + unsafe public static System.Span GetUnmanagedValuesDestination(TUnmanagedElement* unmanaged, int numElements) => throw null; + unsafe public static System.ReadOnlySpan GetUnmanagedValuesSource(TUnmanagedElement* unmanaged, int numElements) => throw null; + } + + } } namespace Remoting { - // Generated from `System.Runtime.Remoting.ObjectHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectHandle : System.MarshalByRefObject { public ObjectHandle(object o) => throw null; @@ -11128,13 +13126,11 @@ namespace System } namespace Serialization { - // Generated from `System.Runtime.Serialization.IDeserializationCallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDeserializationCallback { void OnDeserialization(object sender); } - // Generated from `System.Runtime.Serialization.IFormatterConverter` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IFormatterConverter { object Convert(object value, System.Type type); @@ -11156,63 +13152,53 @@ namespace System System.UInt64 ToUInt64(object value); } - // Generated from `System.Runtime.Serialization.IObjectReference` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IObjectReference { object GetRealObject(System.Runtime.Serialization.StreamingContext context); } - // Generated from `System.Runtime.Serialization.ISafeSerializationData` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISafeSerializationData { void CompleteDeserialization(object deserialized); } - // Generated from `System.Runtime.Serialization.ISerializable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISerializable { void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context); } - // Generated from `System.Runtime.Serialization.OnDeserializedAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OnDeserializedAttribute : System.Attribute { public OnDeserializedAttribute() => throw null; } - // Generated from `System.Runtime.Serialization.OnDeserializingAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OnDeserializingAttribute : System.Attribute { public OnDeserializingAttribute() => throw null; } - // Generated from `System.Runtime.Serialization.OnSerializedAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OnSerializedAttribute : System.Attribute { public OnSerializedAttribute() => throw null; } - // Generated from `System.Runtime.Serialization.OnSerializingAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OnSerializingAttribute : System.Attribute { public OnSerializingAttribute() => throw null; } - // Generated from `System.Runtime.Serialization.OptionalFieldAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class OptionalFieldAttribute : System.Attribute { public OptionalFieldAttribute() => throw null; public int VersionAdded { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Serialization.SafeSerializationEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeSerializationEventArgs : System.EventArgs { public void AddSerializedState(System.Runtime.Serialization.ISafeSerializationData serializedState) => throw null; public System.Runtime.Serialization.StreamingContext StreamingContext { get => throw null; } } - // Generated from `System.Runtime.Serialization.SerializationEntry` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SerializationEntry { public string Name { get => throw null; } @@ -11221,7 +13207,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Runtime.Serialization.SerializationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SerializationException : System.SystemException { public SerializationException() => throw null; @@ -11230,7 +13215,6 @@ namespace System public SerializationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Runtime.Serialization.SerializationInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SerializationInfo { public void AddValue(string name, System.DateTime value) => throw null; @@ -11277,7 +13261,6 @@ namespace System public void SetType(System.Type type) => throw null; } - // Generated from `System.Runtime.Serialization.SerializationInfoEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SerializationInfoEnumerator : System.Collections.IEnumerator { public System.Runtime.Serialization.SerializationEntry Current { get => throw null; } @@ -11289,7 +13272,6 @@ namespace System public object Value { get => throw null; } } - // Generated from `System.Runtime.Serialization.StreamingContext` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct StreamingContext { public object Context { get => throw null; } @@ -11301,7 +13283,6 @@ namespace System public StreamingContext(System.Runtime.Serialization.StreamingContextStates state, object additional) => throw null; } - // Generated from `System.Runtime.Serialization.StreamingContextStates` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum StreamingContextStates : int { @@ -11319,14 +13300,12 @@ namespace System } namespace Versioning { - // Generated from `System.Runtime.Versioning.ComponentGuaranteesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ComponentGuaranteesAttribute : System.Attribute { public ComponentGuaranteesAttribute(System.Runtime.Versioning.ComponentGuaranteesOptions guarantees) => throw null; public System.Runtime.Versioning.ComponentGuaranteesOptions Guarantees { get => throw null; } } - // Generated from `System.Runtime.Versioning.ComponentGuaranteesOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ComponentGuaranteesOptions : int { @@ -11336,7 +13315,6 @@ namespace System Stable = 2, } - // Generated from `System.Runtime.Versioning.FrameworkName` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class FrameworkName : System.IEquatable { public static bool operator !=(System.Runtime.Versioning.FrameworkName left, System.Runtime.Versioning.FrameworkName right) => throw null; @@ -11354,14 +13332,20 @@ namespace System public System.Version Version { get => throw null; } } - // Generated from `System.Runtime.Versioning.OSPlatformAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Drawing.Common, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract partial class OSPlatformAttribute : System.Attribute + public abstract class OSPlatformAttribute : System.Attribute { protected private OSPlatformAttribute(string platformName) => throw null; public string PlatformName { get => throw null; } } - // Generated from `System.Runtime.Versioning.RequiresPreviewFeaturesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class ObsoletedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute + { + public string Message { get => throw null; } + public ObsoletedOSPlatformAttribute(string platformName) : base(default(string)) => throw null; + public ObsoletedOSPlatformAttribute(string platformName, string message) : base(default(string)) => throw null; + public string Url { get => throw null; set => throw null; } + } + public class RequiresPreviewFeaturesAttribute : System.Attribute { public string Message { get => throw null; } @@ -11370,7 +13354,6 @@ namespace System public string Url { get => throw null; set => throw null; } } - // Generated from `System.Runtime.Versioning.ResourceConsumptionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceConsumptionAttribute : System.Attribute { public System.Runtime.Versioning.ResourceScope ConsumptionScope { get => throw null; } @@ -11379,14 +13362,12 @@ namespace System public System.Runtime.Versioning.ResourceScope ResourceScope { get => throw null; } } - // Generated from `System.Runtime.Versioning.ResourceExposureAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ResourceExposureAttribute : System.Attribute { public ResourceExposureAttribute(System.Runtime.Versioning.ResourceScope exposureLevel) => throw null; public System.Runtime.Versioning.ResourceScope ResourceExposureLevel { get => throw null; } } - // Generated from `System.Runtime.Versioning.ResourceScope` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ResourceScope : int { @@ -11399,19 +13380,16 @@ namespace System Process = 2, } - // Generated from `System.Runtime.Versioning.SupportedOSPlatformAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Drawing.Common, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class SupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute + public class SupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute { public SupportedOSPlatformAttribute(string platformName) : base(default(string)) => throw null; } - // Generated from `System.Runtime.Versioning.SupportedOSPlatformGuardAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class SupportedOSPlatformGuardAttribute : System.Runtime.Versioning.OSPlatformAttribute + public class SupportedOSPlatformGuardAttribute : System.Runtime.Versioning.OSPlatformAttribute { public SupportedOSPlatformGuardAttribute(string platformName) : base(default(string)) => throw null; } - // Generated from `System.Runtime.Versioning.TargetFrameworkAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TargetFrameworkAttribute : System.Attribute { public string FrameworkDisplayName { get => throw null; set => throw null; } @@ -11419,25 +13397,23 @@ namespace System public TargetFrameworkAttribute(string frameworkName) => throw null; } - // Generated from `System.Runtime.Versioning.TargetPlatformAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Drawing.Common, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class TargetPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute + public class TargetPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute { public TargetPlatformAttribute(string platformName) : base(default(string)) => throw null; } - // Generated from `System.Runtime.Versioning.UnsupportedOSPlatformAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Drawing.Common, Version=5.0.0.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class UnsupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute + public class UnsupportedOSPlatformAttribute : System.Runtime.Versioning.OSPlatformAttribute { + public string Message { get => throw null; } public UnsupportedOSPlatformAttribute(string platformName) : base(default(string)) => throw null; + public UnsupportedOSPlatformAttribute(string platformName, string message) : base(default(string)) => throw null; } - // Generated from `System.Runtime.Versioning.UnsupportedOSPlatformGuardAttribute` in `Microsoft.Extensions.Hosting, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public partial class UnsupportedOSPlatformGuardAttribute : System.Runtime.Versioning.OSPlatformAttribute + public class UnsupportedOSPlatformGuardAttribute : System.Runtime.Versioning.OSPlatformAttribute { public UnsupportedOSPlatformGuardAttribute(string platformName) : base(default(string)) => throw null; } - // Generated from `System.Runtime.Versioning.VersioningHelper` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class VersioningHelper { public static string MakeVersionSafeName(string name, System.Runtime.Versioning.ResourceScope from, System.Runtime.Versioning.ResourceScope to) => throw null; @@ -11448,14 +13424,12 @@ namespace System } namespace Security { - // Generated from `System.Security.AllowPartiallyTrustedCallersAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AllowPartiallyTrustedCallersAttribute : System.Attribute { public AllowPartiallyTrustedCallersAttribute() => throw null; public System.Security.PartialTrustVisibilityLevel PartialTrustVisibilityLevel { get => throw null; set => throw null; } } - // Generated from `System.Security.IPermission` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IPermission : System.Security.ISecurityEncodable { System.Security.IPermission Copy(); @@ -11465,14 +13439,12 @@ namespace System System.Security.IPermission Union(System.Security.IPermission target); } - // Generated from `System.Security.ISecurityEncodable` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISecurityEncodable { void FromXml(System.Security.SecurityElement e); System.Security.SecurityElement ToXml(); } - // Generated from `System.Security.IStackWalk` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IStackWalk { void Assert(); @@ -11481,14 +13453,12 @@ namespace System void PermitOnly(); } - // Generated from `System.Security.PartialTrustVisibilityLevel` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PartialTrustVisibilityLevel : int { NotVisibleByDefault = 1, VisibleToAllHosts = 0, } - // Generated from `System.Security.PermissionSet` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PermissionSet : System.Collections.ICollection, System.Collections.IEnumerable, System.Runtime.Serialization.IDeserializationCallback, System.Security.ISecurityEncodable, System.Security.IStackWalk { public System.Security.IPermission AddPermission(System.Security.IPermission perm) => throw null; @@ -11529,7 +13499,6 @@ namespace System public System.Security.PermissionSet Union(System.Security.PermissionSet other) => throw null; } - // Generated from `System.Security.SecurityCriticalAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityCriticalAttribute : System.Attribute { public System.Security.SecurityCriticalScope Scope { get => throw null; } @@ -11537,14 +13506,12 @@ namespace System public SecurityCriticalAttribute(System.Security.SecurityCriticalScope scope) => throw null; } - // Generated from `System.Security.SecurityCriticalScope` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SecurityCriticalScope : int { Everything = 1, Explicit = 0, } - // Generated from `System.Security.SecurityElement` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityElement { public void AddAttribute(string name, string value) => throw null; @@ -11569,7 +13536,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Security.SecurityException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityException : System.SystemException { public object Demanded { get => throw null; set => throw null; } @@ -11592,7 +13558,6 @@ namespace System public string Url { get => throw null; set => throw null; } } - // Generated from `System.Security.SecurityRuleSet` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SecurityRuleSet : byte { Level1 = 1, @@ -11600,7 +13565,6 @@ namespace System None = 0, } - // Generated from `System.Security.SecurityRulesAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityRulesAttribute : System.Attribute { public System.Security.SecurityRuleSet RuleSet { get => throw null; } @@ -11608,37 +13572,31 @@ namespace System public bool SkipVerificationInFullTrust { get => throw null; set => throw null; } } - // Generated from `System.Security.SecuritySafeCriticalAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecuritySafeCriticalAttribute : System.Attribute { public SecuritySafeCriticalAttribute() => throw null; } - // Generated from `System.Security.SecurityTransparentAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityTransparentAttribute : System.Attribute { public SecurityTransparentAttribute() => throw null; } - // Generated from `System.Security.SecurityTreatAsSafeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityTreatAsSafeAttribute : System.Attribute { public SecurityTreatAsSafeAttribute() => throw null; } - // Generated from `System.Security.SuppressUnmanagedCodeSecurityAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SuppressUnmanagedCodeSecurityAttribute : System.Attribute { public SuppressUnmanagedCodeSecurityAttribute() => throw null; } - // Generated from `System.Security.UnverifiableCodeAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnverifiableCodeAttribute : System.Attribute { public UnverifiableCodeAttribute() => throw null; } - // Generated from `System.Security.VerificationException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class VerificationException : System.SystemException { public VerificationException() => throw null; @@ -11649,7 +13607,6 @@ namespace System namespace Cryptography { - // Generated from `System.Security.Cryptography.CryptographicException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CryptographicException : System.SystemException { public CryptographicException() => throw null; @@ -11663,20 +13620,17 @@ namespace System } namespace Permissions { - // Generated from `System.Security.Permissions.CodeAccessSecurityAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CodeAccessSecurityAttribute : System.Security.Permissions.SecurityAttribute { protected CodeAccessSecurityAttribute(System.Security.Permissions.SecurityAction action) : base(default(System.Security.Permissions.SecurityAction)) => throw null; } - // Generated from `System.Security.Permissions.PermissionState` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PermissionState : int { None = 0, Unrestricted = 1, } - // Generated from `System.Security.Permissions.SecurityAction` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum SecurityAction : int { Assert = 3, @@ -11690,7 +13644,6 @@ namespace System RequestRefuse = 10, } - // Generated from `System.Security.Permissions.SecurityAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SecurityAttribute : System.Attribute { public System.Security.Permissions.SecurityAction Action { get => throw null; set => throw null; } @@ -11699,7 +13652,6 @@ namespace System public bool Unrestricted { get => throw null; set => throw null; } } - // Generated from `System.Security.Permissions.SecurityPermissionAttribute` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityPermissionAttribute : System.Security.Permissions.CodeAccessSecurityAttribute { public bool Assertion { get => throw null; set => throw null; } @@ -11721,7 +13673,6 @@ namespace System public bool UnmanagedCode { get => throw null; set => throw null; } } - // Generated from `System.Security.Permissions.SecurityPermissionFlag` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SecurityPermissionFlag : int { @@ -11746,7 +13697,6 @@ namespace System } namespace Principal { - // Generated from `System.Security.Principal.IIdentity` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IIdentity { string AuthenticationType { get; } @@ -11754,14 +13704,12 @@ namespace System string Name { get; } } - // Generated from `System.Security.Principal.IPrincipal` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IPrincipal { System.Security.Principal.IIdentity Identity { get; } bool IsInRole(string role); } - // Generated from `System.Security.Principal.PrincipalPolicy` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum PrincipalPolicy : int { NoPrincipal = 1, @@ -11769,7 +13717,6 @@ namespace System WindowsPrincipal = 2, } - // Generated from `System.Security.Principal.TokenImpersonationLevel` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TokenImpersonationLevel : int { Anonymous = 1, @@ -11783,7 +13730,6 @@ namespace System } namespace Text { - // Generated from `System.Text.Decoder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Decoder { public virtual void Convert(System.Byte[] bytes, int byteIndex, int byteCount, System.Char[] chars, int charIndex, int charCount, bool flush, out int bytesUsed, out int charsUsed, out bool completed) => throw null; @@ -11803,7 +13749,6 @@ namespace System public virtual void Reset() => throw null; } - // Generated from `System.Text.DecoderExceptionFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecoderExceptionFallback : System.Text.DecoderFallback { public override System.Text.DecoderFallbackBuffer CreateFallbackBuffer() => throw null; @@ -11813,7 +13758,6 @@ namespace System public override int MaxCharCount { get => throw null; } } - // Generated from `System.Text.DecoderExceptionFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecoderExceptionFallbackBuffer : System.Text.DecoderFallbackBuffer { public DecoderExceptionFallbackBuffer() => throw null; @@ -11823,7 +13767,6 @@ namespace System public override int Remaining { get => throw null; } } - // Generated from `System.Text.DecoderFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DecoderFallback { public abstract System.Text.DecoderFallbackBuffer CreateFallbackBuffer(); @@ -11833,7 +13776,6 @@ namespace System public static System.Text.DecoderFallback ReplacementFallback { get => throw null; } } - // Generated from `System.Text.DecoderFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class DecoderFallbackBuffer { protected DecoderFallbackBuffer() => throw null; @@ -11844,7 +13786,6 @@ namespace System public virtual void Reset() => throw null; } - // Generated from `System.Text.DecoderFallbackException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecoderFallbackException : System.ArgumentException { public System.Byte[] BytesUnknown { get => throw null; } @@ -11855,7 +13796,6 @@ namespace System public int Index { get => throw null; } } - // Generated from `System.Text.DecoderReplacementFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecoderReplacementFallback : System.Text.DecoderFallback { public override System.Text.DecoderFallbackBuffer CreateFallbackBuffer() => throw null; @@ -11867,7 +13807,6 @@ namespace System public override int MaxCharCount { get => throw null; } } - // Generated from `System.Text.DecoderReplacementFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DecoderReplacementFallbackBuffer : System.Text.DecoderFallbackBuffer { public DecoderReplacementFallbackBuffer(System.Text.DecoderReplacementFallback fallback) => throw null; @@ -11878,7 +13817,6 @@ namespace System public override void Reset() => throw null; } - // Generated from `System.Text.Encoder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Encoder { public virtual void Convert(System.Char[] chars, int charIndex, int charCount, System.Byte[] bytes, int byteIndex, int byteCount, bool flush, out int charsUsed, out int bytesUsed, out bool completed) => throw null; @@ -11896,7 +13834,6 @@ namespace System public virtual void Reset() => throw null; } - // Generated from `System.Text.EncoderExceptionFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncoderExceptionFallback : System.Text.EncoderFallback { public override System.Text.EncoderFallbackBuffer CreateFallbackBuffer() => throw null; @@ -11906,7 +13843,6 @@ namespace System public override int MaxCharCount { get => throw null; } } - // Generated from `System.Text.EncoderExceptionFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncoderExceptionFallbackBuffer : System.Text.EncoderFallbackBuffer { public EncoderExceptionFallbackBuffer() => throw null; @@ -11917,7 +13853,6 @@ namespace System public override int Remaining { get => throw null; } } - // Generated from `System.Text.EncoderFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EncoderFallback { public abstract System.Text.EncoderFallbackBuffer CreateFallbackBuffer(); @@ -11927,7 +13862,6 @@ namespace System public static System.Text.EncoderFallback ReplacementFallback { get => throw null; } } - // Generated from `System.Text.EncoderFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EncoderFallbackBuffer { protected EncoderFallbackBuffer() => throw null; @@ -11939,7 +13873,6 @@ namespace System public virtual void Reset() => throw null; } - // Generated from `System.Text.EncoderFallbackException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncoderFallbackException : System.ArgumentException { public System.Char CharUnknown { get => throw null; } @@ -11952,7 +13885,6 @@ namespace System public bool IsUnknownSurrogate() => throw null; } - // Generated from `System.Text.EncoderReplacementFallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncoderReplacementFallback : System.Text.EncoderFallback { public override System.Text.EncoderFallbackBuffer CreateFallbackBuffer() => throw null; @@ -11964,7 +13896,6 @@ namespace System public override int MaxCharCount { get => throw null; } } - // Generated from `System.Text.EncoderReplacementFallbackBuffer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncoderReplacementFallbackBuffer : System.Text.EncoderFallbackBuffer { public EncoderReplacementFallbackBuffer(System.Text.EncoderReplacementFallback fallback) => throw null; @@ -11976,7 +13907,6 @@ namespace System public override void Reset() => throw null; } - // Generated from `System.Text.Encoding` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class Encoding : System.ICloneable { public static System.Text.Encoding ASCII { get => throw null; } @@ -12053,7 +13983,6 @@ namespace System public virtual int WindowsCodePage { get => throw null; } } - // Generated from `System.Text.EncodingInfo` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EncodingInfo { public int CodePage { get => throw null; } @@ -12065,7 +13994,6 @@ namespace System public string Name { get => throw null; } } - // Generated from `System.Text.EncodingProvider` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EncodingProvider { public EncodingProvider() => throw null; @@ -12076,7 +14004,6 @@ namespace System public virtual System.Collections.Generic.IEnumerable GetEncodings() => throw null; } - // Generated from `System.Text.NormalizationForm` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NormalizationForm : int { FormC = 1, @@ -12085,7 +14012,6 @@ namespace System FormKD = 6, } - // Generated from `System.Text.Rune` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct Rune : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.ISpanFormattable { public static bool operator !=(System.Text.Rune left, System.Text.Rune right) => throw null; @@ -12152,10 +14078,8 @@ namespace System public static explicit operator System.Text.Rune(System.UInt32 value) => throw null; } - // Generated from `System.Text.StringBuilder` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class StringBuilder : System.Runtime.Serialization.ISerializable { - // Generated from `System.Text.StringBuilder+AppendInterpolatedStringHandler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AppendInterpolatedStringHandler { public void AppendFormatted(System.ReadOnlySpan value) => throw null; @@ -12174,7 +14098,6 @@ namespace System } - // Generated from `System.Text.StringBuilder+ChunkEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ChunkEnumerator { // Stub generator skipped constructor @@ -12275,7 +14198,6 @@ namespace System public string ToString(int startIndex, int length) => throw null; } - // Generated from `System.Text.StringRuneEnumerator` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct StringRuneEnumerator : System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerator, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable { public System.Text.Rune Current { get => throw null; } @@ -12291,7 +14213,6 @@ namespace System namespace Unicode { - // Generated from `System.Text.Unicode.Utf8` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Utf8 { public static System.Buffers.OperationStatus FromUtf16(System.ReadOnlySpan source, System.Span destination, out int charsRead, out int bytesWritten, bool replaceInvalidSequences = default(bool), bool isFinalBlock = default(bool)) => throw null; @@ -12302,8 +14223,7 @@ namespace System } namespace Threading { - // Generated from `System.Threading.CancellationToken` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct CancellationToken + public struct CancellationToken : System.IEquatable { public static bool operator !=(System.Threading.CancellationToken left, System.Threading.CancellationToken right) => throw null; public static bool operator ==(System.Threading.CancellationToken left, System.Threading.CancellationToken right) => throw null; @@ -12326,7 +14246,6 @@ namespace System public System.Threading.WaitHandle WaitHandle { get => throw null; } } - // Generated from `System.Threading.CancellationTokenRegistration` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct CancellationTokenRegistration : System.IAsyncDisposable, System.IDisposable, System.IEquatable { public static bool operator !=(System.Threading.CancellationTokenRegistration left, System.Threading.CancellationTokenRegistration right) => throw null; @@ -12341,7 +14260,6 @@ namespace System public bool Unregister() => throw null; } - // Generated from `System.Threading.CancellationTokenSource` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CancellationTokenSource : System.IDisposable { public void Cancel() => throw null; @@ -12361,7 +14279,6 @@ namespace System public bool TryReset() => throw null; } - // Generated from `System.Threading.LazyThreadSafetyMode` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LazyThreadSafetyMode : int { ExecutionAndPublication = 2, @@ -12369,22 +14286,20 @@ namespace System PublicationOnly = 1, } - // Generated from `System.Threading.PeriodicTimer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PeriodicTimer : System.IDisposable { public void Dispose() => throw null; public PeriodicTimer(System.TimeSpan period) => throw null; public System.Threading.Tasks.ValueTask WaitForNextTickAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + // ERR: Stub generator didn't handle member: ~PeriodicTimer } - // Generated from `System.Threading.Timeout` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Timeout { public const int Infinite = default; public static System.TimeSpan InfiniteTimeSpan; } - // Generated from `System.Threading.Timer` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Timer : System.MarshalByRefObject, System.IAsyncDisposable, System.IDisposable { public static System.Int64 ActiveCount { get => throw null; } @@ -12402,10 +14317,8 @@ namespace System public Timer(System.Threading.TimerCallback callback, object state, System.UInt32 dueTime, System.UInt32 period) => throw null; } - // Generated from `System.Threading.TimerCallback` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void TimerCallback(object state); - // Generated from `System.Threading.WaitHandle` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class WaitHandle : System.MarshalByRefObject, System.IDisposable { public virtual void Close() => throw null; @@ -12436,7 +14349,6 @@ namespace System public const int WaitTimeout = default; } - // Generated from `System.Threading.WaitHandleExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class WaitHandleExtensions { public static Microsoft.Win32.SafeHandles.SafeWaitHandle GetSafeWaitHandle(this System.Threading.WaitHandle waitHandle) => throw null; @@ -12445,7 +14357,6 @@ namespace System namespace Tasks { - // Generated from `System.Threading.Tasks.ConcurrentExclusiveSchedulerPair` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ConcurrentExclusiveSchedulerPair { public void Complete() => throw null; @@ -12458,7 +14369,6 @@ namespace System public System.Threading.Tasks.TaskScheduler ExclusiveScheduler { get => throw null; } } - // Generated from `System.Threading.Tasks.Task` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Task : System.IAsyncResult, System.IDisposable { public object AsyncState { get => throw null; } @@ -12531,6 +14441,7 @@ namespace System public void Wait() => throw null; public void Wait(System.Threading.CancellationToken cancellationToken) => throw null; public bool Wait(System.TimeSpan timeout) => throw null; + public bool Wait(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) => throw null; public bool Wait(int millisecondsTimeout) => throw null; public bool Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) => throw null; public static void WaitAll(System.Threading.Tasks.Task[] tasks, System.Threading.CancellationToken cancellationToken) => throw null; @@ -12559,7 +14470,6 @@ namespace System public static System.Runtime.CompilerServices.YieldAwaitable Yield() => throw null; } - // Generated from `System.Threading.Tasks.Task<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Task : System.Threading.Tasks.Task { public System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) => throw null; @@ -12599,15 +14509,14 @@ namespace System public System.Threading.Tasks.Task WaitAsync(System.TimeSpan timeout, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Threading.Tasks.TaskAsyncEnumerableExtensions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class TaskAsyncEnumerableExtensions { public static System.Runtime.CompilerServices.ConfiguredAsyncDisposable ConfigureAwait(this System.IAsyncDisposable source, bool continueOnCapturedContext) => throw null; public static System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable ConfigureAwait(this System.Collections.Generic.IAsyncEnumerable source, bool continueOnCapturedContext) => throw null; + public static System.Collections.Generic.IEnumerable ToBlockingEnumerable(this System.Collections.Generic.IAsyncEnumerable source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable WithCancellation(this System.Collections.Generic.IAsyncEnumerable source, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Threading.Tasks.TaskCanceledException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskCanceledException : System.OperationCanceledException { public System.Threading.Tasks.Task Task { get => throw null; } @@ -12619,7 +14528,6 @@ namespace System public TaskCanceledException(string message, System.Exception innerException, System.Threading.CancellationToken token) => throw null; } - // Generated from `System.Threading.Tasks.TaskCompletionSource` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskCompletionSource { public void SetCanceled() => throw null; @@ -12639,7 +14547,6 @@ namespace System public bool TrySetResult() => throw null; } - // Generated from `System.Threading.Tasks.TaskCompletionSource<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskCompletionSource { public void SetCanceled() => throw null; @@ -12659,7 +14566,6 @@ namespace System public bool TrySetResult(TResult result) => throw null; } - // Generated from `System.Threading.Tasks.TaskContinuationOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TaskContinuationOptions : int { @@ -12680,7 +14586,6 @@ namespace System RunContinuationsAsynchronously = 64, } - // Generated from `System.Threading.Tasks.TaskCreationOptions` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TaskCreationOptions : int { @@ -12693,14 +14598,12 @@ namespace System RunContinuationsAsynchronously = 64, } - // Generated from `System.Threading.Tasks.TaskExtensions` in `Microsoft.AspNetCore.Http.Connections, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60; System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static partial class TaskExtensions + public static class TaskExtensions { public static System.Threading.Tasks.Task Unwrap(this System.Threading.Tasks.Task task) => throw null; public static System.Threading.Tasks.Task Unwrap(this System.Threading.Tasks.Task> task) => throw null; } - // Generated from `System.Threading.Tasks.TaskFactory` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskFactory { public System.Threading.CancellationToken CancellationToken { get => throw null; } @@ -12784,7 +14687,6 @@ namespace System public TaskFactory(System.Threading.Tasks.TaskScheduler scheduler) => throw null; } - // Generated from `System.Threading.Tasks.TaskFactory<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskFactory { public System.Threading.CancellationToken CancellationToken { get => throw null; } @@ -12833,7 +14735,6 @@ namespace System public TaskFactory(System.Threading.Tasks.TaskScheduler scheduler) => throw null; } - // Generated from `System.Threading.Tasks.TaskScheduler` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class TaskScheduler { public static System.Threading.Tasks.TaskScheduler Current { get => throw null; } @@ -12850,7 +14751,6 @@ namespace System public static event System.EventHandler UnobservedTaskException; } - // Generated from `System.Threading.Tasks.TaskSchedulerException` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TaskSchedulerException : System.Exception { public TaskSchedulerException() => throw null; @@ -12860,7 +14760,6 @@ namespace System public TaskSchedulerException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.Tasks.TaskStatus` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum TaskStatus : int { Canceled = 6, @@ -12873,7 +14772,6 @@ namespace System WaitingToRun = 2, } - // Generated from `System.Threading.Tasks.UnobservedTaskExceptionEventArgs` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnobservedTaskExceptionEventArgs : System.EventArgs { public System.AggregateException Exception { get => throw null; } @@ -12882,7 +14780,6 @@ namespace System public UnobservedTaskExceptionEventArgs(System.AggregateException exception) => throw null; } - // Generated from `System.Threading.Tasks.ValueTask` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTask : System.IEquatable { public static bool operator !=(System.Threading.Tasks.ValueTask left, System.Threading.Tasks.ValueTask right) => throw null; @@ -12909,7 +14806,6 @@ namespace System public ValueTask(System.Threading.Tasks.Task task) => throw null; } - // Generated from `System.Threading.Tasks.ValueTask<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ValueTask : System.IEquatable> { public static bool operator !=(System.Threading.Tasks.ValueTask left, System.Threading.Tasks.ValueTask right) => throw null; @@ -12935,7 +14831,6 @@ namespace System namespace Sources { - // Generated from `System.Threading.Tasks.Sources.IValueTaskSource` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IValueTaskSource { void GetResult(System.Int16 token); @@ -12943,7 +14838,6 @@ namespace System void OnCompleted(System.Action continuation, object state, System.Int16 token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags); } - // Generated from `System.Threading.Tasks.Sources.IValueTaskSource<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IValueTaskSource { TResult GetResult(System.Int16 token); @@ -12951,7 +14845,6 @@ namespace System void OnCompleted(System.Action continuation, object state, System.Int16 token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags); } - // Generated from `System.Threading.Tasks.Sources.ManualResetValueTaskSourceCore<>` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ManualResetValueTaskSourceCore { public TResult GetResult(System.Int16 token) => throw null; @@ -12965,7 +14858,6 @@ namespace System public System.Int16 Version { get => throw null; } } - // Generated from `System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ValueTaskSourceOnCompletedFlags : int { @@ -12974,7 +14866,6 @@ namespace System UseSchedulingContext = 1, } - // Generated from `System.Threading.Tasks.Sources.ValueTaskSourceStatus` in `System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ValueTaskSourceStatus : int { Canceled = 3, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.AccessControl.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.AccessControl.cs index 3e8b75576d1..3eb413e4276 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.AccessControl.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.AccessControl.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Security.AccessControl, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace AccessControl { - // Generated from `System.Security.AccessControl.AccessControlActions` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AccessControlActions : int { @@ -15,7 +15,6 @@ namespace System View = 1, } - // Generated from `System.Security.AccessControl.AccessControlModification` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AccessControlModification : int { Add = 0, @@ -26,7 +25,6 @@ namespace System Set = 1, } - // Generated from `System.Security.AccessControl.AccessControlSections` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AccessControlSections : int { @@ -38,21 +36,18 @@ namespace System Owner = 4, } - // Generated from `System.Security.AccessControl.AccessControlType` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AccessControlType : int { Allow = 0, Deny = 1, } - // Generated from `System.Security.AccessControl.AccessRule` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class AccessRule : System.Security.AccessControl.AuthorizationRule { public System.Security.AccessControl.AccessControlType AccessControlType { get => throw null; } protected AccessRule(System.Security.Principal.IdentityReference identity, int accessMask, bool isInherited, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags, System.Security.AccessControl.AccessControlType type) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags)) => throw null; } - // Generated from `System.Security.AccessControl.AccessRule<>` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AccessRule : System.Security.AccessControl.AccessRule where T : struct { public AccessRule(System.Security.Principal.IdentityReference identity, T rights, System.Security.AccessControl.AccessControlType type) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AccessControlType)) => throw null; @@ -62,7 +57,6 @@ namespace System public T Rights { get => throw null; } } - // Generated from `System.Security.AccessControl.AceEnumerator` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AceEnumerator : System.Collections.IEnumerator { public System.Security.AccessControl.GenericAce Current { get => throw null; } @@ -71,7 +65,6 @@ namespace System public void Reset() => throw null; } - // Generated from `System.Security.AccessControl.AceFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AceFlags : byte { @@ -87,7 +80,6 @@ namespace System SuccessfulAccess = 64, } - // Generated from `System.Security.AccessControl.AceQualifier` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AceQualifier : int { AccessAllowed = 0, @@ -96,7 +88,6 @@ namespace System SystemAudit = 2, } - // Generated from `System.Security.AccessControl.AceType` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum AceType : byte { AccessAllowed = 0, @@ -119,7 +110,6 @@ namespace System SystemAuditObject = 7, } - // Generated from `System.Security.AccessControl.AuditFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum AuditFlags : int { @@ -128,14 +118,12 @@ namespace System Success = 1, } - // Generated from `System.Security.AccessControl.AuditRule` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class AuditRule : System.Security.AccessControl.AuthorizationRule { public System.Security.AccessControl.AuditFlags AuditFlags { get => throw null; } protected AuditRule(System.Security.Principal.IdentityReference identity, int accessMask, bool isInherited, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags, System.Security.AccessControl.AuditFlags auditFlags) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags)) => throw null; } - // Generated from `System.Security.AccessControl.AuditRule<>` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AuditRule : System.Security.AccessControl.AuditRule where T : struct { public AuditRule(System.Security.Principal.IdentityReference identity, T rights, System.Security.AccessControl.AuditFlags flags) : base(default(System.Security.Principal.IdentityReference), default(int), default(bool), default(System.Security.AccessControl.InheritanceFlags), default(System.Security.AccessControl.PropagationFlags), default(System.Security.AccessControl.AuditFlags)) => throw null; @@ -145,7 +133,6 @@ namespace System public T Rights { get => throw null; } } - // Generated from `System.Security.AccessControl.AuthorizationRule` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class AuthorizationRule { protected internal int AccessMask { get => throw null; } @@ -156,7 +143,6 @@ namespace System public System.Security.AccessControl.PropagationFlags PropagationFlags { get => throw null; } } - // Generated from `System.Security.AccessControl.AuthorizationRuleCollection` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AuthorizationRuleCollection : System.Collections.ReadOnlyCollectionBase { public void AddRule(System.Security.AccessControl.AuthorizationRule rule) => throw null; @@ -165,7 +151,6 @@ namespace System public System.Security.AccessControl.AuthorizationRule this[int index] { get => throw null; } } - // Generated from `System.Security.AccessControl.CommonAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CommonAce : System.Security.AccessControl.QualifiedAce { public override int BinaryLength { get => throw null; } @@ -174,7 +159,6 @@ namespace System public static int MaxOpaqueLength(bool isCallback) => throw null; } - // Generated from `System.Security.AccessControl.CommonAcl` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CommonAcl : System.Security.AccessControl.GenericAcl { public override int BinaryLength { get => throw null; } @@ -190,7 +174,6 @@ namespace System public override System.Byte Revision { get => throw null; } } - // Generated from `System.Security.AccessControl.CommonObjectSecurity` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class CommonObjectSecurity : System.Security.AccessControl.ObjectSecurity { protected void AddAccessRule(System.Security.AccessControl.AccessRule rule) => throw null; @@ -211,7 +194,6 @@ namespace System protected void SetAuditRule(System.Security.AccessControl.AuditRule rule) => throw null; } - // Generated from `System.Security.AccessControl.CommonSecurityDescriptor` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CommonSecurityDescriptor : System.Security.AccessControl.GenericSecurityDescriptor { public void AddDiscretionaryAcl(System.Byte revision, int trusted) => throw null; @@ -235,7 +217,6 @@ namespace System public System.Security.AccessControl.SystemAcl SystemAcl { get => throw null; set => throw null; } } - // Generated from `System.Security.AccessControl.CompoundAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompoundAce : System.Security.AccessControl.KnownAce { public override int BinaryLength { get => throw null; } @@ -244,13 +225,11 @@ namespace System public override void GetBinaryForm(System.Byte[] binaryForm, int offset) => throw null; } - // Generated from `System.Security.AccessControl.CompoundAceType` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum CompoundAceType : int { Impersonation = 1, } - // Generated from `System.Security.AccessControl.ControlFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ControlFlags : int { @@ -273,7 +252,6 @@ namespace System SystemAclProtected = 8192, } - // Generated from `System.Security.AccessControl.CustomAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CustomAce : System.Security.AccessControl.GenericAce { public override int BinaryLength { get => throw null; } @@ -285,7 +263,6 @@ namespace System public void SetOpaque(System.Byte[] opaque) => throw null; } - // Generated from `System.Security.AccessControl.DiscretionaryAcl` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DiscretionaryAcl : System.Security.AccessControl.CommonAcl { public void AddAccess(System.Security.AccessControl.AccessControlType accessType, System.Security.Principal.SecurityIdentifier sid, System.Security.AccessControl.ObjectAccessRule rule) => throw null; @@ -305,7 +282,6 @@ namespace System public void SetAccess(System.Security.AccessControl.AccessControlType accessType, System.Security.Principal.SecurityIdentifier sid, int accessMask, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags, System.Security.AccessControl.ObjectAceFlags objectFlags, System.Guid objectType, System.Guid inheritedObjectType) => throw null; } - // Generated from `System.Security.AccessControl.GenericAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GenericAce { public static bool operator !=(System.Security.AccessControl.GenericAce left, System.Security.AccessControl.GenericAce right) => throw null; @@ -325,7 +301,6 @@ namespace System public System.Security.AccessControl.PropagationFlags PropagationFlags { get => throw null; } } - // Generated from `System.Security.AccessControl.GenericAcl` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GenericAcl : System.Collections.ICollection, System.Collections.IEnumerable { public static System.Byte AclRevision; @@ -345,7 +320,6 @@ namespace System public virtual object SyncRoot { get => throw null; } } - // Generated from `System.Security.AccessControl.GenericSecurityDescriptor` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class GenericSecurityDescriptor { public int BinaryLength { get => throw null; } @@ -359,7 +333,6 @@ namespace System public static System.Byte Revision { get => throw null; } } - // Generated from `System.Security.AccessControl.InheritanceFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum InheritanceFlags : int { @@ -368,7 +341,6 @@ namespace System ObjectInherit = 2, } - // Generated from `System.Security.AccessControl.KnownAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class KnownAce : System.Security.AccessControl.GenericAce { public int AccessMask { get => throw null; set => throw null; } @@ -376,10 +348,8 @@ namespace System public System.Security.Principal.SecurityIdentifier SecurityIdentifier { get => throw null; set => throw null; } } - // Generated from `System.Security.AccessControl.NativeObjectSecurity` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class NativeObjectSecurity : System.Security.AccessControl.CommonObjectSecurity { - // Generated from `System.Security.AccessControl.NativeObjectSecurity+ExceptionFromErrorCode` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected internal delegate System.Exception ExceptionFromErrorCode(int errorCode, string name, System.Runtime.InteropServices.SafeHandle handle, object context); @@ -395,7 +365,6 @@ namespace System protected void Persist(string name, System.Security.AccessControl.AccessControlSections includeSections, object exceptionContext) => throw null; } - // Generated from `System.Security.AccessControl.ObjectAccessRule` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ObjectAccessRule : System.Security.AccessControl.AccessRule { public System.Guid InheritedObjectType { get => throw null; } @@ -404,7 +373,6 @@ namespace System public System.Guid ObjectType { get => throw null; } } - // Generated from `System.Security.AccessControl.ObjectAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ObjectAce : System.Security.AccessControl.QualifiedAce { public override int BinaryLength { get => throw null; } @@ -416,7 +384,6 @@ namespace System public System.Guid ObjectAceType { get => throw null; set => throw null; } } - // Generated from `System.Security.AccessControl.ObjectAceFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ObjectAceFlags : int { @@ -425,7 +392,6 @@ namespace System ObjectAceTypePresent = 1, } - // Generated from `System.Security.AccessControl.ObjectAuditRule` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ObjectAuditRule : System.Security.AccessControl.AuditRule { public System.Guid InheritedObjectType { get => throw null; } @@ -434,7 +400,6 @@ namespace System public System.Guid ObjectType { get => throw null; } } - // Generated from `System.Security.AccessControl.ObjectSecurity` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ObjectSecurity { public abstract System.Type AccessRightType { get; } @@ -484,7 +449,6 @@ namespace System protected void WriteUnlock() => throw null; } - // Generated from `System.Security.AccessControl.ObjectSecurity<>` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class ObjectSecurity : System.Security.AccessControl.NativeObjectSecurity where T : struct { public override System.Type AccessRightType { get => throw null; } @@ -512,7 +476,6 @@ namespace System public virtual void SetAuditRule(System.Security.AccessControl.AuditRule rule) => throw null; } - // Generated from `System.Security.AccessControl.PrivilegeNotHeldException` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PrivilegeNotHeldException : System.UnauthorizedAccessException, System.Runtime.Serialization.ISerializable { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -522,7 +485,6 @@ namespace System public PrivilegeNotHeldException(string privilege, System.Exception inner) => throw null; } - // Generated from `System.Security.AccessControl.PropagationFlags` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum PropagationFlags : int { @@ -531,7 +493,6 @@ namespace System None = 0, } - // Generated from `System.Security.AccessControl.QualifiedAce` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class QualifiedAce : System.Security.AccessControl.KnownAce { public System.Security.AccessControl.AceQualifier AceQualifier { get => throw null; } @@ -542,7 +503,6 @@ namespace System public void SetOpaque(System.Byte[] opaque) => throw null; } - // Generated from `System.Security.AccessControl.RawAcl` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RawAcl : System.Security.AccessControl.GenericAcl { public override int BinaryLength { get => throw null; } @@ -556,7 +516,6 @@ namespace System public override System.Byte Revision { get => throw null; } } - // Generated from `System.Security.AccessControl.RawSecurityDescriptor` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RawSecurityDescriptor : System.Security.AccessControl.GenericSecurityDescriptor { public override System.Security.AccessControl.ControlFlags ControlFlags { get => throw null; } @@ -571,7 +530,6 @@ namespace System public System.Security.AccessControl.RawAcl SystemAcl { get => throw null; set => throw null; } } - // Generated from `System.Security.AccessControl.ResourceType` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ResourceType : int { DSObject = 8, @@ -589,7 +547,6 @@ namespace System WmiGuidObject = 11, } - // Generated from `System.Security.AccessControl.SecurityInfos` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SecurityInfos : int { @@ -599,7 +556,6 @@ namespace System SystemAcl = 8, } - // Generated from `System.Security.AccessControl.SystemAcl` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SystemAcl : System.Security.AccessControl.CommonAcl { public void AddAudit(System.Security.AccessControl.AuditFlags auditFlags, System.Security.Principal.SecurityIdentifier sid, int accessMask, System.Security.AccessControl.InheritanceFlags inheritanceFlags, System.Security.AccessControl.PropagationFlags propagationFlags) => throw null; @@ -622,7 +578,6 @@ namespace System } namespace Policy { - // Generated from `System.Security.Policy.Evidence` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Evidence : System.Collections.ICollection, System.Collections.IEnumerable { public void AddAssembly(object id) => throw null; @@ -650,7 +605,6 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Security.Policy.EvidenceBase` in `System.Security.AccessControl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class EvidenceBase { public virtual System.Security.Policy.EvidenceBase Clone() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Claims.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Claims.cs index 587b68433f8..0388322c56d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Claims.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Claims.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Security.Claims, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Claims { - // Generated from `System.Security.Claims.Claim` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Claim { public Claim(System.IO.BinaryReader reader) => throw null; @@ -33,7 +33,6 @@ namespace System protected virtual void WriteTo(System.IO.BinaryWriter writer, System.Byte[] userData) => throw null; } - // Generated from `System.Security.Claims.ClaimTypes` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ClaimTypes { public const string Actor = default; @@ -92,7 +91,6 @@ namespace System public const string X500DistinguishedName = default; } - // Generated from `System.Security.Claims.ClaimValueTypes` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ClaimValueTypes { public const string Base64Binary = default; @@ -124,7 +122,6 @@ namespace System public const string YearMonthDuration = default; } - // Generated from `System.Security.Claims.ClaimsIdentity` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ClaimsIdentity : System.Security.Principal.IIdentity { public System.Security.Claims.ClaimsIdentity Actor { get => throw null; set => throw null; } @@ -170,7 +167,6 @@ namespace System protected virtual void WriteTo(System.IO.BinaryWriter writer, System.Byte[] userData) => throw null; } - // Generated from `System.Security.Claims.ClaimsPrincipal` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ClaimsPrincipal : System.Security.Principal.IPrincipal { public virtual void AddIdentities(System.Collections.Generic.IEnumerable identities) => throw null; @@ -205,7 +201,6 @@ namespace System } namespace Principal { - // Generated from `System.Security.Principal.GenericIdentity` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GenericIdentity : System.Security.Claims.ClaimsIdentity { public override string AuthenticationType { get => throw null; } @@ -218,7 +213,6 @@ namespace System public override string Name { get => throw null; } } - // Generated from `System.Security.Principal.GenericPrincipal` in `System.Security.Claims, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GenericPrincipal : System.Security.Claims.ClaimsPrincipal { public GenericPrincipal(System.Security.Principal.IIdentity identity, string[] roles) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Algorithms.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Algorithms.cs deleted file mode 100644 index c5ec5af3ee0..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Algorithms.cs +++ /dev/null @@ -1,996 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.Aes` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class Aes : System.Security.Cryptography.SymmetricAlgorithm - { - protected Aes() => throw null; - public static System.Security.Cryptography.Aes Create() => throw null; - public static System.Security.Cryptography.Aes Create(string algorithmName) => throw null; - } - - // Generated from `System.Security.Cryptography.AesCcm` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AesCcm : System.IDisposable - { - public AesCcm(System.Byte[] key) => throw null; - public AesCcm(System.ReadOnlySpan key) => throw null; - public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public void Dispose() => throw null; - public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public static bool IsSupported { get => throw null; } - public static System.Security.Cryptography.KeySizes NonceByteSizes { get => throw null; } - public static System.Security.Cryptography.KeySizes TagByteSizes { get => throw null; } - } - - // Generated from `System.Security.Cryptography.AesGcm` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AesGcm : System.IDisposable - { - public AesGcm(System.Byte[] key) => throw null; - public AesGcm(System.ReadOnlySpan key) => throw null; - public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public void Dispose() => throw null; - public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public static bool IsSupported { get => throw null; } - public static System.Security.Cryptography.KeySizes NonceByteSizes { get => throw null; } - public static System.Security.Cryptography.KeySizes TagByteSizes { get => throw null; } - } - - // Generated from `System.Security.Cryptography.AesManaged` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AesManaged : System.Security.Cryptography.Aes - { - public AesManaged() => throw null; - public override int BlockSize { get => throw null; set => throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override int FeedbackSize { get => throw null; set => throw null; } - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] IV { get => throw null; set => throw null; } - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } - public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.AsymmetricKeyExchangeDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class AsymmetricKeyExchangeDeformatter - { - protected AsymmetricKeyExchangeDeformatter() => throw null; - public abstract System.Byte[] DecryptKeyExchange(System.Byte[] rgb); - public abstract string Parameters { get; set; } - public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); - } - - // Generated from `System.Security.Cryptography.AsymmetricKeyExchangeFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class AsymmetricKeyExchangeFormatter - { - protected AsymmetricKeyExchangeFormatter() => throw null; - public abstract System.Byte[] CreateKeyExchange(System.Byte[] data); - public abstract System.Byte[] CreateKeyExchange(System.Byte[] data, System.Type symAlgType); - public abstract string Parameters { get; } - public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); - } - - // Generated from `System.Security.Cryptography.AsymmetricSignatureDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class AsymmetricSignatureDeformatter - { - protected AsymmetricSignatureDeformatter() => throw null; - public abstract void SetHashAlgorithm(string strName); - public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); - public abstract bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature); - public virtual bool VerifySignature(System.Security.Cryptography.HashAlgorithm hash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.AsymmetricSignatureFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class AsymmetricSignatureFormatter - { - protected AsymmetricSignatureFormatter() => throw null; - public abstract System.Byte[] CreateSignature(System.Byte[] rgbHash); - public virtual System.Byte[] CreateSignature(System.Security.Cryptography.HashAlgorithm hash) => throw null; - public abstract void SetHashAlgorithm(string strName); - public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); - } - - // Generated from `System.Security.Cryptography.ChaCha20Poly1305` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ChaCha20Poly1305 : System.IDisposable - { - public ChaCha20Poly1305(System.Byte[] key) => throw null; - public ChaCha20Poly1305(System.ReadOnlySpan key) => throw null; - public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public void Dispose() => throw null; - public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; - public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; - public static bool IsSupported { get => throw null; } - } - - // Generated from `System.Security.Cryptography.CryptoConfig` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CryptoConfig - { - public static void AddAlgorithm(System.Type algorithm, params string[] names) => throw null; - public static void AddOID(string oid, params string[] names) => throw null; - public static bool AllowOnlyFipsAlgorithms { get => throw null; } - public static object CreateFromName(string name) => throw null; - public static object CreateFromName(string name, params object[] args) => throw null; - public CryptoConfig() => throw null; - public static System.Byte[] EncodeOID(string str) => throw null; - public static string MapNameToOID(string name) => throw null; - } - - // Generated from `System.Security.Cryptography.DES` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class DES : System.Security.Cryptography.SymmetricAlgorithm - { - public static System.Security.Cryptography.DES Create() => throw null; - public static System.Security.Cryptography.DES Create(string algName) => throw null; - protected DES() => throw null; - public static bool IsSemiWeakKey(System.Byte[] rgbKey) => throw null; - public static bool IsWeakKey(System.Byte[] rgbKey) => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.DSA` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class DSA : System.Security.Cryptography.AsymmetricAlgorithm - { - public static System.Security.Cryptography.DSA Create() => throw null; - public static System.Security.Cryptography.DSA Create(System.Security.Cryptography.DSAParameters parameters) => throw null; - public static System.Security.Cryptography.DSA Create(int keySizeInBits) => throw null; - public static System.Security.Cryptography.DSA Create(string algName) => throw null; - public abstract System.Byte[] CreateSignature(System.Byte[] rgbHash); - public System.Byte[] CreateSignature(System.Byte[] rgbHash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] CreateSignatureCore(System.ReadOnlySpan hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected DSA() => throw null; - public abstract System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters); - public override void FromXmlString(string xmlString) => throw null; - public int GetMaxSignatureSize(System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; - public override void ImportFromPem(System.ReadOnlySpan input) => throw null; - public abstract void ImportParameters(System.Security.Cryptography.DSAParameters parameters); - public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] SignDataCore(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] SignDataCore(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public override string ToXmlString(bool includePrivateParameters) => throw null; - public bool TryCreateSignature(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public virtual bool TryCreateSignature(System.ReadOnlySpan hash, System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TryCreateSignatureCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; - public bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; - protected virtual bool TrySignDataCore(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifyDataCore(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifyDataCore(System.IO.Stream data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public abstract bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature); - public bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifySignature(System.ReadOnlySpan hash, System.ReadOnlySpan signature) => throw null; - public bool VerifySignature(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifySignatureCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - } - - // Generated from `System.Security.Cryptography.DSAParameters` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct DSAParameters - { - public int Counter; - // Stub generator skipped constructor - public System.Byte[] G; - public System.Byte[] J; - public System.Byte[] P; - public System.Byte[] Q; - public System.Byte[] Seed; - public System.Byte[] X; - public System.Byte[] Y; - } - - // Generated from `System.Security.Cryptography.DSASignatureDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DSASignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter - { - public DSASignatureDeformatter() => throw null; - public DSASignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetHashAlgorithm(string strName) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.DSASignatureFormat` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum DSASignatureFormat : int - { - IeeeP1363FixedFieldConcatenation = 0, - Rfc3279DerSequence = 1, - } - - // Generated from `System.Security.Cryptography.DSASignatureFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DSASignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter - { - public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; - public DSASignatureFormatter() => throw null; - public DSASignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetHashAlgorithm(string strName) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.DeriveBytes` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class DeriveBytes : System.IDisposable - { - protected DeriveBytes() => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public abstract System.Byte[] GetBytes(int cb); - public abstract void Reset(); - } - - // Generated from `System.Security.Cryptography.ECCurve` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct ECCurve - { - // Generated from `System.Security.Cryptography.ECCurve+ECCurveType` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum ECCurveType : int - { - Characteristic2 = 4, - Implicit = 0, - Named = 5, - PrimeMontgomery = 3, - PrimeShortWeierstrass = 1, - PrimeTwistedEdwards = 2, - } - - - // Generated from `System.Security.Cryptography.ECCurve+NamedCurves` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class NamedCurves - { - public static System.Security.Cryptography.ECCurve brainpoolP160r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP160t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP192r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP192t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP224r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP224t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP256r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP256t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP320r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP320t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP384r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP384t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP512r1 { get => throw null; } - public static System.Security.Cryptography.ECCurve brainpoolP512t1 { get => throw null; } - public static System.Security.Cryptography.ECCurve nistP256 { get => throw null; } - public static System.Security.Cryptography.ECCurve nistP384 { get => throw null; } - public static System.Security.Cryptography.ECCurve nistP521 { get => throw null; } - } - - - public System.Byte[] A; - public System.Byte[] B; - public System.Byte[] Cofactor; - public static System.Security.Cryptography.ECCurve CreateFromFriendlyName(string oidFriendlyName) => throw null; - public static System.Security.Cryptography.ECCurve CreateFromOid(System.Security.Cryptography.Oid curveOid) => throw null; - public static System.Security.Cryptography.ECCurve CreateFromValue(string oidValue) => throw null; - public System.Security.Cryptography.ECCurve.ECCurveType CurveType; - // Stub generator skipped constructor - public System.Security.Cryptography.ECPoint G; - public System.Security.Cryptography.HashAlgorithmName? Hash; - public bool IsCharacteristic2 { get => throw null; } - public bool IsExplicit { get => throw null; } - public bool IsNamed { get => throw null; } - public bool IsPrime { get => throw null; } - public System.Security.Cryptography.Oid Oid { get => throw null; } - public System.Byte[] Order; - public System.Byte[] Polynomial; - public System.Byte[] Prime; - public System.Byte[] Seed; - public void Validate() => throw null; - } - - // Generated from `System.Security.Cryptography.ECDiffieHellman` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class ECDiffieHellman : System.Security.Cryptography.AsymmetricAlgorithm - { - public static System.Security.Cryptography.ECDiffieHellman Create() => throw null; - public static System.Security.Cryptography.ECDiffieHellman Create(System.Security.Cryptography.ECCurve curve) => throw null; - public static System.Security.Cryptography.ECDiffieHellman Create(System.Security.Cryptography.ECParameters parameters) => throw null; - public static System.Security.Cryptography.ECDiffieHellman Create(string algorithm) => throw null; - public System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public virtual System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey) => throw null; - public virtual System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public virtual System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; - public virtual System.Byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Byte[] prfLabel, System.Byte[] prfSeed) => throw null; - protected ECDiffieHellman() => throw null; - public virtual System.Byte[] ExportECPrivateKey() => throw null; - public virtual System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public virtual System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public override void FromXmlString(string xmlString) => throw null; - public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; - public override void ImportFromPem(System.ReadOnlySpan input) => throw null; - public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override string KeyExchangeAlgorithm { get => throw null; } - public abstract System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get; } - public override string SignatureAlgorithm { get => throw null; } - public override string ToXmlString(bool includePrivateParameters) => throw null; - public virtual bool TryExportECPrivateKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.ECDiffieHellmanPublicKey` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class ECDiffieHellmanPublicKey : System.IDisposable - { - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - protected ECDiffieHellmanPublicKey() => throw null; - protected ECDiffieHellmanPublicKey(System.Byte[] keyBlob) => throw null; - public virtual System.Security.Cryptography.ECParameters ExportExplicitParameters() => throw null; - public virtual System.Security.Cryptography.ECParameters ExportParameters() => throw null; - public virtual System.Byte[] ExportSubjectPublicKeyInfo() => throw null; - public virtual System.Byte[] ToByteArray() => throw null; - public virtual string ToXmlString() => throw null; - public virtual bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.ECDsa` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class ECDsa : System.Security.Cryptography.AsymmetricAlgorithm - { - public static System.Security.Cryptography.ECDsa Create() => throw null; - public static System.Security.Cryptography.ECDsa Create(System.Security.Cryptography.ECCurve curve) => throw null; - public static System.Security.Cryptography.ECDsa Create(System.Security.Cryptography.ECParameters parameters) => throw null; - public static System.Security.Cryptography.ECDsa Create(string algorithm) => throw null; - protected ECDsa() => throw null; - public virtual System.Byte[] ExportECPrivateKey() => throw null; - public virtual System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public virtual System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public override void FromXmlString(string xmlString) => throw null; - public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - public int GetMaxSignatureSize(System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; - public override void ImportFromPem(System.ReadOnlySpan input) => throw null; - public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override string KeyExchangeAlgorithm { get => throw null; } - public virtual System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] SignDataCore(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] SignDataCore(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public abstract System.Byte[] SignHash(System.Byte[] hash); - public System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual System.Byte[] SignHashCore(System.ReadOnlySpan hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public override string SignatureAlgorithm { get => throw null; } - public override string ToXmlString(bool includePrivateParameters) => throw null; - public virtual bool TryExportECPrivateKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; - public bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; - protected virtual bool TrySignDataCore(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public virtual bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TrySignHashCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifyDataCore(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifyDataCore(System.IO.Stream data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public abstract bool VerifyHash(System.Byte[] hash, System.Byte[] signature); - public bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - public virtual bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature) => throw null; - public bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - protected virtual bool VerifyHashCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; - } - - // Generated from `System.Security.Cryptography.ECParameters` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct ECParameters - { - public System.Security.Cryptography.ECCurve Curve; - public System.Byte[] D; - // Stub generator skipped constructor - public System.Security.Cryptography.ECPoint Q; - public void Validate() => throw null; - } - - // Generated from `System.Security.Cryptography.ECPoint` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct ECPoint - { - // Stub generator skipped constructor - public System.Byte[] X; - public System.Byte[] Y; - } - - // Generated from `System.Security.Cryptography.HKDF` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class HKDF - { - public static System.Byte[] DeriveKey(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] ikm, int outputLength, System.Byte[] salt = default(System.Byte[]), System.Byte[] info = default(System.Byte[])) => throw null; - public static void DeriveKey(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan ikm, System.Span output, System.ReadOnlySpan salt, System.ReadOnlySpan info) => throw null; - public static System.Byte[] Expand(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] prk, int outputLength, System.Byte[] info = default(System.Byte[])) => throw null; - public static void Expand(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan prk, System.Span output, System.ReadOnlySpan info) => throw null; - public static System.Byte[] Extract(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] ikm, System.Byte[] salt = default(System.Byte[])) => throw null; - public static int Extract(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan ikm, System.ReadOnlySpan salt, System.Span prk) => throw null; - } - - // Generated from `System.Security.Cryptography.HMACMD5` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class HMACMD5 : System.Security.Cryptography.HMAC - { - protected override void Dispose(bool disposing) => throw null; - public HMACMD5() => throw null; - public HMACMD5(System.Byte[] key) => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HMACSHA1` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class HMACSHA1 : System.Security.Cryptography.HMAC - { - protected override void Dispose(bool disposing) => throw null; - public HMACSHA1() => throw null; - public HMACSHA1(System.Byte[] key) => throw null; - public HMACSHA1(System.Byte[] key, bool useManagedSha1) => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HMACSHA256` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class HMACSHA256 : System.Security.Cryptography.HMAC - { - protected override void Dispose(bool disposing) => throw null; - public HMACSHA256() => throw null; - public HMACSHA256(System.Byte[] key) => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HMACSHA384` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class HMACSHA384 : System.Security.Cryptography.HMAC - { - protected override void Dispose(bool disposing) => throw null; - public HMACSHA384() => throw null; - public HMACSHA384(System.Byte[] key) => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public bool ProduceLegacyHmacValues { get => throw null; set => throw null; } - public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HMACSHA512` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class HMACSHA512 : System.Security.Cryptography.HMAC - { - protected override void Dispose(bool disposing) => throw null; - public HMACSHA512() => throw null; - public HMACSHA512(System.Byte[] key) => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public bool ProduceLegacyHmacValues { get => throw null; set => throw null; } - public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.IncrementalHash` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class IncrementalHash : System.IDisposable - { - public System.Security.Cryptography.HashAlgorithmName AlgorithmName { get => throw null; } - public void AppendData(System.Byte[] data) => throw null; - public void AppendData(System.Byte[] data, int offset, int count) => throw null; - public void AppendData(System.ReadOnlySpan data) => throw null; - public static System.Security.Cryptography.IncrementalHash CreateHMAC(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] key) => throw null; - public static System.Security.Cryptography.IncrementalHash CreateHMAC(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.ReadOnlySpan key) => throw null; - public static System.Security.Cryptography.IncrementalHash CreateHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public void Dispose() => throw null; - public System.Byte[] GetCurrentHash() => throw null; - public int GetCurrentHash(System.Span destination) => throw null; - public System.Byte[] GetHashAndReset() => throw null; - public int GetHashAndReset(System.Span destination) => throw null; - public int HashLengthInBytes { get => throw null; } - public bool TryGetCurrentHash(System.Span destination, out int bytesWritten) => throw null; - public bool TryGetHashAndReset(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.MD5` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class MD5 : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.MD5 Create() => throw null; - public static System.Security.Cryptography.MD5 Create(string algName) => throw null; - public static System.Byte[] HashData(System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; - protected MD5() => throw null; - public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.MaskGenerationMethod` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class MaskGenerationMethod - { - public abstract System.Byte[] GenerateMask(System.Byte[] rgbSeed, int cbReturn); - protected MaskGenerationMethod() => throw null; - } - - // Generated from `System.Security.Cryptography.PKCS1MaskGenerationMethod` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class PKCS1MaskGenerationMethod : System.Security.Cryptography.MaskGenerationMethod - { - public override System.Byte[] GenerateMask(System.Byte[] rgbSeed, int cbReturn) => throw null; - public string HashName { get => throw null; set => throw null; } - public PKCS1MaskGenerationMethod() => throw null; - } - - // Generated from `System.Security.Cryptography.RC2` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class RC2 : System.Security.Cryptography.SymmetricAlgorithm - { - public static System.Security.Cryptography.RC2 Create() => throw null; - public static System.Security.Cryptography.RC2 Create(string AlgName) => throw null; - public virtual int EffectiveKeySize { get => throw null; set => throw null; } - protected int EffectiveKeySizeValue; - public override int KeySize { get => throw null; set => throw null; } - protected RC2() => throw null; - } - - // Generated from `System.Security.Cryptography.RSA` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class RSA : System.Security.Cryptography.AsymmetricAlgorithm - { - public static System.Security.Cryptography.RSA Create() => throw null; - public static System.Security.Cryptography.RSA Create(System.Security.Cryptography.RSAParameters parameters) => throw null; - public static System.Security.Cryptography.RSA Create(int keySizeInBits) => throw null; - public static System.Security.Cryptography.RSA Create(string algName) => throw null; - public virtual System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public virtual System.Byte[] DecryptValue(System.Byte[] rgb) => throw null; - public virtual System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public virtual System.Byte[] EncryptValue(System.Byte[] rgb) => throw null; - public abstract System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters); - public virtual System.Byte[] ExportRSAPrivateKey() => throw null; - public virtual System.Byte[] ExportRSAPublicKey() => throw null; - public override void FromXmlString(string xmlString) => throw null; - protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; - public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; - public override void ImportFromPem(System.ReadOnlySpan input) => throw null; - public abstract void ImportParameters(System.Security.Cryptography.RSAParameters parameters); - public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual void ImportRSAPrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual void ImportRSAPublicKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public override string KeyExchangeAlgorithm { get => throw null; } - protected RSA() => throw null; - public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public override string SignatureAlgorithm { get => throw null; } - public override string ToXmlString(bool includePrivateParameters) => throw null; - public virtual bool TryDecrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; - public virtual bool TryEncrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; - public virtual bool TryExportRSAPrivateKey(System.Span destination, out int bytesWritten) => throw null; - public virtual bool TryExportRSAPublicKey(System.Span destination, out int bytesWritten) => throw null; - public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; - public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) => throw null; - public virtual bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public virtual bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAEncryptionPadding` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAEncryptionPadding : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.RSAEncryptionPadding left, System.Security.Cryptography.RSAEncryptionPadding right) => throw null; - public static bool operator ==(System.Security.Cryptography.RSAEncryptionPadding left, System.Security.Cryptography.RSAEncryptionPadding right) => throw null; - public static System.Security.Cryptography.RSAEncryptionPadding CreateOaep(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public bool Equals(System.Security.Cryptography.RSAEncryptionPadding other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public System.Security.Cryptography.RSAEncryptionPaddingMode Mode { get => throw null; } - public System.Security.Cryptography.HashAlgorithmName OaepHashAlgorithm { get => throw null; } - public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA1 { get => throw null; } - public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA256 { get => throw null; } - public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA384 { get => throw null; } - public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA512 { get => throw null; } - public static System.Security.Cryptography.RSAEncryptionPadding Pkcs1 { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.RSAEncryptionPaddingMode` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum RSAEncryptionPaddingMode : int - { - Oaep = 1, - Pkcs1 = 0, - } - - // Generated from `System.Security.Cryptography.RSAOAEPKeyExchangeDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAOAEPKeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter - { - public override System.Byte[] DecryptKeyExchange(System.Byte[] rgbData) => throw null; - public override string Parameters { get => throw null; set => throw null; } - public RSAOAEPKeyExchangeDeformatter() => throw null; - public RSAOAEPKeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAOAEPKeyExchangeFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAOAEPKeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter - { - public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData) => throw null; - public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData, System.Type symAlgType) => throw null; - public System.Byte[] Parameter { get => throw null; set => throw null; } - public override string Parameters { get => throw null; } - public RSAOAEPKeyExchangeFormatter() => throw null; - public RSAOAEPKeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public System.Security.Cryptography.RandomNumberGenerator Rng { get => throw null; set => throw null; } - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAPKCS1KeyExchangeDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAPKCS1KeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter - { - public override System.Byte[] DecryptKeyExchange(System.Byte[] rgbIn) => throw null; - public override string Parameters { get => throw null; set => throw null; } - public System.Security.Cryptography.RandomNumberGenerator RNG { get => throw null; set => throw null; } - public RSAPKCS1KeyExchangeDeformatter() => throw null; - public RSAPKCS1KeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAPKCS1KeyExchangeFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAPKCS1KeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter - { - public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData) => throw null; - public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData, System.Type symAlgType) => throw null; - public override string Parameters { get => throw null; } - public RSAPKCS1KeyExchangeFormatter() => throw null; - public RSAPKCS1KeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public System.Security.Cryptography.RandomNumberGenerator Rng { get => throw null; set => throw null; } - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAPKCS1SignatureDeformatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAPKCS1SignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter - { - public RSAPKCS1SignatureDeformatter() => throw null; - public RSAPKCS1SignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetHashAlgorithm(string strName) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAPKCS1SignatureFormatter` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAPKCS1SignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter - { - public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; - public RSAPKCS1SignatureFormatter() => throw null; - public RSAPKCS1SignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public override void SetHashAlgorithm(string strName) => throw null; - public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAParameters` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct RSAParameters - { - public System.Byte[] D; - public System.Byte[] DP; - public System.Byte[] DQ; - public System.Byte[] Exponent; - public System.Byte[] InverseQ; - public System.Byte[] Modulus; - public System.Byte[] P; - public System.Byte[] Q; - // Stub generator skipped constructor - } - - // Generated from `System.Security.Cryptography.RSASignaturePadding` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSASignaturePadding : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.RSASignaturePadding left, System.Security.Cryptography.RSASignaturePadding right) => throw null; - public static bool operator ==(System.Security.Cryptography.RSASignaturePadding left, System.Security.Cryptography.RSASignaturePadding right) => throw null; - public bool Equals(System.Security.Cryptography.RSASignaturePadding other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public System.Security.Cryptography.RSASignaturePaddingMode Mode { get => throw null; } - public static System.Security.Cryptography.RSASignaturePadding Pkcs1 { get => throw null; } - public static System.Security.Cryptography.RSASignaturePadding Pss { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.RSASignaturePaddingMode` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum RSASignaturePaddingMode : int - { - Pkcs1 = 0, - Pss = 1, - } - - // Generated from `System.Security.Cryptography.RandomNumberGenerator` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class RandomNumberGenerator : System.IDisposable - { - public static System.Security.Cryptography.RandomNumberGenerator Create() => throw null; - public static System.Security.Cryptography.RandomNumberGenerator Create(string rngName) => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public static void Fill(System.Span data) => throw null; - public abstract void GetBytes(System.Byte[] data); - public virtual void GetBytes(System.Byte[] data, int offset, int count) => throw null; - public virtual void GetBytes(System.Span data) => throw null; - public static System.Byte[] GetBytes(int count) => throw null; - public static int GetInt32(int toExclusive) => throw null; - public static int GetInt32(int fromInclusive, int toExclusive) => throw null; - public virtual void GetNonZeroBytes(System.Byte[] data) => throw null; - public virtual void GetNonZeroBytes(System.Span data) => throw null; - protected RandomNumberGenerator() => throw null; - } - - // Generated from `System.Security.Cryptography.Rfc2898DeriveBytes` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class Rfc2898DeriveBytes : System.Security.Cryptography.DeriveBytes - { - public System.Byte[] CryptDeriveKey(string algname, string alghashname, int keySize, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Byte[] GetBytes(int cb) => throw null; - public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } - public int IterationCount { get => throw null; set => throw null; } - public static System.Byte[] Pbkdf2(System.Byte[] password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; - public static void Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, System.Span destination, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public static System.Byte[] Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; - public static void Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, System.Span destination, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public static System.Byte[] Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; - public static System.Byte[] Pbkdf2(string password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; - public override void Reset() => throw null; - public Rfc2898DeriveBytes(System.Byte[] password, System.Byte[] salt, int iterations) => throw null; - public Rfc2898DeriveBytes(System.Byte[] password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public Rfc2898DeriveBytes(string password, System.Byte[] salt) => throw null; - public Rfc2898DeriveBytes(string password, System.Byte[] salt, int iterations) => throw null; - public Rfc2898DeriveBytes(string password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public Rfc2898DeriveBytes(string password, int saltSize) => throw null; - public Rfc2898DeriveBytes(string password, int saltSize, int iterations) => throw null; - public Rfc2898DeriveBytes(string password, int saltSize, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public System.Byte[] Salt { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.Rijndael` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class Rijndael : System.Security.Cryptography.SymmetricAlgorithm - { - public static System.Security.Cryptography.Rijndael Create() => throw null; - public static System.Security.Cryptography.Rijndael Create(string algName) => throw null; - protected Rijndael() => throw null; - } - - // Generated from `System.Security.Cryptography.RijndaelManaged` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RijndaelManaged : System.Security.Cryptography.Rijndael - { - public override int BlockSize { get => throw null; set => throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override int FeedbackSize { get => throw null; set => throw null; } - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] IV { get => throw null; set => throw null; } - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } - public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } - public RijndaelManaged() => throw null; - } - - // Generated from `System.Security.Cryptography.SHA1` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SHA1 : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.SHA1 Create() => throw null; - public static System.Security.Cryptography.SHA1 Create(string hashName) => throw null; - public static System.Byte[] HashData(System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; - protected SHA1() => throw null; - public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA1Managed` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA1Managed : System.Security.Cryptography.SHA1 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA1Managed() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA256` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SHA256 : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.SHA256 Create() => throw null; - public static System.Security.Cryptography.SHA256 Create(string hashName) => throw null; - public static System.Byte[] HashData(System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; - protected SHA256() => throw null; - public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA256Managed` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA256Managed : System.Security.Cryptography.SHA256 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA256Managed() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA384` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SHA384 : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.SHA384 Create() => throw null; - public static System.Security.Cryptography.SHA384 Create(string hashName) => throw null; - public static System.Byte[] HashData(System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; - protected SHA384() => throw null; - public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA384Managed` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA384Managed : System.Security.Cryptography.SHA384 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA384Managed() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA512` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SHA512 : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.SHA512 Create() => throw null; - public static System.Security.Cryptography.SHA512 Create(string hashName) => throw null; - public static System.Byte[] HashData(System.Byte[] source) => throw null; - public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; - public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; - protected SHA512() => throw null; - public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA512Managed` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA512Managed : System.Security.Cryptography.SHA512 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA512Managed() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SignatureDescription` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SignatureDescription - { - public virtual System.Security.Cryptography.AsymmetricSignatureDeformatter CreateDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public virtual System.Security.Cryptography.HashAlgorithm CreateDigest() => throw null; - public virtual System.Security.Cryptography.AsymmetricSignatureFormatter CreateFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public string DeformatterAlgorithm { get => throw null; set => throw null; } - public string DigestAlgorithm { get => throw null; set => throw null; } - public string FormatterAlgorithm { get => throw null; set => throw null; } - public string KeyAlgorithm { get => throw null; set => throw null; } - public SignatureDescription() => throw null; - public SignatureDescription(System.Security.SecurityElement el) => throw null; - } - - // Generated from `System.Security.Cryptography.TripleDES` in `System.Security.Cryptography.Algorithms, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class TripleDES : System.Security.Cryptography.SymmetricAlgorithm - { - public static System.Security.Cryptography.TripleDES Create() => throw null; - public static System.Security.Cryptography.TripleDES Create(string str) => throw null; - public static bool IsWeakKey(System.Byte[] rgbKey) => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - protected TripleDES() => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Cng.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Cng.cs deleted file mode 100644 index 533b738e481..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Cng.cs +++ /dev/null @@ -1,452 +0,0 @@ -// This file contains auto-generated code. - -namespace Microsoft -{ - namespace Win32 - { - namespace SafeHandles - { - // Generated from `Microsoft.Win32.SafeHandles.SafeNCryptHandle` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SafeNCryptHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid - { - public override bool IsInvalid { get => throw null; } - protected override bool ReleaseHandle() => throw null; - protected abstract bool ReleaseNativeHandle(); - protected SafeNCryptHandle() : base(default(bool)) => throw null; - protected SafeNCryptHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) : base(default(bool)) => throw null; - } - - // Generated from `Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SafeNCryptKeyHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - protected override bool ReleaseNativeHandle() => throw null; - public SafeNCryptKeyHandle() => throw null; - public SafeNCryptKeyHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) => throw null; - } - - // Generated from `Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SafeNCryptProviderHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - protected override bool ReleaseNativeHandle() => throw null; - public SafeNCryptProviderHandle() => throw null; - } - - // Generated from `Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SafeNCryptSecretHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle - { - protected override bool ReleaseNativeHandle() => throw null; - public SafeNCryptSecretHandle() => throw null; - } - - } - } -} -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.AesCng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AesCng : System.Security.Cryptography.Aes - { - public AesCng() => throw null; - public AesCng(string keyName) => throw null; - public AesCng(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; - public AesCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.CngAlgorithm` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngAlgorithm : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.CngAlgorithm left, System.Security.Cryptography.CngAlgorithm right) => throw null; - public static bool operator ==(System.Security.Cryptography.CngAlgorithm left, System.Security.Cryptography.CngAlgorithm right) => throw null; - public string Algorithm { get => throw null; } - public CngAlgorithm(string algorithm) => throw null; - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellman { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP256 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP384 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP521 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDsa { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDsaP256 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDsaP384 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm ECDsaP521 { get => throw null; } - public bool Equals(System.Security.Cryptography.CngAlgorithm other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public static System.Security.Cryptography.CngAlgorithm MD5 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm Rsa { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm Sha1 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm Sha256 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm Sha384 { get => throw null; } - public static System.Security.Cryptography.CngAlgorithm Sha512 { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.CngAlgorithmGroup` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngAlgorithmGroup : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.CngAlgorithmGroup left, System.Security.Cryptography.CngAlgorithmGroup right) => throw null; - public static bool operator ==(System.Security.Cryptography.CngAlgorithmGroup left, System.Security.Cryptography.CngAlgorithmGroup right) => throw null; - public string AlgorithmGroup { get => throw null; } - public CngAlgorithmGroup(string algorithmGroup) => throw null; - public static System.Security.Cryptography.CngAlgorithmGroup DiffieHellman { get => throw null; } - public static System.Security.Cryptography.CngAlgorithmGroup Dsa { get => throw null; } - public static System.Security.Cryptography.CngAlgorithmGroup ECDiffieHellman { get => throw null; } - public static System.Security.Cryptography.CngAlgorithmGroup ECDsa { get => throw null; } - public bool Equals(System.Security.Cryptography.CngAlgorithmGroup other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public static System.Security.Cryptography.CngAlgorithmGroup Rsa { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.CngExportPolicies` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngExportPolicies : int - { - AllowArchiving = 4, - AllowExport = 1, - AllowPlaintextArchiving = 8, - AllowPlaintextExport = 2, - None = 0, - } - - // Generated from `System.Security.Cryptography.CngKey` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngKey : System.IDisposable - { - public System.Security.Cryptography.CngAlgorithm Algorithm { get => throw null; } - public System.Security.Cryptography.CngAlgorithmGroup AlgorithmGroup { get => throw null; } - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm) => throw null; - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string keyName) => throw null; - public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string keyName, System.Security.Cryptography.CngKeyCreationParameters creationParameters) => throw null; - public void Delete() => throw null; - public void Dispose() => throw null; - public static bool Exists(string keyName) => throw null; - public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; - public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions options) => throw null; - public System.Byte[] Export(System.Security.Cryptography.CngKeyBlobFormat format) => throw null; - public System.Security.Cryptography.CngExportPolicies ExportPolicy { get => throw null; } - public System.Security.Cryptography.CngProperty GetProperty(string name, System.Security.Cryptography.CngPropertyOptions options) => throw null; - public Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle Handle { get => throw null; } - public bool HasProperty(string name, System.Security.Cryptography.CngPropertyOptions options) => throw null; - public static System.Security.Cryptography.CngKey Import(System.Byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format) => throw null; - public static System.Security.Cryptography.CngKey Import(System.Byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format, System.Security.Cryptography.CngProvider provider) => throw null; - public bool IsEphemeral { get => throw null; } - public bool IsMachineKey { get => throw null; } - public string KeyName { get => throw null; } - public int KeySize { get => throw null; } - public System.Security.Cryptography.CngKeyUsages KeyUsage { get => throw null; } - public static System.Security.Cryptography.CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, System.Security.Cryptography.CngKeyHandleOpenOptions keyHandleOpenOptions) => throw null; - public static System.Security.Cryptography.CngKey Open(string keyName) => throw null; - public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; - public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; - public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } - public System.Security.Cryptography.CngProvider Provider { get => throw null; } - public Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle ProviderHandle { get => throw null; } - public void SetProperty(System.Security.Cryptography.CngProperty property) => throw null; - public System.Security.Cryptography.CngUIPolicy UIPolicy { get => throw null; } - public string UniqueName { get => throw null; } - } - - // Generated from `System.Security.Cryptography.CngKeyBlobFormat` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngKeyBlobFormat : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.CngKeyBlobFormat left, System.Security.Cryptography.CngKeyBlobFormat right) => throw null; - public static bool operator ==(System.Security.Cryptography.CngKeyBlobFormat left, System.Security.Cryptography.CngKeyBlobFormat right) => throw null; - public CngKeyBlobFormat(string format) => throw null; - public static System.Security.Cryptography.CngKeyBlobFormat EccFullPrivateBlob { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat EccFullPublicBlob { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat EccPrivateBlob { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat EccPublicBlob { get => throw null; } - public bool Equals(System.Security.Cryptography.CngKeyBlobFormat other) => throw null; - public override bool Equals(object obj) => throw null; - public string Format { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat GenericPrivateBlob { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat GenericPublicBlob { get => throw null; } - public override int GetHashCode() => throw null; - public static System.Security.Cryptography.CngKeyBlobFormat OpaqueTransportBlob { get => throw null; } - public static System.Security.Cryptography.CngKeyBlobFormat Pkcs8PrivateBlob { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.CngKeyCreationOptions` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngKeyCreationOptions : int - { - MachineKey = 32, - None = 0, - OverwriteExistingKey = 128, - } - - // Generated from `System.Security.Cryptography.CngKeyCreationParameters` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngKeyCreationParameters - { - public CngKeyCreationParameters() => throw null; - public System.Security.Cryptography.CngExportPolicies? ExportPolicy { get => throw null; set => throw null; } - public System.Security.Cryptography.CngKeyCreationOptions KeyCreationOptions { get => throw null; set => throw null; } - public System.Security.Cryptography.CngKeyUsages? KeyUsage { get => throw null; set => throw null; } - public System.Security.Cryptography.CngPropertyCollection Parameters { get => throw null; } - public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } - public System.Security.Cryptography.CngProvider Provider { get => throw null; set => throw null; } - public System.Security.Cryptography.CngUIPolicy UIPolicy { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.CngKeyHandleOpenOptions` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngKeyHandleOpenOptions : int - { - EphemeralKey = 1, - None = 0, - } - - // Generated from `System.Security.Cryptography.CngKeyOpenOptions` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngKeyOpenOptions : int - { - MachineKey = 32, - None = 0, - Silent = 64, - UserKey = 0, - } - - // Generated from `System.Security.Cryptography.CngKeyUsages` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngKeyUsages : int - { - AllUsages = 16777215, - Decryption = 1, - KeyAgreement = 4, - None = 0, - Signing = 2, - } - - // Generated from `System.Security.Cryptography.CngProperty` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct CngProperty : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) => throw null; - public static bool operator ==(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) => throw null; - // Stub generator skipped constructor - public CngProperty(string name, System.Byte[] value, System.Security.Cryptography.CngPropertyOptions options) => throw null; - public bool Equals(System.Security.Cryptography.CngProperty other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public System.Byte[] GetValue() => throw null; - public string Name { get => throw null; } - public System.Security.Cryptography.CngPropertyOptions Options { get => throw null; } - } - - // Generated from `System.Security.Cryptography.CngPropertyCollection` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngPropertyCollection : System.Collections.ObjectModel.Collection - { - public CngPropertyCollection() => throw null; - } - - // Generated from `System.Security.Cryptography.CngPropertyOptions` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngPropertyOptions : int - { - CustomProperty = 1073741824, - None = 0, - Persist = -2147483648, - } - - // Generated from `System.Security.Cryptography.CngProvider` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngProvider : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.CngProvider left, System.Security.Cryptography.CngProvider right) => throw null; - public static bool operator ==(System.Security.Cryptography.CngProvider left, System.Security.Cryptography.CngProvider right) => throw null; - public CngProvider(string provider) => throw null; - public bool Equals(System.Security.Cryptography.CngProvider other) => throw null; - public override bool Equals(object obj) => throw null; - public override int GetHashCode() => throw null; - public static System.Security.Cryptography.CngProvider MicrosoftPlatformCryptoProvider { get => throw null; } - public static System.Security.Cryptography.CngProvider MicrosoftSmartCardKeyStorageProvider { get => throw null; } - public static System.Security.Cryptography.CngProvider MicrosoftSoftwareKeyStorageProvider { get => throw null; } - public string Provider { get => throw null; } - public override string ToString() => throw null; - } - - // Generated from `System.Security.Cryptography.CngUIPolicy` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CngUIPolicy - { - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel) => throw null; - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName) => throw null; - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description) => throw null; - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description, string useContext) => throw null; - public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description, string useContext, string creationTitle) => throw null; - public string CreationTitle { get => throw null; } - public string Description { get => throw null; } - public string FriendlyName { get => throw null; } - public System.Security.Cryptography.CngUIProtectionLevels ProtectionLevel { get => throw null; } - public string UseContext { get => throw null; } - } - - // Generated from `System.Security.Cryptography.CngUIProtectionLevels` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CngUIProtectionLevels : int - { - ForceHighProtection = 2, - None = 0, - ProtectKey = 1, - } - - // Generated from `System.Security.Cryptography.DSACng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DSACng : System.Security.Cryptography.DSA - { - public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; - public DSACng() => throw null; - public DSACng(System.Security.Cryptography.CngKey key) => throw null; - public DSACng(int keySize) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; - public System.Security.Cryptography.CngKey Key { get => throw null; } - public override string KeyExchangeAlgorithm { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override string SignatureAlgorithm { get => throw null; } - public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.ECDiffieHellmanCng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ECDiffieHellmanCng : System.Security.Cryptography.ECDiffieHellman - { - public override System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public override System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.CngKey otherPartyPublicKey) => throw null; - public override System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; - public override System.Byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Byte[] prfLabel, System.Byte[] prfSeed) => throw null; - public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.CngKey otherPartyPublicKey) => throw null; - public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; - protected override void Dispose(bool disposing) => throw null; - public ECDiffieHellmanCng() => throw null; - public ECDiffieHellmanCng(System.Security.Cryptography.CngKey key) => throw null; - public ECDiffieHellmanCng(System.Security.Cryptography.ECCurve curve) => throw null; - public ECDiffieHellmanCng(int keySize) => throw null; - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) => throw null; - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get => throw null; set => throw null; } - public System.Byte[] HmacKey { get => throw null; set => throw null; } - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public System.Security.Cryptography.CngKey Key { get => throw null; } - public System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public System.Byte[] Label { get => throw null; set => throw null; } - public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get => throw null; } - public System.Byte[] SecretAppend { get => throw null; set => throw null; } - public System.Byte[] SecretPrepend { get => throw null; set => throw null; } - public System.Byte[] Seed { get => throw null; set => throw null; } - public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) => throw null; - public bool UseSecretAgreementAsHmacKey { get => throw null; } - } - - // Generated from `System.Security.Cryptography.ECDiffieHellmanCngPublicKey` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ECDiffieHellmanCngPublicKey : System.Security.Cryptography.ECDiffieHellmanPublicKey - { - public System.Security.Cryptography.CngKeyBlobFormat BlobFormat { get => throw null; } - protected override void Dispose(bool disposing) => throw null; - public override System.Security.Cryptography.ECParameters ExportExplicitParameters() => throw null; - public override System.Security.Cryptography.ECParameters ExportParameters() => throw null; - public static System.Security.Cryptography.ECDiffieHellmanPublicKey FromByteArray(System.Byte[] publicKeyBlob, System.Security.Cryptography.CngKeyBlobFormat format) => throw null; - public static System.Security.Cryptography.ECDiffieHellmanCngPublicKey FromXmlString(string xml) => throw null; - public System.Security.Cryptography.CngKey Import() => throw null; - public override string ToXmlString() => throw null; - } - - // Generated from `System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum ECDiffieHellmanKeyDerivationFunction : int - { - Hash = 0, - Hmac = 1, - Tls = 2, - } - - // Generated from `System.Security.Cryptography.ECDsaCng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ECDsaCng : System.Security.Cryptography.ECDsa - { - protected override void Dispose(bool disposing) => throw null; - public ECDsaCng() => throw null; - public ECDsaCng(System.Security.Cryptography.CngKey key) => throw null; - public ECDsaCng(System.Security.Cryptography.ECCurve curve) => throw null; - public ECDsaCng(int keySize) => throw null; - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) => throw null; - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get => throw null; set => throw null; } - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public System.Security.Cryptography.CngKey Key { get => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public System.Byte[] SignData(System.Byte[] data) => throw null; - public System.Byte[] SignData(System.Byte[] data, int offset, int count) => throw null; - public System.Byte[] SignData(System.IO.Stream data) => throw null; - public override System.Byte[] SignHash(System.Byte[] hash) => throw null; - public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) => throw null; - public bool VerifyData(System.Byte[] data, System.Byte[] signature) => throw null; - public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature) => throw null; - public bool VerifyData(System.IO.Stream data, System.Byte[] signature) => throw null; - public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature) => throw null; - } - - // Generated from `System.Security.Cryptography.ECKeyXmlFormat` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum ECKeyXmlFormat : int - { - Rfc4050 = 0, - } - - // Generated from `System.Security.Cryptography.RSACng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSACng : System.Security.Cryptography.RSA - { - public override System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; - public System.Security.Cryptography.CngKey Key { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public RSACng() => throw null; - public RSACng(System.Security.Cryptography.CngKey key) => throw null; - public RSACng(int keySize) => throw null; - public override System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - } - - // Generated from `System.Security.Cryptography.TripleDESCng` in `System.Security.Cryptography.Cng, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class TripleDESCng : System.Security.Cryptography.TripleDES - { - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public TripleDESCng() => throw null; - public TripleDESCng(string keyName) => throw null; - public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; - public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Csp.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Csp.cs deleted file mode 100644 index 47a6941fd1e..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Csp.cs +++ /dev/null @@ -1,308 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.AesCryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AesCryptoServiceProvider : System.Security.Cryptography.Aes - { - public AesCryptoServiceProvider() => throw null; - public override int BlockSize { get => throw null; set => throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override int FeedbackSize { get => throw null; set => throw null; } - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] IV { get => throw null; set => throw null; } - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } - public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.CspKeyContainerInfo` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CspKeyContainerInfo - { - public bool Accessible { get => throw null; } - public CspKeyContainerInfo(System.Security.Cryptography.CspParameters parameters) => throw null; - public bool Exportable { get => throw null; } - public bool HardwareDevice { get => throw null; } - public string KeyContainerName { get => throw null; } - public System.Security.Cryptography.KeyNumber KeyNumber { get => throw null; } - public bool MachineKeyStore { get => throw null; } - public bool Protected { get => throw null; } - public string ProviderName { get => throw null; } - public int ProviderType { get => throw null; } - public bool RandomlyGenerated { get => throw null; } - public bool Removable { get => throw null; } - public string UniqueKeyContainerName { get => throw null; } - } - - // Generated from `System.Security.Cryptography.CspParameters` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CspParameters - { - public CspParameters() => throw null; - public CspParameters(int dwTypeIn) => throw null; - public CspParameters(int dwTypeIn, string strProviderNameIn) => throw null; - public CspParameters(int dwTypeIn, string strProviderNameIn, string strContainerNameIn) => throw null; - public System.Security.Cryptography.CspProviderFlags Flags { get => throw null; set => throw null; } - public string KeyContainerName; - public int KeyNumber; - public System.Security.SecureString KeyPassword { get => throw null; set => throw null; } - public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } - public string ProviderName; - public int ProviderType; - } - - // Generated from `System.Security.Cryptography.CspProviderFlags` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum CspProviderFlags : int - { - CreateEphemeralKey = 128, - NoFlags = 0, - NoPrompt = 64, - UseArchivableKey = 16, - UseDefaultKeyContainer = 2, - UseExistingKey = 8, - UseMachineKeyStore = 1, - UseNonExportableKey = 4, - UseUserProtectedKey = 32, - } - - // Generated from `System.Security.Cryptography.DESCryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DESCryptoServiceProvider : System.Security.Cryptography.DES - { - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public DESCryptoServiceProvider() => throw null; - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - } - - // Generated from `System.Security.Cryptography.DSACryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DSACryptoServiceProvider : System.Security.Cryptography.DSA, System.Security.Cryptography.ICspAsymmetricAlgorithm - { - public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; - public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get => throw null; } - public DSACryptoServiceProvider() => throw null; - public DSACryptoServiceProvider(System.Security.Cryptography.CspParameters parameters) => throw null; - public DSACryptoServiceProvider(int dwKeySize) => throw null; - public DSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters parameters) => throw null; - protected override void Dispose(bool disposing) => throw null; - public System.Byte[] ExportCspBlob(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public void ImportCspBlob(System.Byte[] keyBlob) => throw null; - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; - public override string KeyExchangeAlgorithm { get => throw null; } - public override int KeySize { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public bool PersistKeyInCsp { get => throw null; set => throw null; } - public bool PublicOnly { get => throw null; } - public System.Byte[] SignData(System.Byte[] buffer) => throw null; - public System.Byte[] SignData(System.Byte[] buffer, int offset, int count) => throw null; - public System.Byte[] SignData(System.IO.Stream inputStream) => throw null; - public System.Byte[] SignHash(System.Byte[] rgbHash, string str) => throw null; - public override string SignatureAlgorithm { get => throw null; } - public static bool UseMachineKeyStore { get => throw null; set => throw null; } - public bool VerifyData(System.Byte[] rgbData, System.Byte[] rgbSignature) => throw null; - public bool VerifyHash(System.Byte[] rgbHash, string str, System.Byte[] rgbSignature) => throw null; - public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.ICspAsymmetricAlgorithm` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public interface ICspAsymmetricAlgorithm - { - System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get; } - System.Byte[] ExportCspBlob(bool includePrivateParameters); - void ImportCspBlob(System.Byte[] rawData); - } - - // Generated from `System.Security.Cryptography.KeyNumber` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum KeyNumber : int - { - Exchange = 1, - Signature = 2, - } - - // Generated from `System.Security.Cryptography.MD5CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class MD5CryptoServiceProvider : System.Security.Cryptography.MD5 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public MD5CryptoServiceProvider() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.PasswordDeriveBytes` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class PasswordDeriveBytes : System.Security.Cryptography.DeriveBytes - { - public System.Byte[] CryptDeriveKey(string algname, string alghashname, int keySize, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Byte[] GetBytes(int cb) => throw null; - public string HashName { get => throw null; set => throw null; } - public int IterationCount { get => throw null; set => throw null; } - public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt) => throw null; - public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, System.Security.Cryptography.CspParameters cspParams) => throw null; - public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, string hashName, int iterations) => throw null; - public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, string hashName, int iterations, System.Security.Cryptography.CspParameters cspParams) => throw null; - public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt) => throw null; - public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, System.Security.Cryptography.CspParameters cspParams) => throw null; - public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, string strHashName, int iterations) => throw null; - public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters cspParams) => throw null; - public override void Reset() => throw null; - public System.Byte[] Salt { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.RC2CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RC2CryptoServiceProvider : System.Security.Cryptography.RC2 - { - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override int EffectiveKeySize { get => throw null; set => throw null; } - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public RC2CryptoServiceProvider() => throw null; - public bool UseSalt { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.RNGCryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RNGCryptoServiceProvider : System.Security.Cryptography.RandomNumberGenerator - { - protected override void Dispose(bool disposing) => throw null; - public override void GetBytes(System.Byte[] data) => throw null; - public override void GetBytes(System.Byte[] data, int offset, int count) => throw null; - public override void GetBytes(System.Span data) => throw null; - public override void GetNonZeroBytes(System.Byte[] data) => throw null; - public override void GetNonZeroBytes(System.Span data) => throw null; - public RNGCryptoServiceProvider() => throw null; - public RNGCryptoServiceProvider(System.Byte[] rgb) => throw null; - public RNGCryptoServiceProvider(System.Security.Cryptography.CspParameters cspParams) => throw null; - public RNGCryptoServiceProvider(string str) => throw null; - } - - // Generated from `System.Security.Cryptography.RSACryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSACryptoServiceProvider : System.Security.Cryptography.RSA, System.Security.Cryptography.ICspAsymmetricAlgorithm - { - public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get => throw null; } - public override System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public System.Byte[] Decrypt(System.Byte[] rgb, bool fOAEP) => throw null; - public override System.Byte[] DecryptValue(System.Byte[] rgb) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public System.Byte[] Encrypt(System.Byte[] rgb, bool fOAEP) => throw null; - public override System.Byte[] EncryptValue(System.Byte[] rgb) => throw null; - public System.Byte[] ExportCspBlob(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public void ImportCspBlob(System.Byte[] keyBlob) => throw null; - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; - public override string KeyExchangeAlgorithm { get => throw null; } - public override int KeySize { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public bool PersistKeyInCsp { get => throw null; set => throw null; } - public bool PublicOnly { get => throw null; } - public RSACryptoServiceProvider() => throw null; - public RSACryptoServiceProvider(System.Security.Cryptography.CspParameters parameters) => throw null; - public RSACryptoServiceProvider(int dwKeySize) => throw null; - public RSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters parameters) => throw null; - public System.Byte[] SignData(System.Byte[] buffer, int offset, int count, object halg) => throw null; - public System.Byte[] SignData(System.Byte[] buffer, object halg) => throw null; - public System.Byte[] SignData(System.IO.Stream inputStream, object halg) => throw null; - public override System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public System.Byte[] SignHash(System.Byte[] rgbHash, string str) => throw null; - public override string SignatureAlgorithm { get => throw null; } - public static bool UseMachineKeyStore { get => throw null; set => throw null; } - public bool VerifyData(System.Byte[] buffer, object halg, System.Byte[] signature) => throw null; - public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public bool VerifyHash(System.Byte[] rgbHash, string str, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA1CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA1CryptoServiceProvider : System.Security.Cryptography.SHA1 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA1CryptoServiceProvider() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA256CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA256CryptoServiceProvider : System.Security.Cryptography.SHA256 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA256CryptoServiceProvider() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA384CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA384CryptoServiceProvider : System.Security.Cryptography.SHA384 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA384CryptoServiceProvider() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.SHA512CryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SHA512CryptoServiceProvider : System.Security.Cryptography.SHA512 - { - protected override void Dispose(bool disposing) => throw null; - protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public override void Initialize() => throw null; - public SHA512CryptoServiceProvider() => throw null; - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.TripleDESCryptoServiceProvider` in `System.Security.Cryptography.Csp, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class TripleDESCryptoServiceProvider : System.Security.Cryptography.TripleDES - { - public override int BlockSize { get => throw null; set => throw null; } - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override int FeedbackSize { get => throw null; set => throw null; } - public override void GenerateIV() => throw null; - public override void GenerateKey() => throw null; - public override System.Byte[] IV { get => throw null; set => throw null; } - public override System.Byte[] Key { get => throw null; set => throw null; } - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } - public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } - public TripleDESCryptoServiceProvider() => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Encoding.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Encoding.cs deleted file mode 100644 index 67908c660ac..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Encoding.cs +++ /dev/null @@ -1,168 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.AsnEncodedData` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AsnEncodedData - { - protected AsnEncodedData() => throw null; - public AsnEncodedData(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public AsnEncodedData(System.Byte[] rawData) => throw null; - public AsnEncodedData(System.Security.Cryptography.Oid oid, System.Byte[] rawData) => throw null; - public AsnEncodedData(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData) => throw null; - public AsnEncodedData(System.ReadOnlySpan rawData) => throw null; - public AsnEncodedData(string oid, System.Byte[] rawData) => throw null; - public AsnEncodedData(string oid, System.ReadOnlySpan rawData) => throw null; - public virtual void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public virtual string Format(bool multiLine) => throw null; - public System.Security.Cryptography.Oid Oid { get => throw null; set => throw null; } - public System.Byte[] RawData { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.AsnEncodedDataCollection` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AsnEncodedDataCollection : System.Collections.ICollection, System.Collections.IEnumerable - { - public int Add(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public AsnEncodedDataCollection() => throw null; - public AsnEncodedDataCollection(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(System.Security.Cryptography.AsnEncodedData[] array, int index) => throw null; - public int Count { get => throw null; } - public System.Security.Cryptography.AsnEncodedDataEnumerator GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public bool IsSynchronized { get => throw null; } - public System.Security.Cryptography.AsnEncodedData this[int index] { get => throw null; } - public void Remove(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public object SyncRoot { get => throw null; } - } - - // Generated from `System.Security.Cryptography.AsnEncodedDataEnumerator` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class AsnEncodedDataEnumerator : System.Collections.IEnumerator - { - public System.Security.Cryptography.AsnEncodedData Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - public bool MoveNext() => throw null; - public void Reset() => throw null; - } - - // Generated from `System.Security.Cryptography.FromBase64Transform` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class FromBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform - { - public virtual bool CanReuseTransform { get => throw null; } - public bool CanTransformMultipleBlocks { get => throw null; } - public void Clear() => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public FromBase64Transform() => throw null; - public FromBase64Transform(System.Security.Cryptography.FromBase64TransformMode whitespaces) => throw null; - public int InputBlockSize { get => throw null; } - public int OutputBlockSize { get => throw null; } - public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; - public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; - // ERR: Stub generator didn't handle member: ~FromBase64Transform - } - - // Generated from `System.Security.Cryptography.FromBase64TransformMode` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum FromBase64TransformMode : int - { - DoNotIgnoreWhiteSpaces = 1, - IgnoreWhiteSpaces = 0, - } - - // Generated from `System.Security.Cryptography.Oid` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class Oid - { - public string FriendlyName { get => throw null; set => throw null; } - public static System.Security.Cryptography.Oid FromFriendlyName(string friendlyName, System.Security.Cryptography.OidGroup group) => throw null; - public static System.Security.Cryptography.Oid FromOidValue(string oidValue, System.Security.Cryptography.OidGroup group) => throw null; - public Oid() => throw null; - public Oid(System.Security.Cryptography.Oid oid) => throw null; - public Oid(string oid) => throw null; - public Oid(string value, string friendlyName) => throw null; - public string Value { get => throw null; set => throw null; } - } - - // Generated from `System.Security.Cryptography.OidCollection` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class OidCollection : System.Collections.ICollection, System.Collections.IEnumerable - { - public int Add(System.Security.Cryptography.Oid oid) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(System.Security.Cryptography.Oid[] array, int index) => throw null; - public int Count { get => throw null; } - public System.Security.Cryptography.OidEnumerator GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public bool IsSynchronized { get => throw null; } - public System.Security.Cryptography.Oid this[int index] { get => throw null; } - public System.Security.Cryptography.Oid this[string oid] { get => throw null; } - public OidCollection() => throw null; - public object SyncRoot { get => throw null; } - } - - // Generated from `System.Security.Cryptography.OidEnumerator` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class OidEnumerator : System.Collections.IEnumerator - { - public System.Security.Cryptography.Oid Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - public bool MoveNext() => throw null; - public void Reset() => throw null; - } - - // Generated from `System.Security.Cryptography.OidGroup` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum OidGroup : int - { - All = 0, - Attribute = 5, - EncryptionAlgorithm = 2, - EnhancedKeyUsage = 7, - ExtensionOrAttribute = 6, - HashAlgorithm = 1, - KeyDerivationFunction = 10, - Policy = 8, - PublicKeyAlgorithm = 3, - SignatureAlgorithm = 4, - Template = 9, - } - - // Generated from `System.Security.Cryptography.PemEncoding` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class PemEncoding - { - public static System.Security.Cryptography.PemFields Find(System.ReadOnlySpan pemData) => throw null; - public static int GetEncodedSize(int labelLength, int dataLength) => throw null; - public static bool TryFind(System.ReadOnlySpan pemData, out System.Security.Cryptography.PemFields fields) => throw null; - public static bool TryWrite(System.ReadOnlySpan label, System.ReadOnlySpan data, System.Span destination, out int charsWritten) => throw null; - public static System.Char[] Write(System.ReadOnlySpan label, System.ReadOnlySpan data) => throw null; - } - - // Generated from `System.Security.Cryptography.PemFields` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct PemFields - { - public System.Range Base64Data { get => throw null; } - public int DecodedDataLength { get => throw null; } - public System.Range Label { get => throw null; } - public System.Range Location { get => throw null; } - // Stub generator skipped constructor - } - - // Generated from `System.Security.Cryptography.ToBase64Transform` in `System.Security.Cryptography.Encoding, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ToBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform - { - public virtual bool CanReuseTransform { get => throw null; } - public bool CanTransformMultipleBlocks { get => throw null; } - public void Clear() => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public int InputBlockSize { get => throw null; } - public int OutputBlockSize { get => throw null; } - public ToBase64Transform() => throw null; - public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; - public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; - // ERR: Stub generator didn't handle member: ~ToBase64Transform - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.OpenSsl.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.OpenSsl.cs deleted file mode 100644 index a3e404fc36b..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.OpenSsl.cs +++ /dev/null @@ -1,106 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.DSAOpenSsl` in `System.Security.Cryptography.OpenSsl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class DSAOpenSsl : System.Security.Cryptography.DSA - { - public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; - public DSAOpenSsl() => throw null; - public DSAOpenSsl(System.Security.Cryptography.DSAParameters parameters) => throw null; - public DSAOpenSsl(System.IntPtr handle) => throw null; - public DSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; - public DSAOpenSsl(int keySize) => throw null; - protected override void Dispose(bool disposing) => throw null; - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; - public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; - public override int KeySize { set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; - } - - // Generated from `System.Security.Cryptography.ECDiffieHellmanOpenSsl` in `System.Security.Cryptography.OpenSsl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ECDiffieHellmanOpenSsl : System.Security.Cryptography.ECDiffieHellman - { - public override System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public override System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; - public override System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; - public override System.Byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Byte[] prfLabel, System.Byte[] prfSeed) => throw null; - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; - public ECDiffieHellmanOpenSsl() => throw null; - public ECDiffieHellmanOpenSsl(System.Security.Cryptography.ECCurve curve) => throw null; - public ECDiffieHellmanOpenSsl(System.IntPtr handle) => throw null; - public ECDiffieHellmanOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; - public ECDiffieHellmanOpenSsl(int keySize) => throw null; - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get => throw null; } - } - - // Generated from `System.Security.Cryptography.ECDsaOpenSsl` in `System.Security.Cryptography.OpenSsl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class ECDsaOpenSsl : System.Security.Cryptography.ECDsa - { - protected override void Dispose(bool disposing) => throw null; - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; - public ECDsaOpenSsl() => throw null; - public ECDsaOpenSsl(System.Security.Cryptography.ECCurve curve) => throw null; - public ECDsaOpenSsl(System.IntPtr handle) => throw null; - public ECDsaOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; - public ECDsaOpenSsl(int keySize) => throw null; - public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; - public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; - public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; - public override int KeySize { get => throw null; set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public override System.Byte[] SignHash(System.Byte[] hash) => throw null; - public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature) => throw null; - } - - // Generated from `System.Security.Cryptography.RSAOpenSsl` in `System.Security.Cryptography.OpenSsl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class RSAOpenSsl : System.Security.Cryptography.RSA - { - public override System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - protected override void Dispose(bool disposing) => throw null; - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; - public override System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; - public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; - protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; - public override int KeySize { set => throw null; } - public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - public RSAOpenSsl() => throw null; - public RSAOpenSsl(System.IntPtr handle) => throw null; - public RSAOpenSsl(System.Security.Cryptography.RSAParameters parameters) => throw null; - public RSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; - public RSAOpenSsl(int keySize) => throw null; - public override System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - } - - // Generated from `System.Security.Cryptography.SafeEvpPKeyHandle` in `System.Security.Cryptography.OpenSsl, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SafeEvpPKeyHandle : System.Runtime.InteropServices.SafeHandle - { - public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateHandle() => throw null; - public override bool IsInvalid { get => throw null; } - public static System.Int64 OpenSslVersion { get => throw null; } - protected override bool ReleaseHandle() => throw null; - public SafeEvpPKeyHandle() : base(default(System.IntPtr), default(bool)) => throw null; - public SafeEvpPKeyHandle(System.IntPtr handle, bool ownsHandle) : base(default(System.IntPtr), default(bool)) => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Primitives.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Primitives.cs deleted file mode 100644 index b638b8da71d..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.Primitives.cs +++ /dev/null @@ -1,314 +0,0 @@ -// This file contains auto-generated code. - -namespace System -{ - namespace Security - { - namespace Cryptography - { - // Generated from `System.Security.Cryptography.AsymmetricAlgorithm` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class AsymmetricAlgorithm : System.IDisposable - { - protected AsymmetricAlgorithm() => throw null; - public void Clear() => throw null; - public static System.Security.Cryptography.AsymmetricAlgorithm Create() => throw null; - public static System.Security.Cryptography.AsymmetricAlgorithm Create(string algName) => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public virtual System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; - public virtual System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; - public virtual System.Byte[] ExportPkcs8PrivateKey() => throw null; - public virtual System.Byte[] ExportSubjectPublicKeyInfo() => throw null; - public virtual void FromXmlString(string xmlString) => throw null; - public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; - public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; - public virtual void ImportFromPem(System.ReadOnlySpan input) => throw null; - public virtual void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public virtual string KeyExchangeAlgorithm { get => throw null; } - public virtual int KeySize { get => throw null; set => throw null; } - protected int KeySizeValue; - public virtual System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; - public virtual string SignatureAlgorithm { get => throw null; } - public virtual string ToXmlString(bool includePrivateParameters) => throw null; - public virtual bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public virtual bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; - public virtual bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; - public virtual bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.CipherMode` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum CipherMode : int - { - CBC = 1, - CFB = 4, - CTS = 5, - ECB = 2, - OFB = 3, - } - - // Generated from `System.Security.Cryptography.CryptoStream` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CryptoStream : System.IO.Stream, System.IDisposable - { - public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; - public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; - public override bool CanRead { get => throw null; } - public override bool CanSeek { get => throw null; } - public override bool CanWrite { get => throw null; } - public void Clear() => throw null; - public override void CopyTo(System.IO.Stream destination, int bufferSize) => throw null; - public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => throw null; - public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICryptoTransform transform, System.Security.Cryptography.CryptoStreamMode mode) => throw null; - public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICryptoTransform transform, System.Security.Cryptography.CryptoStreamMode mode, bool leaveOpen) => throw null; - protected override void Dispose(bool disposing) => throw null; - public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null; - public override int EndRead(System.IAsyncResult asyncResult) => throw null; - public override void EndWrite(System.IAsyncResult asyncResult) => throw null; - public override void Flush() => throw null; - public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null; - public void FlushFinalBlock() => throw null; - public System.Threading.Tasks.ValueTask FlushFinalBlockAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; - public bool HasFlushedFinalBlock { get => throw null; } - public override System.Int64 Length { get => throw null; } - public override System.Int64 Position { get => throw null; set => throw null; } - public override int Read(System.Byte[] buffer, int offset, int count) => throw null; - public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; - public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; - public override int ReadByte() => throw null; - public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null; - public override void SetLength(System.Int64 value) => throw null; - public override void Write(System.Byte[] buffer, int offset, int count) => throw null; - public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; - public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; - public override void WriteByte(System.Byte value) => throw null; - } - - // Generated from `System.Security.Cryptography.CryptoStreamMode` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum CryptoStreamMode : int - { - Read = 0, - Write = 1, - } - - // Generated from `System.Security.Cryptography.CryptographicOperations` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class CryptographicOperations - { - public static bool FixedTimeEquals(System.ReadOnlySpan left, System.ReadOnlySpan right) => throw null; - public static void ZeroMemory(System.Span buffer) => throw null; - } - - // Generated from `System.Security.Cryptography.CryptographicUnexpectedOperationException` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CryptographicUnexpectedOperationException : System.Security.Cryptography.CryptographicException - { - public CryptographicUnexpectedOperationException() => throw null; - protected CryptographicUnexpectedOperationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; - public CryptographicUnexpectedOperationException(string message) => throw null; - public CryptographicUnexpectedOperationException(string message, System.Exception inner) => throw null; - public CryptographicUnexpectedOperationException(string format, string insert) => throw null; - } - - // Generated from `System.Security.Cryptography.HMAC` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class HMAC : System.Security.Cryptography.KeyedHashAlgorithm - { - protected int BlockSizeValue { get => throw null; set => throw null; } - public static System.Security.Cryptography.HMAC Create() => throw null; - public static System.Security.Cryptography.HMAC Create(string algorithmName) => throw null; - protected override void Dispose(bool disposing) => throw null; - protected HMAC() => throw null; - protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; - protected override void HashCore(System.ReadOnlySpan source) => throw null; - protected override System.Byte[] HashFinal() => throw null; - public string HashName { get => throw null; set => throw null; } - public override void Initialize() => throw null; - public override System.Byte[] Key { get => throw null; set => throw null; } - protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HashAlgorithm` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class HashAlgorithm : System.IDisposable, System.Security.Cryptography.ICryptoTransform - { - public virtual bool CanReuseTransform { get => throw null; } - public virtual bool CanTransformMultipleBlocks { get => throw null; } - public void Clear() => throw null; - public System.Byte[] ComputeHash(System.Byte[] buffer) => throw null; - public System.Byte[] ComputeHash(System.Byte[] buffer, int offset, int count) => throw null; - public System.Byte[] ComputeHash(System.IO.Stream inputStream) => throw null; - public System.Threading.Tasks.Task ComputeHashAsync(System.IO.Stream inputStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; - public static System.Security.Cryptography.HashAlgorithm Create() => throw null; - public static System.Security.Cryptography.HashAlgorithm Create(string hashName) => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public virtual System.Byte[] Hash { get => throw null; } - protected HashAlgorithm() => throw null; - protected abstract void HashCore(System.Byte[] array, int ibStart, int cbSize); - protected virtual void HashCore(System.ReadOnlySpan source) => throw null; - protected abstract System.Byte[] HashFinal(); - public virtual int HashSize { get => throw null; } - protected int HashSizeValue; - protected internal System.Byte[] HashValue; - public abstract void Initialize(); - public virtual int InputBlockSize { get => throw null; } - public virtual int OutputBlockSize { get => throw null; } - protected int State; - public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; - public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; - public bool TryComputeHash(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; - protected virtual bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.HashAlgorithmName` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct HashAlgorithmName : System.IEquatable - { - public static bool operator !=(System.Security.Cryptography.HashAlgorithmName left, System.Security.Cryptography.HashAlgorithmName right) => throw null; - public static bool operator ==(System.Security.Cryptography.HashAlgorithmName left, System.Security.Cryptography.HashAlgorithmName right) => throw null; - public bool Equals(System.Security.Cryptography.HashAlgorithmName other) => throw null; - public override bool Equals(object obj) => throw null; - public static System.Security.Cryptography.HashAlgorithmName FromOid(string oidValue) => throw null; - public override int GetHashCode() => throw null; - // Stub generator skipped constructor - public HashAlgorithmName(string name) => throw null; - public static System.Security.Cryptography.HashAlgorithmName MD5 { get => throw null; } - public string Name { get => throw null; } - public static System.Security.Cryptography.HashAlgorithmName SHA1 { get => throw null; } - public static System.Security.Cryptography.HashAlgorithmName SHA256 { get => throw null; } - public static System.Security.Cryptography.HashAlgorithmName SHA384 { get => throw null; } - public static System.Security.Cryptography.HashAlgorithmName SHA512 { get => throw null; } - public override string ToString() => throw null; - public static bool TryFromOid(string oidValue, out System.Security.Cryptography.HashAlgorithmName value) => throw null; - } - - // Generated from `System.Security.Cryptography.ICryptoTransform` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public interface ICryptoTransform : System.IDisposable - { - bool CanReuseTransform { get; } - bool CanTransformMultipleBlocks { get; } - int InputBlockSize { get; } - int OutputBlockSize { get; } - int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset); - System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount); - } - - // Generated from `System.Security.Cryptography.KeySizes` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class KeySizes - { - public KeySizes(int minSize, int maxSize, int skipSize) => throw null; - public int MaxSize { get => throw null; } - public int MinSize { get => throw null; } - public int SkipSize { get => throw null; } - } - - // Generated from `System.Security.Cryptography.KeyedHashAlgorithm` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class KeyedHashAlgorithm : System.Security.Cryptography.HashAlgorithm - { - public static System.Security.Cryptography.KeyedHashAlgorithm Create() => throw null; - public static System.Security.Cryptography.KeyedHashAlgorithm Create(string algName) => throw null; - protected override void Dispose(bool disposing) => throw null; - public virtual System.Byte[] Key { get => throw null; set => throw null; } - protected System.Byte[] KeyValue; - protected KeyedHashAlgorithm() => throw null; - } - - // Generated from `System.Security.Cryptography.PaddingMode` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum PaddingMode : int - { - ANSIX923 = 4, - ISO10126 = 5, - None = 1, - PKCS7 = 2, - Zeros = 3, - } - - // Generated from `System.Security.Cryptography.PbeEncryptionAlgorithm` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum PbeEncryptionAlgorithm : int - { - Aes128Cbc = 1, - Aes192Cbc = 2, - Aes256Cbc = 3, - TripleDes3KeyPkcs12 = 4, - Unknown = 0, - } - - // Generated from `System.Security.Cryptography.PbeParameters` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class PbeParameters - { - public System.Security.Cryptography.PbeEncryptionAlgorithm EncryptionAlgorithm { get => throw null; } - public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } - public int IterationCount { get => throw null; } - public PbeParameters(System.Security.Cryptography.PbeEncryptionAlgorithm encryptionAlgorithm, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int iterationCount) => throw null; - } - - // Generated from `System.Security.Cryptography.SymmetricAlgorithm` in `System.Security.Cryptography.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class SymmetricAlgorithm : System.IDisposable - { - public virtual int BlockSize { get => throw null; set => throw null; } - protected int BlockSizeValue; - public void Clear() => throw null; - public static System.Security.Cryptography.SymmetricAlgorithm Create() => throw null; - public static System.Security.Cryptography.SymmetricAlgorithm Create(string algName) => throw null; - public virtual System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; - public abstract System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV); - public virtual System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; - public abstract System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV); - public System.Byte[] DecryptCbc(System.Byte[] ciphertext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public System.Byte[] DecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public int DecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public System.Byte[] DecryptCfb(System.Byte[] ciphertext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public System.Byte[] DecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public int DecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public System.Byte[] DecryptEcb(System.Byte[] ciphertext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public System.Byte[] DecryptEcb(System.ReadOnlySpan ciphertext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public int DecryptEcb(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public System.Byte[] EncryptCbc(System.Byte[] plaintext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public System.Byte[] EncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public int EncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public System.Byte[] EncryptCfb(System.Byte[] plaintext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public System.Byte[] EncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public int EncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public System.Byte[] EncryptEcb(System.Byte[] plaintext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public System.Byte[] EncryptEcb(System.ReadOnlySpan plaintext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public int EncryptEcb(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public virtual int FeedbackSize { get => throw null; set => throw null; } - protected int FeedbackSizeValue; - public abstract void GenerateIV(); - public abstract void GenerateKey(); - public int GetCiphertextLengthCbc(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - public int GetCiphertextLengthCfb(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - public int GetCiphertextLengthEcb(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode) => throw null; - public virtual System.Byte[] IV { get => throw null; set => throw null; } - protected System.Byte[] IVValue; - public virtual System.Byte[] Key { get => throw null; set => throw null; } - public virtual int KeySize { get => throw null; set => throw null; } - protected int KeySizeValue; - protected System.Byte[] KeyValue; - public virtual System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } - protected System.Security.Cryptography.KeySizes[] LegalBlockSizesValue; - public virtual System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } - protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; - public virtual System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } - protected System.Security.Cryptography.CipherMode ModeValue; - public virtual System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } - protected System.Security.Cryptography.PaddingMode PaddingValue; - protected SymmetricAlgorithm() => throw null; - public bool TryDecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - protected virtual bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - public bool TryDecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - protected virtual bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; - public bool TryDecryptEcb(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - protected virtual bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - public bool TryEncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; - protected virtual bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - public bool TryEncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; - protected virtual bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; - public bool TryEncryptEcb(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - protected virtual bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; - public bool ValidKeySize(int bitLength) => throw null; - } - - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.X509Certificates.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.X509Certificates.cs deleted file mode 100644 index 443f319acb5..00000000000 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.X509Certificates.cs +++ /dev/null @@ -1,732 +0,0 @@ -// This file contains auto-generated code. - -namespace Microsoft -{ - namespace Win32 - { - namespace SafeHandles - { - // Generated from `Microsoft.Win32.SafeHandles.SafeX509ChainHandle` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SafeX509ChainHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid - { - protected override void Dispose(bool disposing) => throw null; - protected override bool ReleaseHandle() => throw null; - public SafeX509ChainHandle() : base(default(bool)) => throw null; - } - - } - } -} -namespace System -{ - namespace Security - { - namespace Cryptography - { - namespace X509Certificates - { - // Generated from `System.Security.Cryptography.X509Certificates.CertificateRequest` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class CertificateRequest - { - public System.Collections.ObjectModel.Collection CertificateExtensions { get => throw null; } - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.Byte[] serialNumber) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.Byte[] serialNumber) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSigned(System.DateTimeOffset notBefore, System.DateTimeOffset notAfter) => throw null; - public System.Byte[] CreateSigningRequest() => throw null; - public System.Byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) => throw null; - public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } - public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get => throw null; } - } - - // Generated from `System.Security.Cryptography.X509Certificates.DSACertificateExtensions` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class DSACertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) => throw null; - public static System.Security.Cryptography.DSA GetDSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public static System.Security.Cryptography.DSA GetDSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.ECDsaCertificateExtensions` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class ECDsaCertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.ECDsa privateKey) => throw null; - public static System.Security.Cryptography.ECDsa GetECDsaPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public static System.Security.Cryptography.ECDsa GetECDsaPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.OpenFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum OpenFlags : int - { - IncludeArchived = 8, - MaxAllowed = 2, - OpenExistingOnly = 4, - ReadOnly = 0, - ReadWrite = 1, - } - - // Generated from `System.Security.Cryptography.X509Certificates.PublicKey` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class PublicKey - { - public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; - public System.Security.Cryptography.AsnEncodedData EncodedKeyValue { get => throw null; } - public System.Security.Cryptography.AsnEncodedData EncodedParameters { get => throw null; } - public System.Byte[] ExportSubjectPublicKeyInfo() => throw null; - public System.Security.Cryptography.DSA GetDSAPublicKey() => throw null; - public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPublicKey() => throw null; - public System.Security.Cryptography.ECDsa GetECDsaPublicKey() => throw null; - public System.Security.Cryptography.RSA GetRSAPublicKey() => throw null; - public System.Security.Cryptography.AsymmetricAlgorithm Key { get => throw null; } - public System.Security.Cryptography.Oid Oid { get => throw null; } - public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; - public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData parameters, System.Security.Cryptography.AsnEncodedData keyValue) => throw null; - public bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.RSACertificateExtensions` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public static class RSACertificateExtensions - { - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.RSA privateKey) => throw null; - public static System.Security.Cryptography.RSA GetRSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public static System.Security.Cryptography.RSA GetRSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.StoreLocation` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum StoreLocation : int - { - CurrentUser = 1, - LocalMachine = 2, - } - - // Generated from `System.Security.Cryptography.X509Certificates.StoreName` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum StoreName : int - { - AddressBook = 1, - AuthRoot = 2, - CertificateAuthority = 3, - Disallowed = 4, - My = 5, - Root = 6, - TrustedPeople = 7, - TrustedPublisher = 8, - } - - // Generated from `System.Security.Cryptography.X509Certificates.SubjectAlternativeNameBuilder` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class SubjectAlternativeNameBuilder - { - public void AddDnsName(string dnsName) => throw null; - public void AddEmailAddress(string emailAddress) => throw null; - public void AddIpAddress(System.Net.IPAddress ipAddress) => throw null; - public void AddUri(System.Uri uri) => throw null; - public void AddUserPrincipalName(string upn) => throw null; - public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical = default(bool)) => throw null; - public SubjectAlternativeNameBuilder() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X500DistinguishedName` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X500DistinguishedName : System.Security.Cryptography.AsnEncodedData - { - public string Decode(System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) => throw null; - public override string Format(bool multiLine) => throw null; - public string Name { get => throw null; } - public X500DistinguishedName(System.Security.Cryptography.AsnEncodedData encodedDistinguishedName) => throw null; - public X500DistinguishedName(System.Byte[] encodedDistinguishedName) => throw null; - public X500DistinguishedName(System.ReadOnlySpan encodedDistinguishedName) => throw null; - public X500DistinguishedName(System.Security.Cryptography.X509Certificates.X500DistinguishedName distinguishedName) => throw null; - public X500DistinguishedName(string distinguishedName) => throw null; - public X500DistinguishedName(string distinguishedName, System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum X500DistinguishedNameFlags : int - { - DoNotUsePlusSign = 32, - DoNotUseQuotes = 64, - ForceUTF8Encoding = 16384, - None = 0, - Reversed = 1, - UseCommas = 128, - UseNewLines = 256, - UseSemicolons = 16, - UseT61Encoding = 8192, - UseUTF8Encoding = 4096, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509BasicConstraintsExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public bool CertificateAuthority { get => throw null; } - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public bool HasPathLengthConstraint { get => throw null; } - public int PathLengthConstraint { get => throw null; } - public X509BasicConstraintsExtension() => throw null; - public X509BasicConstraintsExtension(System.Security.Cryptography.AsnEncodedData encodedBasicConstraints, bool critical) => throw null; - public X509BasicConstraintsExtension(bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Certificate` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Certificate : System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable - { - public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromCertFile(string filename) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromSignedFile(string filename) => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public virtual bool Equals(System.Security.Cryptography.X509Certificates.X509Certificate other) => throw null; - public override bool Equals(object obj) => throw null; - public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) => throw null; - public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, System.Security.SecureString password) => throw null; - public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string password) => throw null; - protected static string FormatDate(System.DateTime date) => throw null; - public virtual System.Byte[] GetCertHash() => throw null; - public virtual System.Byte[] GetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public virtual string GetCertHashString() => throw null; - public virtual string GetCertHashString(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; - public virtual string GetEffectiveDateString() => throw null; - public virtual string GetExpirationDateString() => throw null; - public virtual string GetFormat() => throw null; - public override int GetHashCode() => throw null; - public virtual string GetIssuerName() => throw null; - public virtual string GetKeyAlgorithm() => throw null; - public virtual System.Byte[] GetKeyAlgorithmParameters() => throw null; - public virtual string GetKeyAlgorithmParametersString() => throw null; - public virtual string GetName() => throw null; - void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; - public virtual System.Byte[] GetPublicKey() => throw null; - public virtual string GetPublicKeyString() => throw null; - public virtual System.Byte[] GetRawCertData() => throw null; - public virtual string GetRawCertDataString() => throw null; - public virtual System.Byte[] GetSerialNumber() => throw null; - public virtual string GetSerialNumberString() => throw null; - public System.IntPtr Handle { get => throw null; } - public virtual void Import(System.Byte[] rawData) => throw null; - public virtual void Import(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public virtual void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public virtual void Import(string fileName) => throw null; - public virtual void Import(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public virtual void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public string Issuer { get => throw null; } - void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null; - public virtual void Reset() => throw null; - public string Subject { get => throw null; } - public override string ToString() => throw null; - public virtual string ToString(bool fVerbose) => throw null; - public virtual bool TryGetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Span destination, out int bytesWritten) => throw null; - public X509Certificate() => throw null; - public X509Certificate(System.Byte[] data) => throw null; - public X509Certificate(System.Byte[] rawData, System.Security.SecureString password) => throw null; - public X509Certificate(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate(System.Byte[] rawData, string password) => throw null; - public X509Certificate(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate(System.IntPtr handle) => throw null; - public X509Certificate(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; - public X509Certificate(System.Security.Cryptography.X509Certificates.X509Certificate cert) => throw null; - public X509Certificate(string fileName) => throw null; - public X509Certificate(string fileName, System.Security.SecureString password) => throw null; - public X509Certificate(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate(string fileName, string password) => throw null; - public X509Certificate(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Certificate2` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Certificate2 : System.Security.Cryptography.X509Certificates.X509Certificate - { - public bool Archived { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.ECDiffieHellman privateKey) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem, System.ReadOnlySpan password) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath, System.ReadOnlySpan password, string keyPemFilePath = default(string)) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem) => throw null; - public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath = default(string)) => throw null; - public System.Security.Cryptography.X509Certificates.X509ExtensionCollection Extensions { get => throw null; } - public string FriendlyName { get => throw null; set => throw null; } - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.Byte[] rawData) => throw null; - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.ReadOnlySpan rawData) => throw null; - public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(string fileName) => throw null; - public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPrivateKey() => throw null; - public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPublicKey() => throw null; - public string GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType nameType, bool forIssuer) => throw null; - public bool HasPrivateKey { get => throw null; } - public override void Import(System.Byte[] rawData) => throw null; - public override void Import(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public override void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public override void Import(string fileName) => throw null; - public override void Import(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public override void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public System.Security.Cryptography.X509Certificates.X500DistinguishedName IssuerName { get => throw null; } - public System.DateTime NotAfter { get => throw null; } - public System.DateTime NotBefore { get => throw null; } - public System.Security.Cryptography.AsymmetricAlgorithm PrivateKey { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } - public System.Byte[] RawData { get => throw null; } - public override void Reset() => throw null; - public string SerialNumber { get => throw null; } - public System.Security.Cryptography.Oid SignatureAlgorithm { get => throw null; } - public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get => throw null; } - public string Thumbprint { get => throw null; } - public override string ToString() => throw null; - public override string ToString(bool verbose) => throw null; - public bool Verify() => throw null; - public int Version { get => throw null; } - public X509Certificate2() => throw null; - public X509Certificate2(System.Byte[] rawData) => throw null; - public X509Certificate2(System.Byte[] rawData, System.Security.SecureString password) => throw null; - public X509Certificate2(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate2(System.Byte[] rawData, string password) => throw null; - public X509Certificate2(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate2(System.IntPtr handle) => throw null; - public X509Certificate2(System.ReadOnlySpan rawData) => throw null; - public X509Certificate2(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - protected X509Certificate2(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; - public X509Certificate2(System.Security.Cryptography.X509Certificates.X509Certificate certificate) => throw null; - public X509Certificate2(string fileName) => throw null; - public X509Certificate2(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public X509Certificate2(string fileName, System.Security.SecureString password) => throw null; - public X509Certificate2(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - public X509Certificate2(string fileName, string password) => throw null; - public X509Certificate2(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Certificate2Collection` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Certificate2Collection : System.Security.Cryptography.X509Certificates.X509CertificateCollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable - { - public int Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; - public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) => throw null; - public System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string password) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Find(System.Security.Cryptography.X509Certificates.X509FindType findType, object findValue, bool validOnly) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator GetEnumerator() => throw null; - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; - public void Import(System.Byte[] rawData) => throw null; - public void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public void Import(System.ReadOnlySpan rawData) => throw null; - public void Import(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public void Import(System.ReadOnlySpan rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public void Import(string fileName) => throw null; - public void Import(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; - public void ImportFromPem(System.ReadOnlySpan certPem) => throw null; - public void ImportFromPemFile(string certPemFilePath) => throw null; - public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2 this[int index] { get => throw null; set => throw null; } - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; - public X509Certificate2Collection() => throw null; - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; - public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Certificate2Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - public System.Security.Cryptography.X509Certificates.X509Certificate2 Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - void System.IDisposable.Dispose() => throw null; - public bool MoveNext() => throw null; - bool System.Collections.IEnumerator.MoveNext() => throw null; - public void Reset() => throw null; - void System.Collections.IEnumerator.Reset() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509CertificateCollection` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509CertificateCollection : System.Collections.CollectionBase - { - // Generated from `System.Security.Cryptography.X509Certificates.X509CertificateCollection+X509CertificateEnumerator` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509CertificateEnumerator : System.Collections.IEnumerator - { - public System.Security.Cryptography.X509Certificates.X509Certificate Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - public bool MoveNext() => throw null; - bool System.Collections.IEnumerator.MoveNext() => throw null; - public void Reset() => throw null; - void System.Collections.IEnumerator.Reset() => throw null; - public X509CertificateEnumerator(System.Security.Cryptography.X509Certificates.X509CertificateCollection mappings) => throw null; - } - - - public int Add(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; - public void AddRange(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) => throw null; - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate[] value) => throw null; - public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; - public void CopyTo(System.Security.Cryptography.X509Certificates.X509Certificate[] array, int index) => throw null; - public System.Security.Cryptography.X509Certificates.X509CertificateCollection.X509CertificateEnumerator GetEnumerator() => throw null; - public override int GetHashCode() => throw null; - public int IndexOf(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; - public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate this[int index] { get => throw null; set => throw null; } - protected override void OnValidate(object value) => throw null; - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; - public X509CertificateCollection() => throw null; - public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) => throw null; - public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509Certificate[] value) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Chain` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Chain : System.IDisposable - { - public bool Build(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public System.IntPtr ChainContext { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainElementCollection ChainElements { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainPolicy ChainPolicy { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainStatus { get => throw null; } - public static System.Security.Cryptography.X509Certificates.X509Chain Create() => throw null; - public void Dispose() => throw null; - protected virtual void Dispose(bool disposing) => throw null; - public void Reset() => throw null; - public Microsoft.Win32.SafeHandles.SafeX509ChainHandle SafeHandle { get => throw null; } - public X509Chain() => throw null; - public X509Chain(System.IntPtr chainContext) => throw null; - public X509Chain(bool useMachineContext) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainElement` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ChainElement - { - public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainElementStatus { get => throw null; } - public string Information { get => throw null; } - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainElementCollection` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ChainElementCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable - { - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(System.Security.Cryptography.X509Certificates.X509ChainElement[] array, int index) => throw null; - public int Count { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator GetEnumerator() => throw null; - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public bool IsSynchronized { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainElement this[int index] { get => throw null; } - public object SyncRoot { get => throw null; } - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ChainElementEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - public System.Security.Cryptography.X509Certificates.X509ChainElement Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - void System.IDisposable.Dispose() => throw null; - public bool MoveNext() => throw null; - public void Reset() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainPolicy` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ChainPolicy - { - public System.Security.Cryptography.OidCollection ApplicationPolicy { get => throw null; } - public System.Security.Cryptography.OidCollection CertificatePolicy { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection CustomTrustStore { get => throw null; } - public bool DisableCertificateDownloads { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection ExtraStore { get => throw null; } - public void Reset() => throw null; - public System.Security.Cryptography.X509Certificates.X509RevocationFlag RevocationFlag { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509ChainTrustMode TrustMode { get => throw null; set => throw null; } - public System.TimeSpan UrlRetrievalTimeout { get => throw null; set => throw null; } - public System.Security.Cryptography.X509Certificates.X509VerificationFlags VerificationFlags { get => throw null; set => throw null; } - public System.DateTime VerificationTime { get => throw null; set => throw null; } - public X509ChainPolicy() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainStatus` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct X509ChainStatus - { - public System.Security.Cryptography.X509Certificates.X509ChainStatusFlags Status { get => throw null; set => throw null; } - public string StatusInformation { get => throw null; set => throw null; } - // Stub generator skipped constructor - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainStatusFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum X509ChainStatusFlags : int - { - CtlNotSignatureValid = 262144, - CtlNotTimeValid = 131072, - CtlNotValidForUsage = 524288, - Cyclic = 128, - ExplicitDistrust = 67108864, - HasExcludedNameConstraint = 32768, - HasNotDefinedNameConstraint = 8192, - HasNotPermittedNameConstraint = 16384, - HasNotSupportedCriticalExtension = 134217728, - HasNotSupportedNameConstraint = 4096, - HasWeakSignature = 1048576, - InvalidBasicConstraints = 1024, - InvalidExtension = 256, - InvalidNameConstraints = 2048, - InvalidPolicyConstraints = 512, - NoError = 0, - NoIssuanceChainPolicy = 33554432, - NotSignatureValid = 8, - NotTimeNested = 2, - NotTimeValid = 1, - NotValidForUsage = 16, - OfflineRevocation = 16777216, - PartialChain = 65536, - RevocationStatusUnknown = 64, - Revoked = 4, - UntrustedRoot = 32, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ChainTrustMode` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509ChainTrustMode : int - { - CustomRootTrust = 1, - System = 0, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ContentType` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509ContentType : int - { - Authenticode = 6, - Cert = 1, - Pfx = 3, - Pkcs12 = 3, - Pkcs7 = 5, - SerializedCert = 2, - SerializedStore = 4, - Unknown = 0, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509EnhancedKeyUsageExtension` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509EnhancedKeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public System.Security.Cryptography.OidCollection EnhancedKeyUsages { get => throw null; } - public X509EnhancedKeyUsageExtension() => throw null; - public X509EnhancedKeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedEnhancedKeyUsages, bool critical) => throw null; - public X509EnhancedKeyUsageExtension(System.Security.Cryptography.OidCollection enhancedKeyUsages, bool critical) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Extension` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Extension : System.Security.Cryptography.AsnEncodedData - { - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public bool Critical { get => throw null; set => throw null; } - protected X509Extension() => throw null; - public X509Extension(System.Security.Cryptography.AsnEncodedData encodedExtension, bool critical) => throw null; - public X509Extension(System.Security.Cryptography.Oid oid, System.Byte[] rawData, bool critical) => throw null; - public X509Extension(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData, bool critical) => throw null; - public X509Extension(string oid, System.Byte[] rawData, bool critical) => throw null; - public X509Extension(string oid, System.ReadOnlySpan rawData, bool critical) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ExtensionCollection` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ExtensionCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable - { - public int Add(System.Security.Cryptography.X509Certificates.X509Extension extension) => throw null; - void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; - public void CopyTo(System.Security.Cryptography.X509Certificates.X509Extension[] array, int index) => throw null; - public int Count { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator GetEnumerator() => throw null; - System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; - public bool IsSynchronized { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509Extension this[int index] { get => throw null; } - public System.Security.Cryptography.X509Certificates.X509Extension this[string oid] { get => throw null; } - public object SyncRoot { get => throw null; } - public X509ExtensionCollection() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509ExtensionEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable - { - public System.Security.Cryptography.X509Certificates.X509Extension Current { get => throw null; } - object System.Collections.IEnumerator.Current { get => throw null; } - void System.IDisposable.Dispose() => throw null; - public bool MoveNext() => throw null; - public void Reset() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509FindType` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509FindType : int - { - FindByApplicationPolicy = 10, - FindByCertificatePolicy = 11, - FindByExtension = 12, - FindByIssuerDistinguishedName = 4, - FindByIssuerName = 3, - FindByKeyUsage = 13, - FindBySerialNumber = 5, - FindBySubjectDistinguishedName = 2, - FindBySubjectKeyIdentifier = 14, - FindBySubjectName = 1, - FindByTemplateName = 9, - FindByThumbprint = 0, - FindByTimeExpired = 8, - FindByTimeNotYetValid = 7, - FindByTimeValid = 6, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509IncludeOption` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509IncludeOption : int - { - EndCertOnly = 2, - ExcludeRoot = 1, - None = 0, - WholeChain = 3, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509KeyStorageFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum X509KeyStorageFlags : int - { - DefaultKeySet = 0, - EphemeralKeySet = 32, - Exportable = 4, - MachineKeySet = 2, - PersistKeySet = 16, - UserKeySet = 1, - UserProtected = 8, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509KeyUsageExtension` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509KeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public System.Security.Cryptography.X509Certificates.X509KeyUsageFlags KeyUsages { get => throw null; } - public X509KeyUsageExtension() => throw null; - public X509KeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedKeyUsage, bool critical) => throw null; - public X509KeyUsageExtension(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags keyUsages, bool critical) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509KeyUsageFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum X509KeyUsageFlags : int - { - CrlSign = 2, - DataEncipherment = 16, - DecipherOnly = 32768, - DigitalSignature = 128, - EncipherOnly = 1, - KeyAgreement = 8, - KeyCertSign = 4, - KeyEncipherment = 32, - NonRepudiation = 64, - None = 0, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509NameType` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509NameType : int - { - DnsFromAlternativeName = 4, - DnsName = 3, - EmailName = 1, - SimpleName = 0, - UpnName = 2, - UrlName = 5, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509RevocationFlag` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509RevocationFlag : int - { - EndCertificateOnly = 0, - EntireChain = 1, - ExcludeRoot = 2, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509RevocationMode` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509RevocationMode : int - { - NoCheck = 0, - Offline = 2, - Online = 1, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509SignatureGenerator` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public abstract class X509SignatureGenerator - { - protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey(); - public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) => throw null; - public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForRSA(System.Security.Cryptography.RSA key, System.Security.Cryptography.RSASignaturePadding signaturePadding) => throw null; - public abstract System.Byte[] GetSignatureAlgorithmIdentifier(System.Security.Cryptography.HashAlgorithmName hashAlgorithm); - public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } - public abstract System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm); - protected X509SignatureGenerator() => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509Store` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509Store : System.IDisposable - { - public void Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; - public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get => throw null; } - public void Close() => throw null; - public void Dispose() => throw null; - public bool IsOpen { get => throw null; } - public System.Security.Cryptography.X509Certificates.StoreLocation Location { get => throw null; } - public string Name { get => throw null; } - public void Open(System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; - public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; - public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; - public System.IntPtr StoreHandle { get => throw null; } - public X509Store() => throw null; - public X509Store(System.IntPtr storeHandle) => throw null; - public X509Store(System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName) => throw null; - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; - public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; - public X509Store(string storeName) => throw null; - public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; - public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public class X509SubjectKeyIdentifierExtension : System.Security.Cryptography.X509Certificates.X509Extension - { - public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; - public string SubjectKeyIdentifier { get => throw null; } - public X509SubjectKeyIdentifierExtension() => throw null; - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.AsnEncodedData encodedSubjectKeyIdentifier, bool critical) => throw null; - public X509SubjectKeyIdentifierExtension(System.Byte[] subjectKeyIdentifier, bool critical) => throw null; - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) => throw null; - public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, bool critical) => throw null; - public X509SubjectKeyIdentifierExtension(System.ReadOnlySpan subjectKeyIdentifier, bool critical) => throw null; - public X509SubjectKeyIdentifierExtension(string subjectKeyIdentifier, bool critical) => throw null; - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public enum X509SubjectKeyIdentifierHashAlgorithm : int - { - CapiSha1 = 2, - Sha1 = 0, - ShortSha1 = 1, - } - - // Generated from `System.Security.Cryptography.X509Certificates.X509VerificationFlags` in `System.Security.Cryptography.X509Certificates, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - [System.Flags] - public enum X509VerificationFlags : int - { - AllFlags = 4095, - AllowUnknownCertificateAuthority = 16, - IgnoreCertificateAuthorityRevocationUnknown = 1024, - IgnoreCtlNotTimeValid = 2, - IgnoreCtlSignerRevocationUnknown = 512, - IgnoreEndRevocationUnknown = 256, - IgnoreInvalidBasicConstraints = 8, - IgnoreInvalidName = 64, - IgnoreInvalidPolicy = 128, - IgnoreNotTimeNested = 4, - IgnoreNotTimeValid = 1, - IgnoreRootRevocationUnknown = 2048, - IgnoreWrongUsage = 32, - NoFlag = 0, - } - - } - } - } -} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.cs new file mode 100644 index 00000000000..c3a9156d0b3 --- /dev/null +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Cryptography.cs @@ -0,0 +1,3051 @@ +// This file contains auto-generated code. +// Generated from `System.Security.Cryptography, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. + +namespace Microsoft +{ + namespace Win32 + { + namespace SafeHandles + { + public abstract class SafeNCryptHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + protected override bool ReleaseHandle() => throw null; + protected abstract bool ReleaseNativeHandle(); + protected SafeNCryptHandle() : base(default(bool)) => throw null; + protected SafeNCryptHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) : base(default(bool)) => throw null; + } + + public class SafeNCryptKeyHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + protected override bool ReleaseNativeHandle() => throw null; + public SafeNCryptKeyHandle() => throw null; + public SafeNCryptKeyHandle(System.IntPtr handle, System.Runtime.InteropServices.SafeHandle parentHandle) => throw null; + } + + public class SafeNCryptProviderHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + protected override bool ReleaseNativeHandle() => throw null; + public SafeNCryptProviderHandle() => throw null; + } + + public class SafeNCryptSecretHandle : Microsoft.Win32.SafeHandles.SafeNCryptHandle + { + protected override bool ReleaseNativeHandle() => throw null; + public SafeNCryptSecretHandle() => throw null; + } + + public class SafeX509ChainHandle : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid + { + protected override void Dispose(bool disposing) => throw null; + protected override bool ReleaseHandle() => throw null; + public SafeX509ChainHandle() : base(default(bool)) => throw null; + } + + } + } +} +namespace System +{ + namespace Security + { + namespace Cryptography + { + public abstract class Aes : System.Security.Cryptography.SymmetricAlgorithm + { + protected Aes() => throw null; + public static System.Security.Cryptography.Aes Create() => throw null; + public static System.Security.Cryptography.Aes Create(string algorithmName) => throw null; + } + + public class AesCcm : System.IDisposable + { + public AesCcm(System.Byte[] key) => throw null; + public AesCcm(System.ReadOnlySpan key) => throw null; + public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public void Dispose() => throw null; + public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public static bool IsSupported { get => throw null; } + public static System.Security.Cryptography.KeySizes NonceByteSizes { get => throw null; } + public static System.Security.Cryptography.KeySizes TagByteSizes { get => throw null; } + } + + public class AesCng : System.Security.Cryptography.Aes + { + public AesCng() => throw null; + public AesCng(string keyName) => throw null; + public AesCng(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; + public AesCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + protected override bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + protected override bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + protected override bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + } + + public class AesCryptoServiceProvider : System.Security.Cryptography.Aes + { + public AesCryptoServiceProvider() => throw null; + public override int BlockSize { get => throw null; set => throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override int FeedbackSize { get => throw null; set => throw null; } + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] IV { get => throw null; set => throw null; } + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } + public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } + } + + public class AesGcm : System.IDisposable + { + public AesGcm(System.Byte[] key) => throw null; + public AesGcm(System.ReadOnlySpan key) => throw null; + public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public void Dispose() => throw null; + public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public static bool IsSupported { get => throw null; } + public static System.Security.Cryptography.KeySizes NonceByteSizes { get => throw null; } + public static System.Security.Cryptography.KeySizes TagByteSizes { get => throw null; } + } + + public class AesManaged : System.Security.Cryptography.Aes + { + public AesManaged() => throw null; + public override int BlockSize { get => throw null; set => throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override int FeedbackSize { get => throw null; set => throw null; } + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] IV { get => throw null; set => throw null; } + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } + public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } + } + + public class AsnEncodedData + { + protected AsnEncodedData() => throw null; + public AsnEncodedData(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public AsnEncodedData(System.Byte[] rawData) => throw null; + public AsnEncodedData(System.Security.Cryptography.Oid oid, System.Byte[] rawData) => throw null; + public AsnEncodedData(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData) => throw null; + public AsnEncodedData(System.ReadOnlySpan rawData) => throw null; + public AsnEncodedData(string oid, System.Byte[] rawData) => throw null; + public AsnEncodedData(string oid, System.ReadOnlySpan rawData) => throw null; + public virtual void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public virtual string Format(bool multiLine) => throw null; + public System.Security.Cryptography.Oid Oid { get => throw null; set => throw null; } + public System.Byte[] RawData { get => throw null; set => throw null; } + } + + public class AsnEncodedDataCollection : System.Collections.ICollection, System.Collections.IEnumerable + { + public int Add(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public AsnEncodedDataCollection() => throw null; + public AsnEncodedDataCollection(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(System.Security.Cryptography.AsnEncodedData[] array, int index) => throw null; + public int Count { get => throw null; } + public System.Security.Cryptography.AsnEncodedDataEnumerator GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public bool IsSynchronized { get => throw null; } + public System.Security.Cryptography.AsnEncodedData this[int index] { get => throw null; } + public void Remove(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public object SyncRoot { get => throw null; } + } + + public class AsnEncodedDataEnumerator : System.Collections.IEnumerator + { + public System.Security.Cryptography.AsnEncodedData Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + public bool MoveNext() => throw null; + public void Reset() => throw null; + } + + public abstract class AsymmetricAlgorithm : System.IDisposable + { + protected AsymmetricAlgorithm() => throw null; + public void Clear() => throw null; + public static System.Security.Cryptography.AsymmetricAlgorithm Create() => throw null; + public static System.Security.Cryptography.AsymmetricAlgorithm Create(string algName) => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public virtual System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public virtual System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public string ExportEncryptedPkcs8PrivateKeyPem(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public virtual System.Byte[] ExportPkcs8PrivateKey() => throw null; + public string ExportPkcs8PrivateKeyPem() => throw null; + public virtual System.Byte[] ExportSubjectPublicKeyInfo() => throw null; + public string ExportSubjectPublicKeyInfoPem() => throw null; + public virtual void FromXmlString(string xmlString) => throw null; + public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; + public virtual void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; + public virtual void ImportFromPem(System.ReadOnlySpan input) => throw null; + public virtual void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual string KeyExchangeAlgorithm { get => throw null; } + public virtual int KeySize { get => throw null; set => throw null; } + protected int KeySizeValue; + public virtual System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; + public virtual string SignatureAlgorithm { get => throw null; } + public virtual string ToXmlString(bool includePrivateParameters) => throw null; + public virtual bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public virtual bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public bool TryExportEncryptedPkcs8PrivateKeyPem(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int charsWritten) => throw null; + public virtual bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public bool TryExportPkcs8PrivateKeyPem(System.Span destination, out int charsWritten) => throw null; + public virtual bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + public bool TryExportSubjectPublicKeyInfoPem(System.Span destination, out int charsWritten) => throw null; + } + + public abstract class AsymmetricKeyExchangeDeformatter + { + protected AsymmetricKeyExchangeDeformatter() => throw null; + public abstract System.Byte[] DecryptKeyExchange(System.Byte[] rgb); + public abstract string Parameters { get; set; } + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } + + public abstract class AsymmetricKeyExchangeFormatter + { + protected AsymmetricKeyExchangeFormatter() => throw null; + public abstract System.Byte[] CreateKeyExchange(System.Byte[] data); + public abstract System.Byte[] CreateKeyExchange(System.Byte[] data, System.Type symAlgType); + public abstract string Parameters { get; } + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } + + public abstract class AsymmetricSignatureDeformatter + { + protected AsymmetricSignatureDeformatter() => throw null; + public abstract void SetHashAlgorithm(string strName); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + public abstract bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature); + public virtual bool VerifySignature(System.Security.Cryptography.HashAlgorithm hash, System.Byte[] rgbSignature) => throw null; + } + + public abstract class AsymmetricSignatureFormatter + { + protected AsymmetricSignatureFormatter() => throw null; + public abstract System.Byte[] CreateSignature(System.Byte[] rgbHash); + public virtual System.Byte[] CreateSignature(System.Security.Cryptography.HashAlgorithm hash) => throw null; + public abstract void SetHashAlgorithm(string strName); + public abstract void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key); + } + + public class ChaCha20Poly1305 : System.IDisposable + { + public ChaCha20Poly1305(System.Byte[] key) => throw null; + public ChaCha20Poly1305(System.ReadOnlySpan key) => throw null; + public void Decrypt(System.Byte[] nonce, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] plaintext, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Decrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan ciphertext, System.ReadOnlySpan tag, System.Span plaintext, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public void Dispose() => throw null; + public void Encrypt(System.Byte[] nonce, System.Byte[] plaintext, System.Byte[] ciphertext, System.Byte[] tag, System.Byte[] associatedData = default(System.Byte[])) => throw null; + public void Encrypt(System.ReadOnlySpan nonce, System.ReadOnlySpan plaintext, System.Span ciphertext, System.Span tag, System.ReadOnlySpan associatedData = default(System.ReadOnlySpan)) => throw null; + public static bool IsSupported { get => throw null; } + } + + public enum CipherMode : int + { + CBC = 1, + CFB = 4, + CTS = 5, + ECB = 2, + OFB = 3, + } + + public class CngAlgorithm : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.CngAlgorithm left, System.Security.Cryptography.CngAlgorithm right) => throw null; + public static bool operator ==(System.Security.Cryptography.CngAlgorithm left, System.Security.Cryptography.CngAlgorithm right) => throw null; + public string Algorithm { get => throw null; } + public CngAlgorithm(string algorithm) => throw null; + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellman { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP256 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP384 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDiffieHellmanP521 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDsa { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDsaP256 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDsaP384 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm ECDsaP521 { get => throw null; } + public bool Equals(System.Security.Cryptography.CngAlgorithm other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public static System.Security.Cryptography.CngAlgorithm MD5 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm Rsa { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm Sha1 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm Sha256 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm Sha384 { get => throw null; } + public static System.Security.Cryptography.CngAlgorithm Sha512 { get => throw null; } + public override string ToString() => throw null; + } + + public class CngAlgorithmGroup : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.CngAlgorithmGroup left, System.Security.Cryptography.CngAlgorithmGroup right) => throw null; + public static bool operator ==(System.Security.Cryptography.CngAlgorithmGroup left, System.Security.Cryptography.CngAlgorithmGroup right) => throw null; + public string AlgorithmGroup { get => throw null; } + public CngAlgorithmGroup(string algorithmGroup) => throw null; + public static System.Security.Cryptography.CngAlgorithmGroup DiffieHellman { get => throw null; } + public static System.Security.Cryptography.CngAlgorithmGroup Dsa { get => throw null; } + public static System.Security.Cryptography.CngAlgorithmGroup ECDiffieHellman { get => throw null; } + public static System.Security.Cryptography.CngAlgorithmGroup ECDsa { get => throw null; } + public bool Equals(System.Security.Cryptography.CngAlgorithmGroup other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public static System.Security.Cryptography.CngAlgorithmGroup Rsa { get => throw null; } + public override string ToString() => throw null; + } + + [System.Flags] + public enum CngExportPolicies : int + { + AllowArchiving = 4, + AllowExport = 1, + AllowPlaintextArchiving = 8, + AllowPlaintextExport = 2, + None = 0, + } + + public class CngKey : System.IDisposable + { + public System.Security.Cryptography.CngAlgorithm Algorithm { get => throw null; } + public System.Security.Cryptography.CngAlgorithmGroup AlgorithmGroup { get => throw null; } + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm) => throw null; + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string keyName) => throw null; + public static System.Security.Cryptography.CngKey Create(System.Security.Cryptography.CngAlgorithm algorithm, string keyName, System.Security.Cryptography.CngKeyCreationParameters creationParameters) => throw null; + public void Delete() => throw null; + public void Dispose() => throw null; + public static bool Exists(string keyName) => throw null; + public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; + public static bool Exists(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions options) => throw null; + public System.Byte[] Export(System.Security.Cryptography.CngKeyBlobFormat format) => throw null; + public System.Security.Cryptography.CngExportPolicies ExportPolicy { get => throw null; } + public System.Security.Cryptography.CngProperty GetProperty(string name, System.Security.Cryptography.CngPropertyOptions options) => throw null; + public Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle Handle { get => throw null; } + public bool HasProperty(string name, System.Security.Cryptography.CngPropertyOptions options) => throw null; + public static System.Security.Cryptography.CngKey Import(System.Byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format) => throw null; + public static System.Security.Cryptography.CngKey Import(System.Byte[] keyBlob, System.Security.Cryptography.CngKeyBlobFormat format, System.Security.Cryptography.CngProvider provider) => throw null; + public bool IsEphemeral { get => throw null; } + public bool IsMachineKey { get => throw null; } + public string KeyName { get => throw null; } + public int KeySize { get => throw null; } + public System.Security.Cryptography.CngKeyUsages KeyUsage { get => throw null; } + public static System.Security.Cryptography.CngKey Open(Microsoft.Win32.SafeHandles.SafeNCryptKeyHandle keyHandle, System.Security.Cryptography.CngKeyHandleOpenOptions keyHandleOpenOptions) => throw null; + public static System.Security.Cryptography.CngKey Open(string keyName) => throw null; + public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; + public static System.Security.Cryptography.CngKey Open(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; + public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } + public System.Security.Cryptography.CngProvider Provider { get => throw null; } + public Microsoft.Win32.SafeHandles.SafeNCryptProviderHandle ProviderHandle { get => throw null; } + public void SetProperty(System.Security.Cryptography.CngProperty property) => throw null; + public System.Security.Cryptography.CngUIPolicy UIPolicy { get => throw null; } + public string UniqueName { get => throw null; } + } + + public class CngKeyBlobFormat : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.CngKeyBlobFormat left, System.Security.Cryptography.CngKeyBlobFormat right) => throw null; + public static bool operator ==(System.Security.Cryptography.CngKeyBlobFormat left, System.Security.Cryptography.CngKeyBlobFormat right) => throw null; + public CngKeyBlobFormat(string format) => throw null; + public static System.Security.Cryptography.CngKeyBlobFormat EccFullPrivateBlob { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat EccFullPublicBlob { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat EccPrivateBlob { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat EccPublicBlob { get => throw null; } + public bool Equals(System.Security.Cryptography.CngKeyBlobFormat other) => throw null; + public override bool Equals(object obj) => throw null; + public string Format { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat GenericPrivateBlob { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat GenericPublicBlob { get => throw null; } + public override int GetHashCode() => throw null; + public static System.Security.Cryptography.CngKeyBlobFormat OpaqueTransportBlob { get => throw null; } + public static System.Security.Cryptography.CngKeyBlobFormat Pkcs8PrivateBlob { get => throw null; } + public override string ToString() => throw null; + } + + [System.Flags] + public enum CngKeyCreationOptions : int + { + MachineKey = 32, + None = 0, + OverwriteExistingKey = 128, + } + + public class CngKeyCreationParameters + { + public CngKeyCreationParameters() => throw null; + public System.Security.Cryptography.CngExportPolicies? ExportPolicy { get => throw null; set => throw null; } + public System.Security.Cryptography.CngKeyCreationOptions KeyCreationOptions { get => throw null; set => throw null; } + public System.Security.Cryptography.CngKeyUsages? KeyUsage { get => throw null; set => throw null; } + public System.Security.Cryptography.CngPropertyCollection Parameters { get => throw null; } + public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } + public System.Security.Cryptography.CngProvider Provider { get => throw null; set => throw null; } + public System.Security.Cryptography.CngUIPolicy UIPolicy { get => throw null; set => throw null; } + } + + [System.Flags] + public enum CngKeyHandleOpenOptions : int + { + EphemeralKey = 1, + None = 0, + } + + [System.Flags] + public enum CngKeyOpenOptions : int + { + MachineKey = 32, + None = 0, + Silent = 64, + UserKey = 0, + } + + [System.Flags] + public enum CngKeyUsages : int + { + AllUsages = 16777215, + Decryption = 1, + KeyAgreement = 4, + None = 0, + Signing = 2, + } + + public struct CngProperty : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) => throw null; + public static bool operator ==(System.Security.Cryptography.CngProperty left, System.Security.Cryptography.CngProperty right) => throw null; + // Stub generator skipped constructor + public CngProperty(string name, System.Byte[] value, System.Security.Cryptography.CngPropertyOptions options) => throw null; + public bool Equals(System.Security.Cryptography.CngProperty other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public System.Byte[] GetValue() => throw null; + public string Name { get => throw null; } + public System.Security.Cryptography.CngPropertyOptions Options { get => throw null; } + } + + public class CngPropertyCollection : System.Collections.ObjectModel.Collection + { + public CngPropertyCollection() => throw null; + } + + [System.Flags] + public enum CngPropertyOptions : int + { + CustomProperty = 1073741824, + None = 0, + Persist = -2147483648, + } + + public class CngProvider : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.CngProvider left, System.Security.Cryptography.CngProvider right) => throw null; + public static bool operator ==(System.Security.Cryptography.CngProvider left, System.Security.Cryptography.CngProvider right) => throw null; + public CngProvider(string provider) => throw null; + public bool Equals(System.Security.Cryptography.CngProvider other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public static System.Security.Cryptography.CngProvider MicrosoftPlatformCryptoProvider { get => throw null; } + public static System.Security.Cryptography.CngProvider MicrosoftSmartCardKeyStorageProvider { get => throw null; } + public static System.Security.Cryptography.CngProvider MicrosoftSoftwareKeyStorageProvider { get => throw null; } + public string Provider { get => throw null; } + public override string ToString() => throw null; + } + + public class CngUIPolicy + { + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel) => throw null; + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName) => throw null; + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description) => throw null; + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description, string useContext) => throw null; + public CngUIPolicy(System.Security.Cryptography.CngUIProtectionLevels protectionLevel, string friendlyName, string description, string useContext, string creationTitle) => throw null; + public string CreationTitle { get => throw null; } + public string Description { get => throw null; } + public string FriendlyName { get => throw null; } + public System.Security.Cryptography.CngUIProtectionLevels ProtectionLevel { get => throw null; } + public string UseContext { get => throw null; } + } + + [System.Flags] + public enum CngUIProtectionLevels : int + { + ForceHighProtection = 2, + None = 0, + ProtectKey = 1, + } + + public class CryptoConfig + { + public static void AddAlgorithm(System.Type algorithm, params string[] names) => throw null; + public static void AddOID(string oid, params string[] names) => throw null; + public static bool AllowOnlyFipsAlgorithms { get => throw null; } + public static object CreateFromName(string name) => throw null; + public static object CreateFromName(string name, params object[] args) => throw null; + public CryptoConfig() => throw null; + public static System.Byte[] EncodeOID(string str) => throw null; + public static string MapNameToOID(string name) => throw null; + } + + public class CryptoStream : System.IO.Stream, System.IDisposable + { + public override System.IAsyncResult BeginRead(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; + public override System.IAsyncResult BeginWrite(System.Byte[] buffer, int offset, int count, System.AsyncCallback callback, object state) => throw null; + public override bool CanRead { get => throw null; } + public override bool CanSeek { get => throw null; } + public override bool CanWrite { get => throw null; } + public void Clear() => throw null; + public override void CopyTo(System.IO.Stream destination, int bufferSize) => throw null; + public override System.Threading.Tasks.Task CopyToAsync(System.IO.Stream destination, int bufferSize, System.Threading.CancellationToken cancellationToken) => throw null; + public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICryptoTransform transform, System.Security.Cryptography.CryptoStreamMode mode) => throw null; + public CryptoStream(System.IO.Stream stream, System.Security.Cryptography.ICryptoTransform transform, System.Security.Cryptography.CryptoStreamMode mode, bool leaveOpen) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Threading.Tasks.ValueTask DisposeAsync() => throw null; + public override int EndRead(System.IAsyncResult asyncResult) => throw null; + public override void EndWrite(System.IAsyncResult asyncResult) => throw null; + public override void Flush() => throw null; + public override System.Threading.Tasks.Task FlushAsync(System.Threading.CancellationToken cancellationToken) => throw null; + public void FlushFinalBlock() => throw null; + public System.Threading.Tasks.ValueTask FlushFinalBlockAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public bool HasFlushedFinalBlock { get => throw null; } + public override System.Int64 Length { get => throw null; } + public override System.Int64 Position { get => throw null; set => throw null; } + public override int Read(System.Byte[] buffer, int offset, int count) => throw null; + public override System.Threading.Tasks.Task ReadAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask ReadAsync(System.Memory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override int ReadByte() => throw null; + public override System.Int64 Seek(System.Int64 offset, System.IO.SeekOrigin origin) => throw null; + public override void SetLength(System.Int64 value) => throw null; + public override void Write(System.Byte[] buffer, int offset, int count) => throw null; + public override System.Threading.Tasks.Task WriteAsync(System.Byte[] buffer, int offset, int count, System.Threading.CancellationToken cancellationToken) => throw null; + public override System.Threading.Tasks.ValueTask WriteAsync(System.ReadOnlyMemory buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public override void WriteByte(System.Byte value) => throw null; + } + + public enum CryptoStreamMode : int + { + Read = 0, + Write = 1, + } + + public static class CryptographicOperations + { + public static bool FixedTimeEquals(System.ReadOnlySpan left, System.ReadOnlySpan right) => throw null; + public static void ZeroMemory(System.Span buffer) => throw null; + } + + public class CryptographicUnexpectedOperationException : System.Security.Cryptography.CryptographicException + { + public CryptographicUnexpectedOperationException() => throw null; + protected CryptographicUnexpectedOperationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public CryptographicUnexpectedOperationException(string message) => throw null; + public CryptographicUnexpectedOperationException(string message, System.Exception inner) => throw null; + public CryptographicUnexpectedOperationException(string format, string insert) => throw null; + } + + public class CspKeyContainerInfo + { + public bool Accessible { get => throw null; } + public CspKeyContainerInfo(System.Security.Cryptography.CspParameters parameters) => throw null; + public bool Exportable { get => throw null; } + public bool HardwareDevice { get => throw null; } + public string KeyContainerName { get => throw null; } + public System.Security.Cryptography.KeyNumber KeyNumber { get => throw null; } + public bool MachineKeyStore { get => throw null; } + public bool Protected { get => throw null; } + public string ProviderName { get => throw null; } + public int ProviderType { get => throw null; } + public bool RandomlyGenerated { get => throw null; } + public bool Removable { get => throw null; } + public string UniqueKeyContainerName { get => throw null; } + } + + public class CspParameters + { + public CspParameters() => throw null; + public CspParameters(int dwTypeIn) => throw null; + public CspParameters(int dwTypeIn, string strProviderNameIn) => throw null; + public CspParameters(int dwTypeIn, string strProviderNameIn, string strContainerNameIn) => throw null; + public System.Security.Cryptography.CspProviderFlags Flags { get => throw null; set => throw null; } + public string KeyContainerName; + public int KeyNumber; + public System.Security.SecureString KeyPassword { get => throw null; set => throw null; } + public System.IntPtr ParentWindowHandle { get => throw null; set => throw null; } + public string ProviderName; + public int ProviderType; + } + + [System.Flags] + public enum CspProviderFlags : int + { + CreateEphemeralKey = 128, + NoFlags = 0, + NoPrompt = 64, + UseArchivableKey = 16, + UseDefaultKeyContainer = 2, + UseExistingKey = 8, + UseMachineKeyStore = 1, + UseNonExportableKey = 4, + UseUserProtectedKey = 32, + } + + public abstract class DES : System.Security.Cryptography.SymmetricAlgorithm + { + public static System.Security.Cryptography.DES Create() => throw null; + public static System.Security.Cryptography.DES Create(string algName) => throw null; + protected DES() => throw null; + public static bool IsSemiWeakKey(System.Byte[] rgbKey) => throw null; + public static bool IsWeakKey(System.Byte[] rgbKey) => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + } + + public class DESCryptoServiceProvider : System.Security.Cryptography.DES + { + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public DESCryptoServiceProvider() => throw null; + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + } + + public abstract class DSA : System.Security.Cryptography.AsymmetricAlgorithm + { + public static System.Security.Cryptography.DSA Create() => throw null; + public static System.Security.Cryptography.DSA Create(System.Security.Cryptography.DSAParameters parameters) => throw null; + public static System.Security.Cryptography.DSA Create(int keySizeInBits) => throw null; + public static System.Security.Cryptography.DSA Create(string algName) => throw null; + public abstract System.Byte[] CreateSignature(System.Byte[] rgbHash); + public System.Byte[] CreateSignature(System.Byte[] rgbHash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] CreateSignatureCore(System.ReadOnlySpan hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected DSA() => throw null; + public abstract System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters); + public override void FromXmlString(string xmlString) => throw null; + public int GetMaxSignatureSize(System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; + public override void ImportFromPem(System.ReadOnlySpan input) => throw null; + public abstract void ImportParameters(System.Security.Cryptography.DSAParameters parameters); + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; + public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] SignDataCore(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] SignDataCore(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public override string ToXmlString(bool includePrivateParameters) => throw null; + public bool TryCreateSignature(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public virtual bool TryCreateSignature(System.ReadOnlySpan hash, System.Span destination, out int bytesWritten) => throw null; + protected virtual bool TryCreateSignatureCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; + public bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; + protected virtual bool TrySignDataCore(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifyDataCore(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifyDataCore(System.IO.Stream data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public abstract bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature); + public bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifySignature(System.ReadOnlySpan hash, System.ReadOnlySpan signature) => throw null; + public bool VerifySignature(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifySignatureCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + } + + public class DSACng : System.Security.Cryptography.DSA + { + public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; + public DSACng() => throw null; + public DSACng(System.Security.Cryptography.CngKey key) => throw null; + public DSACng(int keySize) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; + public System.Security.Cryptography.CngKey Key { get => throw null; } + public override string KeyExchangeAlgorithm { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override string SignatureAlgorithm { get => throw null; } + protected override bool TryCreateSignatureCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; + protected override bool VerifySignatureCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + } + + public class DSACryptoServiceProvider : System.Security.Cryptography.DSA, System.Security.Cryptography.ICspAsymmetricAlgorithm + { + public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; + public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get => throw null; } + public DSACryptoServiceProvider() => throw null; + public DSACryptoServiceProvider(System.Security.Cryptography.CspParameters parameters) => throw null; + public DSACryptoServiceProvider(int dwKeySize) => throw null; + public DSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters parameters) => throw null; + protected override void Dispose(bool disposing) => throw null; + public System.Byte[] ExportCspBlob(bool includePrivateParameters) => throw null; + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; + protected override System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + protected override System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public void ImportCspBlob(System.Byte[] keyBlob) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; + public override string KeyExchangeAlgorithm { get => throw null; } + public override int KeySize { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public bool PersistKeyInCsp { get => throw null; set => throw null; } + public bool PublicOnly { get => throw null; } + public System.Byte[] SignData(System.Byte[] buffer) => throw null; + public System.Byte[] SignData(System.Byte[] buffer, int offset, int count) => throw null; + public System.Byte[] SignData(System.IO.Stream inputStream) => throw null; + public System.Byte[] SignHash(System.Byte[] rgbHash, string str) => throw null; + public override string SignatureAlgorithm { get => throw null; } + public static bool UseMachineKeyStore { get => throw null; set => throw null; } + public bool VerifyData(System.Byte[] rgbData, System.Byte[] rgbSignature) => throw null; + public bool VerifyHash(System.Byte[] rgbHash, string str, System.Byte[] rgbSignature) => throw null; + public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; + } + + public class DSAOpenSsl : System.Security.Cryptography.DSA + { + public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; + public DSAOpenSsl() => throw null; + public DSAOpenSsl(System.Security.Cryptography.DSAParameters parameters) => throw null; + public DSAOpenSsl(System.IntPtr handle) => throw null; + public DSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; + public DSAOpenSsl(int keySize) => throw null; + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; + public override System.Security.Cryptography.DSAParameters ExportParameters(bool includePrivateParameters) => throw null; + public override void ImportParameters(System.Security.Cryptography.DSAParameters parameters) => throw null; + public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; + } + + public struct DSAParameters + { + public int Counter; + // Stub generator skipped constructor + public System.Byte[] G; + public System.Byte[] J; + public System.Byte[] P; + public System.Byte[] Q; + public System.Byte[] Seed; + public System.Byte[] X; + public System.Byte[] Y; + } + + public class DSASignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter + { + public DSASignatureDeformatter() => throw null; + public DSASignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetHashAlgorithm(string strName) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; + } + + public enum DSASignatureFormat : int + { + IeeeP1363FixedFieldConcatenation = 0, + Rfc3279DerSequence = 1, + } + + public class DSASignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter + { + public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; + public DSASignatureFormatter() => throw null; + public DSASignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetHashAlgorithm(string strName) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public abstract class DeriveBytes : System.IDisposable + { + protected DeriveBytes() => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public abstract System.Byte[] GetBytes(int cb); + public abstract void Reset(); + } + + public abstract class ECAlgorithm : System.Security.Cryptography.AsymmetricAlgorithm + { + protected ECAlgorithm() => throw null; + public virtual System.Byte[] ExportECPrivateKey() => throw null; + public string ExportECPrivateKeyPem() => throw null; + public virtual System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; + public virtual System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; + public virtual void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; + public virtual void ImportECPrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; + public override void ImportFromPem(System.ReadOnlySpan input) => throw null; + public virtual void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual bool TryExportECPrivateKey(System.Span destination, out int bytesWritten) => throw null; + public bool TryExportECPrivateKeyPem(System.Span destination, out int charsWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + } + + public struct ECCurve + { + public enum ECCurveType : int + { + Characteristic2 = 4, + Implicit = 0, + Named = 5, + PrimeMontgomery = 3, + PrimeShortWeierstrass = 1, + PrimeTwistedEdwards = 2, + } + + + public static class NamedCurves + { + public static System.Security.Cryptography.ECCurve brainpoolP160r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP160t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP192r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP192t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP224r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP224t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP256r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP256t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP320r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP320t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP384r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP384t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP512r1 { get => throw null; } + public static System.Security.Cryptography.ECCurve brainpoolP512t1 { get => throw null; } + public static System.Security.Cryptography.ECCurve nistP256 { get => throw null; } + public static System.Security.Cryptography.ECCurve nistP384 { get => throw null; } + public static System.Security.Cryptography.ECCurve nistP521 { get => throw null; } + } + + + public System.Byte[] A; + public System.Byte[] B; + public System.Byte[] Cofactor; + public static System.Security.Cryptography.ECCurve CreateFromFriendlyName(string oidFriendlyName) => throw null; + public static System.Security.Cryptography.ECCurve CreateFromOid(System.Security.Cryptography.Oid curveOid) => throw null; + public static System.Security.Cryptography.ECCurve CreateFromValue(string oidValue) => throw null; + public System.Security.Cryptography.ECCurve.ECCurveType CurveType; + // Stub generator skipped constructor + public System.Security.Cryptography.ECPoint G; + public System.Security.Cryptography.HashAlgorithmName? Hash; + public bool IsCharacteristic2 { get => throw null; } + public bool IsExplicit { get => throw null; } + public bool IsNamed { get => throw null; } + public bool IsPrime { get => throw null; } + public System.Security.Cryptography.Oid Oid { get => throw null; } + public System.Byte[] Order; + public System.Byte[] Polynomial; + public System.Byte[] Prime; + public System.Byte[] Seed; + public void Validate() => throw null; + } + + public abstract class ECDiffieHellman : System.Security.Cryptography.ECAlgorithm + { + public static System.Security.Cryptography.ECDiffieHellman Create() => throw null; + public static System.Security.Cryptography.ECDiffieHellman Create(System.Security.Cryptography.ECCurve curve) => throw null; + public static System.Security.Cryptography.ECDiffieHellman Create(System.Security.Cryptography.ECParameters parameters) => throw null; + public static System.Security.Cryptography.ECDiffieHellman Create(string algorithm) => throw null; + public System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public virtual System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; + public System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey) => throw null; + public virtual System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; + public virtual System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; + public virtual System.Byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Byte[] prfLabel, System.Byte[] prfSeed) => throw null; + protected ECDiffieHellman() => throw null; + public override void FromXmlString(string xmlString) => throw null; + public override string KeyExchangeAlgorithm { get => throw null; } + public abstract System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get; } + public override string SignatureAlgorithm { get => throw null; } + public override string ToXmlString(bool includePrivateParameters) => throw null; + } + + public class ECDiffieHellmanCng : System.Security.Cryptography.ECDiffieHellman + { + public override System.Byte[] DeriveKeyFromHash(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; + public override System.Byte[] DeriveKeyFromHmac(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] hmacKey, System.Byte[] secretPrepend, System.Byte[] secretAppend) => throw null; + public System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.CngKey otherPartyPublicKey) => throw null; + public override System.Byte[] DeriveKeyMaterial(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; + public override System.Byte[] DeriveKeyTls(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey, System.Byte[] prfLabel, System.Byte[] prfSeed) => throw null; + public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.CngKey otherPartyPublicKey) => throw null; + public Microsoft.Win32.SafeHandles.SafeNCryptSecretHandle DeriveSecretAgreementHandle(System.Security.Cryptography.ECDiffieHellmanPublicKey otherPartyPublicKey) => throw null; + protected override void Dispose(bool disposing) => throw null; + public ECDiffieHellmanCng() => throw null; + public ECDiffieHellmanCng(System.Security.Cryptography.CngKey key) => throw null; + public ECDiffieHellmanCng(System.Security.Cryptography.ECCurve curve) => throw null; + public ECDiffieHellmanCng(int keySize) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; + public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) => throw null; + public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; + public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get => throw null; set => throw null; } + public System.Byte[] HmacKey { get => throw null; set => throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public System.Security.Cryptography.CngKey Key { get => throw null; } + public System.Security.Cryptography.ECDiffieHellmanKeyDerivationFunction KeyDerivationFunction { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public System.Byte[] Label { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get => throw null; } + public System.Byte[] SecretAppend { get => throw null; set => throw null; } + public System.Byte[] SecretPrepend { get => throw null; set => throw null; } + public System.Byte[] Seed { get => throw null; set => throw null; } + public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public bool UseSecretAgreementAsHmacKey { get => throw null; } + } + + public class ECDiffieHellmanCngPublicKey : System.Security.Cryptography.ECDiffieHellmanPublicKey + { + public System.Security.Cryptography.CngKeyBlobFormat BlobFormat { get => throw null; } + protected override void Dispose(bool disposing) => throw null; + public override System.Security.Cryptography.ECParameters ExportExplicitParameters() => throw null; + public override System.Security.Cryptography.ECParameters ExportParameters() => throw null; + public static System.Security.Cryptography.ECDiffieHellmanPublicKey FromByteArray(System.Byte[] publicKeyBlob, System.Security.Cryptography.CngKeyBlobFormat format) => throw null; + public static System.Security.Cryptography.ECDiffieHellmanCngPublicKey FromXmlString(string xml) => throw null; + public System.Security.Cryptography.CngKey Import() => throw null; + public override string ToXmlString() => throw null; + } + + public enum ECDiffieHellmanKeyDerivationFunction : int + { + Hash = 0, + Hmac = 1, + Tls = 2, + } + + public class ECDiffieHellmanOpenSsl : System.Security.Cryptography.ECDiffieHellman + { + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; + public ECDiffieHellmanOpenSsl() => throw null; + public ECDiffieHellmanOpenSsl(System.Security.Cryptography.ECCurve curve) => throw null; + public ECDiffieHellmanOpenSsl(System.IntPtr handle) => throw null; + public ECDiffieHellmanOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; + public ECDiffieHellmanOpenSsl(int keySize) => throw null; + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; + public override System.Security.Cryptography.ECDiffieHellmanPublicKey PublicKey { get => throw null; } + } + + public abstract class ECDiffieHellmanPublicKey : System.IDisposable + { + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + protected ECDiffieHellmanPublicKey() => throw null; + protected ECDiffieHellmanPublicKey(System.Byte[] keyBlob) => throw null; + public virtual System.Security.Cryptography.ECParameters ExportExplicitParameters() => throw null; + public virtual System.Security.Cryptography.ECParameters ExportParameters() => throw null; + public virtual System.Byte[] ExportSubjectPublicKeyInfo() => throw null; + public virtual System.Byte[] ToByteArray() => throw null; + public virtual string ToXmlString() => throw null; + public virtual bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class ECDsa : System.Security.Cryptography.ECAlgorithm + { + public static System.Security.Cryptography.ECDsa Create() => throw null; + public static System.Security.Cryptography.ECDsa Create(System.Security.Cryptography.ECCurve curve) => throw null; + public static System.Security.Cryptography.ECDsa Create(System.Security.Cryptography.ECParameters parameters) => throw null; + public static System.Security.Cryptography.ECDsa Create(string algorithm) => throw null; + protected ECDsa() => throw null; + public override void FromXmlString(string xmlString) => throw null; + public int GetMaxSignatureSize(System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public override string KeyExchangeAlgorithm { get => throw null; } + public virtual System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public System.Byte[] SignData(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public int SignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public int SignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] SignDataCore(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] SignDataCore(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public abstract System.Byte[] SignHash(System.Byte[] hash); + public System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public System.Byte[] SignHash(System.ReadOnlySpan hash) => throw null; + public System.Byte[] SignHash(System.ReadOnlySpan hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public int SignHash(System.ReadOnlySpan hash, System.Span destination) => throw null; + public int SignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual System.Byte[] SignHashCore(System.ReadOnlySpan hash, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public override string SignatureAlgorithm { get => throw null; } + public override string ToXmlString(bool includePrivateParameters) => throw null; + protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; + public bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; + protected virtual bool TrySignDataCore(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public virtual bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, out int bytesWritten) => throw null; + protected virtual bool TrySignHashCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifyDataCore(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifyDataCore(System.IO.Stream data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public abstract bool VerifyHash(System.Byte[] hash, System.Byte[] signature); + public bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + public virtual bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature) => throw null; + public bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + protected virtual bool VerifyHashCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + } + + public class ECDsaCng : System.Security.Cryptography.ECDsa + { + protected override void Dispose(bool disposing) => throw null; + public ECDsaCng() => throw null; + public ECDsaCng(System.Security.Cryptography.CngKey key) => throw null; + public ECDsaCng(System.Security.Cryptography.ECCurve curve) => throw null; + public ECDsaCng(int keySize) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Security.Cryptography.ECParameters ExportExplicitParameters(bool includePrivateParameters) => throw null; + public override System.Security.Cryptography.ECParameters ExportParameters(bool includePrivateParameters) => throw null; + public void FromXmlString(string xml, System.Security.Cryptography.ECKeyXmlFormat format) => throw null; + public override void GenerateKey(System.Security.Cryptography.ECCurve curve) => throw null; + public System.Security.Cryptography.CngAlgorithm HashAlgorithm { get => throw null; set => throw null; } + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.ECParameters parameters) => throw null; + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public System.Security.Cryptography.CngKey Key { get => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public System.Byte[] SignData(System.Byte[] data) => throw null; + public System.Byte[] SignData(System.Byte[] data, int offset, int count) => throw null; + public System.Byte[] SignData(System.IO.Stream data) => throw null; + public override System.Byte[] SignHash(System.Byte[] hash) => throw null; + public string ToXmlString(System.Security.Cryptography.ECKeyXmlFormat format) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public override bool TrySignHash(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TrySignHashCore(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.DSASignatureFormat signatureFormat, out int bytesWritten) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature) => throw null; + public bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature) => throw null; + public bool VerifyData(System.IO.Stream data, System.Byte[] signature) => throw null; + public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature) => throw null; + public override bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature) => throw null; + protected override bool VerifyHashCore(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.DSASignatureFormat signatureFormat) => throw null; + } + + public class ECDsaOpenSsl : System.Security.Cryptography.ECDsa + { + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; + public ECDsaOpenSsl() => throw null; + public ECDsaOpenSsl(System.Security.Cryptography.ECCurve curve) => throw null; + public ECDsaOpenSsl(System.IntPtr handle) => throw null; + public ECDsaOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; + public ECDsaOpenSsl(int keySize) => throw null; + public override System.Byte[] SignHash(System.Byte[] hash) => throw null; + public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature) => throw null; + } + + public enum ECKeyXmlFormat : int + { + Rfc4050 = 0, + } + + public struct ECParameters + { + public System.Security.Cryptography.ECCurve Curve; + public System.Byte[] D; + // Stub generator skipped constructor + public System.Security.Cryptography.ECPoint Q; + public void Validate() => throw null; + } + + public struct ECPoint + { + // Stub generator skipped constructor + public System.Byte[] X; + public System.Byte[] Y; + } + + public class FromBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform + { + public virtual bool CanReuseTransform { get => throw null; } + public bool CanTransformMultipleBlocks { get => throw null; } + public void Clear() => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public FromBase64Transform() => throw null; + public FromBase64Transform(System.Security.Cryptography.FromBase64TransformMode whitespaces) => throw null; + public int InputBlockSize { get => throw null; } + public int OutputBlockSize { get => throw null; } + public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; + public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; + // ERR: Stub generator didn't handle member: ~FromBase64Transform + } + + public enum FromBase64TransformMode : int + { + DoNotIgnoreWhiteSpaces = 1, + IgnoreWhiteSpaces = 0, + } + + public static class HKDF + { + public static System.Byte[] DeriveKey(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] ikm, int outputLength, System.Byte[] salt = default(System.Byte[]), System.Byte[] info = default(System.Byte[])) => throw null; + public static void DeriveKey(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan ikm, System.Span output, System.ReadOnlySpan salt, System.ReadOnlySpan info) => throw null; + public static System.Byte[] Expand(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] prk, int outputLength, System.Byte[] info = default(System.Byte[])) => throw null; + public static void Expand(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan prk, System.Span output, System.ReadOnlySpan info) => throw null; + public static System.Byte[] Extract(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.Byte[] ikm, System.Byte[] salt = default(System.Byte[])) => throw null; + public static int Extract(System.Security.Cryptography.HashAlgorithmName hashAlgorithmName, System.ReadOnlySpan ikm, System.ReadOnlySpan salt, System.Span prk) => throw null; + } + + public abstract class HMAC : System.Security.Cryptography.KeyedHashAlgorithm + { + protected int BlockSizeValue { get => throw null; set => throw null; } + public static System.Security.Cryptography.HMAC Create() => throw null; + public static System.Security.Cryptography.HMAC Create(string algorithmName) => throw null; + protected override void Dispose(bool disposing) => throw null; + protected HMAC() => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public string HashName { get => throw null; set => throw null; } + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class HMACMD5 : System.Security.Cryptography.HMAC + { + protected override void Dispose(bool disposing) => throw null; + public HMACMD5() => throw null; + public HMACMD5(System.Byte[] key) => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.IO.Stream source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.Byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class HMACSHA1 : System.Security.Cryptography.HMAC + { + protected override void Dispose(bool disposing) => throw null; + public HMACSHA1() => throw null; + public HMACSHA1(System.Byte[] key) => throw null; + public HMACSHA1(System.Byte[] key, bool useManagedSha1) => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.IO.Stream source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.Byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class HMACSHA256 : System.Security.Cryptography.HMAC + { + protected override void Dispose(bool disposing) => throw null; + public HMACSHA256() => throw null; + public HMACSHA256(System.Byte[] key) => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.IO.Stream source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.Byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class HMACSHA384 : System.Security.Cryptography.HMAC + { + protected override void Dispose(bool disposing) => throw null; + public HMACSHA384() => throw null; + public HMACSHA384(System.Byte[] key) => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.IO.Stream source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.Byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public bool ProduceLegacyHmacValues { get => throw null; set => throw null; } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class HMACSHA512 : System.Security.Cryptography.HMAC + { + protected override void Dispose(bool disposing) => throw null; + public HMACSHA512() => throw null; + public HMACSHA512(System.Byte[] key) => throw null; + protected override void HashCore(System.Byte[] rgb, int ib, int cb) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.Byte[] key, System.IO.Stream source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) => throw null; + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.Byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + public override void Initialize() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public bool ProduceLegacyHmacValues { get => throw null; set => throw null; } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class HashAlgorithm : System.IDisposable, System.Security.Cryptography.ICryptoTransform + { + public virtual bool CanReuseTransform { get => throw null; } + public virtual bool CanTransformMultipleBlocks { get => throw null; } + public void Clear() => throw null; + public System.Byte[] ComputeHash(System.Byte[] buffer) => throw null; + public System.Byte[] ComputeHash(System.Byte[] buffer, int offset, int count) => throw null; + public System.Byte[] ComputeHash(System.IO.Stream inputStream) => throw null; + public System.Threading.Tasks.Task ComputeHashAsync(System.IO.Stream inputStream, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Security.Cryptography.HashAlgorithm Create() => throw null; + public static System.Security.Cryptography.HashAlgorithm Create(string hashName) => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public virtual System.Byte[] Hash { get => throw null; } + protected HashAlgorithm() => throw null; + protected abstract void HashCore(System.Byte[] array, int ibStart, int cbSize); + protected virtual void HashCore(System.ReadOnlySpan source) => throw null; + protected abstract System.Byte[] HashFinal(); + public virtual int HashSize { get => throw null; } + protected int HashSizeValue; + protected internal System.Byte[] HashValue; + public abstract void Initialize(); + public virtual int InputBlockSize { get => throw null; } + public virtual int OutputBlockSize { get => throw null; } + protected int State; + public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; + public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; + public bool TryComputeHash(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + protected virtual bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public struct HashAlgorithmName : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.HashAlgorithmName left, System.Security.Cryptography.HashAlgorithmName right) => throw null; + public static bool operator ==(System.Security.Cryptography.HashAlgorithmName left, System.Security.Cryptography.HashAlgorithmName right) => throw null; + public bool Equals(System.Security.Cryptography.HashAlgorithmName other) => throw null; + public override bool Equals(object obj) => throw null; + public static System.Security.Cryptography.HashAlgorithmName FromOid(string oidValue) => throw null; + public override int GetHashCode() => throw null; + // Stub generator skipped constructor + public HashAlgorithmName(string name) => throw null; + public static System.Security.Cryptography.HashAlgorithmName MD5 { get => throw null; } + public string Name { get => throw null; } + public static System.Security.Cryptography.HashAlgorithmName SHA1 { get => throw null; } + public static System.Security.Cryptography.HashAlgorithmName SHA256 { get => throw null; } + public static System.Security.Cryptography.HashAlgorithmName SHA384 { get => throw null; } + public static System.Security.Cryptography.HashAlgorithmName SHA512 { get => throw null; } + public override string ToString() => throw null; + public static bool TryFromOid(string oidValue, out System.Security.Cryptography.HashAlgorithmName value) => throw null; + } + + public interface ICryptoTransform : System.IDisposable + { + bool CanReuseTransform { get; } + bool CanTransformMultipleBlocks { get; } + int InputBlockSize { get; } + int OutputBlockSize { get; } + int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset); + System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount); + } + + public interface ICspAsymmetricAlgorithm + { + System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get; } + System.Byte[] ExportCspBlob(bool includePrivateParameters); + void ImportCspBlob(System.Byte[] rawData); + } + + public class IncrementalHash : System.IDisposable + { + public System.Security.Cryptography.HashAlgorithmName AlgorithmName { get => throw null; } + public void AppendData(System.Byte[] data) => throw null; + public void AppendData(System.Byte[] data, int offset, int count) => throw null; + public void AppendData(System.ReadOnlySpan data) => throw null; + public static System.Security.Cryptography.IncrementalHash CreateHMAC(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Byte[] key) => throw null; + public static System.Security.Cryptography.IncrementalHash CreateHMAC(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.ReadOnlySpan key) => throw null; + public static System.Security.Cryptography.IncrementalHash CreateHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public void Dispose() => throw null; + public System.Byte[] GetCurrentHash() => throw null; + public int GetCurrentHash(System.Span destination) => throw null; + public System.Byte[] GetHashAndReset() => throw null; + public int GetHashAndReset(System.Span destination) => throw null; + public int HashLengthInBytes { get => throw null; } + public bool TryGetCurrentHash(System.Span destination, out int bytesWritten) => throw null; + public bool TryGetHashAndReset(System.Span destination, out int bytesWritten) => throw null; + } + + public enum KeyNumber : int + { + Exchange = 1, + Signature = 2, + } + + public class KeySizes + { + public KeySizes(int minSize, int maxSize, int skipSize) => throw null; + public int MaxSize { get => throw null; } + public int MinSize { get => throw null; } + public int SkipSize { get => throw null; } + } + + public abstract class KeyedHashAlgorithm : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.KeyedHashAlgorithm Create() => throw null; + public static System.Security.Cryptography.KeyedHashAlgorithm Create(string algName) => throw null; + protected override void Dispose(bool disposing) => throw null; + public virtual System.Byte[] Key { get => throw null; set => throw null; } + protected System.Byte[] KeyValue; + protected KeyedHashAlgorithm() => throw null; + } + + public abstract class MD5 : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.MD5 Create() => throw null; + public static System.Security.Cryptography.MD5 Create(string algName) => throw null; + public static System.Byte[] HashData(System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.IO.Stream source) => throw null; + public static int HashData(System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + protected MD5() => throw null; + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + } + + public class MD5CryptoServiceProvider : System.Security.Cryptography.MD5 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public MD5CryptoServiceProvider() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class MaskGenerationMethod + { + public abstract System.Byte[] GenerateMask(System.Byte[] rgbSeed, int cbReturn); + protected MaskGenerationMethod() => throw null; + } + + public class Oid + { + public string FriendlyName { get => throw null; set => throw null; } + public static System.Security.Cryptography.Oid FromFriendlyName(string friendlyName, System.Security.Cryptography.OidGroup group) => throw null; + public static System.Security.Cryptography.Oid FromOidValue(string oidValue, System.Security.Cryptography.OidGroup group) => throw null; + public Oid() => throw null; + public Oid(System.Security.Cryptography.Oid oid) => throw null; + public Oid(string oid) => throw null; + public Oid(string value, string friendlyName) => throw null; + public string Value { get => throw null; set => throw null; } + } + + public class OidCollection : System.Collections.ICollection, System.Collections.IEnumerable + { + public int Add(System.Security.Cryptography.Oid oid) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(System.Security.Cryptography.Oid[] array, int index) => throw null; + public int Count { get => throw null; } + public System.Security.Cryptography.OidEnumerator GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public bool IsSynchronized { get => throw null; } + public System.Security.Cryptography.Oid this[int index] { get => throw null; } + public System.Security.Cryptography.Oid this[string oid] { get => throw null; } + public OidCollection() => throw null; + public object SyncRoot { get => throw null; } + } + + public class OidEnumerator : System.Collections.IEnumerator + { + public System.Security.Cryptography.Oid Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + public bool MoveNext() => throw null; + public void Reset() => throw null; + } + + public enum OidGroup : int + { + All = 0, + Attribute = 5, + EncryptionAlgorithm = 2, + EnhancedKeyUsage = 7, + ExtensionOrAttribute = 6, + HashAlgorithm = 1, + KeyDerivationFunction = 10, + Policy = 8, + PublicKeyAlgorithm = 3, + SignatureAlgorithm = 4, + Template = 9, + } + + public class PKCS1MaskGenerationMethod : System.Security.Cryptography.MaskGenerationMethod + { + public override System.Byte[] GenerateMask(System.Byte[] rgbSeed, int cbReturn) => throw null; + public string HashName { get => throw null; set => throw null; } + public PKCS1MaskGenerationMethod() => throw null; + } + + public enum PaddingMode : int + { + ANSIX923 = 4, + ISO10126 = 5, + None = 1, + PKCS7 = 2, + Zeros = 3, + } + + public class PasswordDeriveBytes : System.Security.Cryptography.DeriveBytes + { + public System.Byte[] CryptDeriveKey(string algname, string alghashname, int keySize, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Byte[] GetBytes(int cb) => throw null; + public string HashName { get => throw null; set => throw null; } + public int IterationCount { get => throw null; set => throw null; } + public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt) => throw null; + public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, System.Security.Cryptography.CspParameters cspParams) => throw null; + public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, string hashName, int iterations) => throw null; + public PasswordDeriveBytes(System.Byte[] password, System.Byte[] salt, string hashName, int iterations, System.Security.Cryptography.CspParameters cspParams) => throw null; + public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt) => throw null; + public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, System.Security.Cryptography.CspParameters cspParams) => throw null; + public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, string strHashName, int iterations) => throw null; + public PasswordDeriveBytes(string strPassword, System.Byte[] rgbSalt, string strHashName, int iterations, System.Security.Cryptography.CspParameters cspParams) => throw null; + public override void Reset() => throw null; + public System.Byte[] Salt { get => throw null; set => throw null; } + } + + public enum PbeEncryptionAlgorithm : int + { + Aes128Cbc = 1, + Aes192Cbc = 2, + Aes256Cbc = 3, + TripleDes3KeyPkcs12 = 4, + Unknown = 0, + } + + public class PbeParameters + { + public System.Security.Cryptography.PbeEncryptionAlgorithm EncryptionAlgorithm { get => throw null; } + public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } + public int IterationCount { get => throw null; } + public PbeParameters(System.Security.Cryptography.PbeEncryptionAlgorithm encryptionAlgorithm, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int iterationCount) => throw null; + } + + public static class PemEncoding + { + public static System.Security.Cryptography.PemFields Find(System.ReadOnlySpan pemData) => throw null; + public static int GetEncodedSize(int labelLength, int dataLength) => throw null; + public static bool TryFind(System.ReadOnlySpan pemData, out System.Security.Cryptography.PemFields fields) => throw null; + public static bool TryWrite(System.ReadOnlySpan label, System.ReadOnlySpan data, System.Span destination, out int charsWritten) => throw null; + public static System.Char[] Write(System.ReadOnlySpan label, System.ReadOnlySpan data) => throw null; + public static string WriteString(System.ReadOnlySpan label, System.ReadOnlySpan data) => throw null; + } + + public struct PemFields + { + public System.Range Base64Data { get => throw null; } + public int DecodedDataLength { get => throw null; } + public System.Range Label { get => throw null; } + public System.Range Location { get => throw null; } + // Stub generator skipped constructor + } + + public abstract class RC2 : System.Security.Cryptography.SymmetricAlgorithm + { + public static System.Security.Cryptography.RC2 Create() => throw null; + public static System.Security.Cryptography.RC2 Create(string AlgName) => throw null; + public virtual int EffectiveKeySize { get => throw null; set => throw null; } + protected int EffectiveKeySizeValue; + public override int KeySize { get => throw null; set => throw null; } + protected RC2() => throw null; + } + + public class RC2CryptoServiceProvider : System.Security.Cryptography.RC2 + { + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override int EffectiveKeySize { get => throw null; set => throw null; } + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public RC2CryptoServiceProvider() => throw null; + public bool UseSalt { get => throw null; set => throw null; } + } + + public class RNGCryptoServiceProvider : System.Security.Cryptography.RandomNumberGenerator + { + protected override void Dispose(bool disposing) => throw null; + public override void GetBytes(System.Byte[] data) => throw null; + public override void GetBytes(System.Byte[] data, int offset, int count) => throw null; + public override void GetBytes(System.Span data) => throw null; + public override void GetNonZeroBytes(System.Byte[] data) => throw null; + public override void GetNonZeroBytes(System.Span data) => throw null; + public RNGCryptoServiceProvider() => throw null; + public RNGCryptoServiceProvider(System.Byte[] rgb) => throw null; + public RNGCryptoServiceProvider(System.Security.Cryptography.CspParameters cspParams) => throw null; + public RNGCryptoServiceProvider(string str) => throw null; + } + + public abstract class RSA : System.Security.Cryptography.AsymmetricAlgorithm + { + public static System.Security.Cryptography.RSA Create() => throw null; + public static System.Security.Cryptography.RSA Create(System.Security.Cryptography.RSAParameters parameters) => throw null; + public static System.Security.Cryptography.RSA Create(int keySizeInBits) => throw null; + public static System.Security.Cryptography.RSA Create(string algName) => throw null; + public virtual System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public System.Byte[] Decrypt(System.ReadOnlySpan data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public int Decrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public virtual System.Byte[] DecryptValue(System.Byte[] rgb) => throw null; + public virtual System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public System.Byte[] Encrypt(System.ReadOnlySpan data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public int Encrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public virtual System.Byte[] EncryptValue(System.Byte[] rgb) => throw null; + public abstract System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters); + public virtual System.Byte[] ExportRSAPrivateKey() => throw null; + public string ExportRSAPrivateKeyPem() => throw null; + public virtual System.Byte[] ExportRSAPublicKey() => throw null; + public string ExportRSAPublicKeyPem() => throw null; + public override void FromXmlString(string xmlString) => throw null; + protected virtual System.Byte[] HashData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + protected virtual System.Byte[] HashData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan passwordBytes) => throw null; + public override void ImportFromEncryptedPem(System.ReadOnlySpan input, System.ReadOnlySpan password) => throw null; + public override void ImportFromPem(System.ReadOnlySpan input) => throw null; + public abstract void ImportParameters(System.Security.Cryptography.RSAParameters parameters); + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual void ImportRSAPrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public virtual void ImportRSAPublicKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; + public override string KeyExchangeAlgorithm { get => throw null; } + protected RSA() => throw null; + public System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual System.Byte[] SignData(System.Byte[] data, int offset, int count, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public System.Byte[] SignData(System.ReadOnlySpan data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public int SignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual System.Byte[] SignData(System.IO.Stream data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public System.Byte[] SignHash(System.ReadOnlySpan hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public int SignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public override string SignatureAlgorithm { get => throw null; } + public override string ToXmlString(bool includePrivateParameters) => throw null; + public virtual bool TryDecrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; + public virtual bool TryEncrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public virtual bool TryExportRSAPrivateKey(System.Span destination, out int bytesWritten) => throw null; + public bool TryExportRSAPrivateKeyPem(System.Span destination, out int charsWritten) => throw null; + public virtual bool TryExportRSAPublicKey(System.Span destination, out int bytesWritten) => throw null; + public bool TryExportRSAPublicKeyPem(System.Span destination, out int charsWritten) => throw null; + public override bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + protected virtual bool TryHashData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, out int bytesWritten) => throw null; + public virtual bool TrySignData(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) => throw null; + public virtual bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) => throw null; + public bool VerifyData(System.Byte[] data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual bool VerifyData(System.Byte[] data, int offset, int count, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual bool VerifyData(System.ReadOnlySpan data, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public bool VerifyData(System.IO.Stream data, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public virtual bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + } + + public class RSACng : System.Security.Cryptography.RSA + { + public override System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Byte[] ExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters) => throw null; + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; + public override void ImportPkcs8PrivateKey(System.ReadOnlySpan source, out int bytesRead) => throw null; + public System.Security.Cryptography.CngKey Key { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public RSACng() => throw null; + public RSACng(System.Security.Cryptography.CngKey key) => throw null; + public RSACng(int keySize) => throw null; + public override System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public override bool TryDecrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; + public override bool TryEncrypt(System.ReadOnlySpan data, System.Span destination, System.Security.Cryptography.RSAEncryptionPadding padding, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.Security.Cryptography.PbeParameters pbeParameters, System.Span destination, out int bytesWritten) => throw null; + public override bool TryExportPkcs8PrivateKey(System.Span destination, out int bytesWritten) => throw null; + public override bool TrySignHash(System.ReadOnlySpan hash, System.Span destination, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding, out int bytesWritten) => throw null; + public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public override bool VerifyHash(System.ReadOnlySpan hash, System.ReadOnlySpan signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + } + + public class RSACryptoServiceProvider : System.Security.Cryptography.RSA, System.Security.Cryptography.ICspAsymmetricAlgorithm + { + public System.Security.Cryptography.CspKeyContainerInfo CspKeyContainerInfo { get => throw null; } + public override System.Byte[] Decrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public System.Byte[] Decrypt(System.Byte[] rgb, bool fOAEP) => throw null; + public override System.Byte[] DecryptValue(System.Byte[] rgb) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Byte[] Encrypt(System.Byte[] data, System.Security.Cryptography.RSAEncryptionPadding padding) => throw null; + public System.Byte[] Encrypt(System.Byte[] rgb, bool fOAEP) => throw null; + public override System.Byte[] EncryptValue(System.Byte[] rgb) => throw null; + public System.Byte[] ExportCspBlob(bool includePrivateParameters) => throw null; + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; + public void ImportCspBlob(System.Byte[] keyBlob) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan passwordBytes, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportEncryptedPkcs8PrivateKey(System.ReadOnlySpan password, System.ReadOnlySpan source, out int bytesRead) => throw null; + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; + public override string KeyExchangeAlgorithm { get => throw null; } + public override int KeySize { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public bool PersistKeyInCsp { get => throw null; set => throw null; } + public bool PublicOnly { get => throw null; } + public RSACryptoServiceProvider() => throw null; + public RSACryptoServiceProvider(System.Security.Cryptography.CspParameters parameters) => throw null; + public RSACryptoServiceProvider(int dwKeySize) => throw null; + public RSACryptoServiceProvider(int dwKeySize, System.Security.Cryptography.CspParameters parameters) => throw null; + public System.Byte[] SignData(System.Byte[] buffer, int offset, int count, object halg) => throw null; + public System.Byte[] SignData(System.Byte[] buffer, object halg) => throw null; + public System.Byte[] SignData(System.IO.Stream inputStream, object halg) => throw null; + public override System.Byte[] SignHash(System.Byte[] hash, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public System.Byte[] SignHash(System.Byte[] rgbHash, string str) => throw null; + public override string SignatureAlgorithm { get => throw null; } + public static bool UseMachineKeyStore { get => throw null; set => throw null; } + public bool VerifyData(System.Byte[] buffer, object halg, System.Byte[] signature) => throw null; + public override bool VerifyHash(System.Byte[] hash, System.Byte[] signature, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public bool VerifyHash(System.Byte[] rgbHash, string str, System.Byte[] rgbSignature) => throw null; + } + + public class RSAEncryptionPadding : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.RSAEncryptionPadding left, System.Security.Cryptography.RSAEncryptionPadding right) => throw null; + public static bool operator ==(System.Security.Cryptography.RSAEncryptionPadding left, System.Security.Cryptography.RSAEncryptionPadding right) => throw null; + public static System.Security.Cryptography.RSAEncryptionPadding CreateOaep(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public bool Equals(System.Security.Cryptography.RSAEncryptionPadding other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public System.Security.Cryptography.RSAEncryptionPaddingMode Mode { get => throw null; } + public System.Security.Cryptography.HashAlgorithmName OaepHashAlgorithm { get => throw null; } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA1 { get => throw null; } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA256 { get => throw null; } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA384 { get => throw null; } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA512 { get => throw null; } + public static System.Security.Cryptography.RSAEncryptionPadding Pkcs1 { get => throw null; } + public override string ToString() => throw null; + } + + public enum RSAEncryptionPaddingMode : int + { + Oaep = 1, + Pkcs1 = 0, + } + + public class RSAOAEPKeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter + { + public override System.Byte[] DecryptKeyExchange(System.Byte[] rgbData) => throw null; + public override string Parameters { get => throw null; set => throw null; } + public RSAOAEPKeyExchangeDeformatter() => throw null; + public RSAOAEPKeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public class RSAOAEPKeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter + { + public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData) => throw null; + public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData, System.Type symAlgType) => throw null; + public System.Byte[] Parameter { get => throw null; set => throw null; } + public override string Parameters { get => throw null; } + public RSAOAEPKeyExchangeFormatter() => throw null; + public RSAOAEPKeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public System.Security.Cryptography.RandomNumberGenerator Rng { get => throw null; set => throw null; } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public class RSAOpenSsl : System.Security.Cryptography.RSA + { + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateKeyHandle() => throw null; + public override System.Security.Cryptography.RSAParameters ExportParameters(bool includePrivateParameters) => throw null; + public override void ImportParameters(System.Security.Cryptography.RSAParameters parameters) => throw null; + public RSAOpenSsl() => throw null; + public RSAOpenSsl(System.IntPtr handle) => throw null; + public RSAOpenSsl(System.Security.Cryptography.RSAParameters parameters) => throw null; + public RSAOpenSsl(System.Security.Cryptography.SafeEvpPKeyHandle pkeyHandle) => throw null; + public RSAOpenSsl(int keySize) => throw null; + } + + public class RSAPKCS1KeyExchangeDeformatter : System.Security.Cryptography.AsymmetricKeyExchangeDeformatter + { + public override System.Byte[] DecryptKeyExchange(System.Byte[] rgbIn) => throw null; + public override string Parameters { get => throw null; set => throw null; } + public System.Security.Cryptography.RandomNumberGenerator RNG { get => throw null; set => throw null; } + public RSAPKCS1KeyExchangeDeformatter() => throw null; + public RSAPKCS1KeyExchangeDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public class RSAPKCS1KeyExchangeFormatter : System.Security.Cryptography.AsymmetricKeyExchangeFormatter + { + public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData) => throw null; + public override System.Byte[] CreateKeyExchange(System.Byte[] rgbData, System.Type symAlgType) => throw null; + public override string Parameters { get => throw null; } + public RSAPKCS1KeyExchangeFormatter() => throw null; + public RSAPKCS1KeyExchangeFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public System.Security.Cryptography.RandomNumberGenerator Rng { get => throw null; set => throw null; } + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public class RSAPKCS1SignatureDeformatter : System.Security.Cryptography.AsymmetricSignatureDeformatter + { + public RSAPKCS1SignatureDeformatter() => throw null; + public RSAPKCS1SignatureDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetHashAlgorithm(string strName) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override bool VerifySignature(System.Byte[] rgbHash, System.Byte[] rgbSignature) => throw null; + } + + public class RSAPKCS1SignatureFormatter : System.Security.Cryptography.AsymmetricSignatureFormatter + { + public override System.Byte[] CreateSignature(System.Byte[] rgbHash) => throw null; + public RSAPKCS1SignatureFormatter() => throw null; + public RSAPKCS1SignatureFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public override void SetHashAlgorithm(string strName) => throw null; + public override void SetKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + } + + public struct RSAParameters + { + public System.Byte[] D; + public System.Byte[] DP; + public System.Byte[] DQ; + public System.Byte[] Exponent; + public System.Byte[] InverseQ; + public System.Byte[] Modulus; + public System.Byte[] P; + public System.Byte[] Q; + // Stub generator skipped constructor + } + + public class RSASignaturePadding : System.IEquatable + { + public static bool operator !=(System.Security.Cryptography.RSASignaturePadding left, System.Security.Cryptography.RSASignaturePadding right) => throw null; + public static bool operator ==(System.Security.Cryptography.RSASignaturePadding left, System.Security.Cryptography.RSASignaturePadding right) => throw null; + public bool Equals(System.Security.Cryptography.RSASignaturePadding other) => throw null; + public override bool Equals(object obj) => throw null; + public override int GetHashCode() => throw null; + public System.Security.Cryptography.RSASignaturePaddingMode Mode { get => throw null; } + public static System.Security.Cryptography.RSASignaturePadding Pkcs1 { get => throw null; } + public static System.Security.Cryptography.RSASignaturePadding Pss { get => throw null; } + public override string ToString() => throw null; + } + + public enum RSASignaturePaddingMode : int + { + Pkcs1 = 0, + Pss = 1, + } + + public abstract class RandomNumberGenerator : System.IDisposable + { + public static System.Security.Cryptography.RandomNumberGenerator Create() => throw null; + public static System.Security.Cryptography.RandomNumberGenerator Create(string rngName) => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public static void Fill(System.Span data) => throw null; + public abstract void GetBytes(System.Byte[] data); + public virtual void GetBytes(System.Byte[] data, int offset, int count) => throw null; + public virtual void GetBytes(System.Span data) => throw null; + public static System.Byte[] GetBytes(int count) => throw null; + public static int GetInt32(int toExclusive) => throw null; + public static int GetInt32(int fromInclusive, int toExclusive) => throw null; + public virtual void GetNonZeroBytes(System.Byte[] data) => throw null; + public virtual void GetNonZeroBytes(System.Span data) => throw null; + protected RandomNumberGenerator() => throw null; + } + + public class Rfc2898DeriveBytes : System.Security.Cryptography.DeriveBytes + { + public System.Byte[] CryptDeriveKey(string algname, string alghashname, int keySize, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override System.Byte[] GetBytes(int cb) => throw null; + public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } + public int IterationCount { get => throw null; set => throw null; } + public static System.Byte[] Pbkdf2(System.Byte[] password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; + public static void Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, System.Span destination, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public static System.Byte[] Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; + public static void Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, System.Span destination, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public static System.Byte[] Pbkdf2(System.ReadOnlySpan password, System.ReadOnlySpan salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; + public static System.Byte[] Pbkdf2(string password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, int outputLength) => throw null; + public override void Reset() => throw null; + public Rfc2898DeriveBytes(System.Byte[] password, System.Byte[] salt, int iterations) => throw null; + public Rfc2898DeriveBytes(System.Byte[] password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public Rfc2898DeriveBytes(string password, System.Byte[] salt) => throw null; + public Rfc2898DeriveBytes(string password, System.Byte[] salt, int iterations) => throw null; + public Rfc2898DeriveBytes(string password, System.Byte[] salt, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public Rfc2898DeriveBytes(string password, int saltSize) => throw null; + public Rfc2898DeriveBytes(string password, int saltSize, int iterations) => throw null; + public Rfc2898DeriveBytes(string password, int saltSize, int iterations, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public System.Byte[] Salt { get => throw null; set => throw null; } + } + + public abstract class Rijndael : System.Security.Cryptography.SymmetricAlgorithm + { + public static System.Security.Cryptography.Rijndael Create() => throw null; + public static System.Security.Cryptography.Rijndael Create(string algName) => throw null; + protected Rijndael() => throw null; + } + + public class RijndaelManaged : System.Security.Cryptography.Rijndael + { + public override int BlockSize { get => throw null; set => throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override int FeedbackSize { get => throw null; set => throw null; } + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] IV { get => throw null; set => throw null; } + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } + public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } + public RijndaelManaged() => throw null; + } + + public abstract class SHA1 : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.SHA1 Create() => throw null; + public static System.Security.Cryptography.SHA1 Create(string hashName) => throw null; + public static System.Byte[] HashData(System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.IO.Stream source) => throw null; + public static int HashData(System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + protected SHA1() => throw null; + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA1CryptoServiceProvider : System.Security.Cryptography.SHA1 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA1CryptoServiceProvider() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA1Managed : System.Security.Cryptography.SHA1 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA1Managed() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class SHA256 : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.SHA256 Create() => throw null; + public static System.Security.Cryptography.SHA256 Create(string hashName) => throw null; + public static System.Byte[] HashData(System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.IO.Stream source) => throw null; + public static int HashData(System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + protected SHA256() => throw null; + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA256CryptoServiceProvider : System.Security.Cryptography.SHA256 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA256CryptoServiceProvider() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA256Managed : System.Security.Cryptography.SHA256 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA256Managed() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class SHA384 : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.SHA384 Create() => throw null; + public static System.Security.Cryptography.SHA384 Create(string hashName) => throw null; + public static System.Byte[] HashData(System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.IO.Stream source) => throw null; + public static int HashData(System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + protected SHA384() => throw null; + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA384CryptoServiceProvider : System.Security.Cryptography.SHA384 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA384CryptoServiceProvider() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA384Managed : System.Security.Cryptography.SHA384 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA384Managed() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public abstract class SHA512 : System.Security.Cryptography.HashAlgorithm + { + public static System.Security.Cryptography.SHA512 Create() => throw null; + public static System.Security.Cryptography.SHA512 Create(string hashName) => throw null; + public static System.Byte[] HashData(System.Byte[] source) => throw null; + public static System.Byte[] HashData(System.ReadOnlySpan source) => throw null; + public static int HashData(System.ReadOnlySpan source, System.Span destination) => throw null; + public static System.Byte[] HashData(System.IO.Stream source) => throw null; + public static int HashData(System.IO.Stream source, System.Span destination) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public const int HashSizeInBits = default; + public const int HashSizeInBytes = default; + protected SHA512() => throw null; + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA512CryptoServiceProvider : System.Security.Cryptography.SHA512 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA512CryptoServiceProvider() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class SHA512Managed : System.Security.Cryptography.SHA512 + { + protected override void Dispose(bool disposing) => throw null; + protected override void HashCore(System.Byte[] array, int ibStart, int cbSize) => throw null; + protected override void HashCore(System.ReadOnlySpan source) => throw null; + protected override System.Byte[] HashFinal() => throw null; + public override void Initialize() => throw null; + public SHA512Managed() => throw null; + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) => throw null; + } + + public class SafeEvpPKeyHandle : System.Runtime.InteropServices.SafeHandle + { + public System.Security.Cryptography.SafeEvpPKeyHandle DuplicateHandle() => throw null; + public override bool IsInvalid { get => throw null; } + public static System.Int64 OpenSslVersion { get => throw null; } + protected override bool ReleaseHandle() => throw null; + public SafeEvpPKeyHandle() : base(default(System.IntPtr), default(bool)) => throw null; + public SafeEvpPKeyHandle(System.IntPtr handle, bool ownsHandle) : base(default(System.IntPtr), default(bool)) => throw null; + } + + public class SignatureDescription + { + public virtual System.Security.Cryptography.AsymmetricSignatureDeformatter CreateDeformatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public virtual System.Security.Cryptography.HashAlgorithm CreateDigest() => throw null; + public virtual System.Security.Cryptography.AsymmetricSignatureFormatter CreateFormatter(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public string DeformatterAlgorithm { get => throw null; set => throw null; } + public string DigestAlgorithm { get => throw null; set => throw null; } + public string FormatterAlgorithm { get => throw null; set => throw null; } + public string KeyAlgorithm { get => throw null; set => throw null; } + public SignatureDescription() => throw null; + public SignatureDescription(System.Security.SecurityElement el) => throw null; + } + + public abstract class SymmetricAlgorithm : System.IDisposable + { + public virtual int BlockSize { get => throw null; set => throw null; } + protected int BlockSizeValue; + public void Clear() => throw null; + public static System.Security.Cryptography.SymmetricAlgorithm Create() => throw null; + public static System.Security.Cryptography.SymmetricAlgorithm Create(string algName) => throw null; + public virtual System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public abstract System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV); + public virtual System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public abstract System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV); + public System.Byte[] DecryptCbc(System.Byte[] ciphertext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public System.Byte[] DecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public int DecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public System.Byte[] DecryptCfb(System.Byte[] ciphertext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public System.Byte[] DecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public int DecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public System.Byte[] DecryptEcb(System.Byte[] ciphertext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public System.Byte[] DecryptEcb(System.ReadOnlySpan ciphertext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public int DecryptEcb(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public System.Byte[] EncryptCbc(System.Byte[] plaintext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public System.Byte[] EncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public int EncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public System.Byte[] EncryptCfb(System.Byte[] plaintext, System.Byte[] iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public System.Byte[] EncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public int EncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public System.Byte[] EncryptEcb(System.Byte[] plaintext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public System.Byte[] EncryptEcb(System.ReadOnlySpan plaintext, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public int EncryptEcb(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public virtual int FeedbackSize { get => throw null; set => throw null; } + protected int FeedbackSizeValue; + public abstract void GenerateIV(); + public abstract void GenerateKey(); + public int GetCiphertextLengthCbc(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + public int GetCiphertextLengthCfb(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + public int GetCiphertextLengthEcb(int plaintextLength, System.Security.Cryptography.PaddingMode paddingMode) => throw null; + public virtual System.Byte[] IV { get => throw null; set => throw null; } + protected System.Byte[] IVValue; + public virtual System.Byte[] Key { get => throw null; set => throw null; } + public virtual int KeySize { get => throw null; set => throw null; } + protected int KeySizeValue; + protected System.Byte[] KeyValue; + public virtual System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } + protected System.Security.Cryptography.KeySizes[] LegalBlockSizesValue; + public virtual System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + protected System.Security.Cryptography.KeySizes[] LegalKeySizesValue; + public virtual System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } + protected System.Security.Cryptography.CipherMode ModeValue; + public virtual System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } + protected System.Security.Cryptography.PaddingMode PaddingValue; + protected SymmetricAlgorithm() => throw null; + public bool TryDecryptCbc(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + protected virtual bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + public bool TryDecryptCfb(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + protected virtual bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + public bool TryDecryptEcb(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected virtual bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + public bool TryEncryptCbc(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode)) => throw null; + protected virtual bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + public bool TryEncryptCfb(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, out int bytesWritten, System.Security.Cryptography.PaddingMode paddingMode = default(System.Security.Cryptography.PaddingMode), int feedbackSizeInBits = default(int)) => throw null; + protected virtual bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + public bool TryEncryptEcb(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected virtual bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + public bool ValidKeySize(int bitLength) => throw null; + } + + public class ToBase64Transform : System.IDisposable, System.Security.Cryptography.ICryptoTransform + { + public virtual bool CanReuseTransform { get => throw null; } + public bool CanTransformMultipleBlocks { get => throw null; } + public void Clear() => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public int InputBlockSize { get => throw null; } + public int OutputBlockSize { get => throw null; } + public ToBase64Transform() => throw null; + public int TransformBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount, System.Byte[] outputBuffer, int outputOffset) => throw null; + public System.Byte[] TransformFinalBlock(System.Byte[] inputBuffer, int inputOffset, int inputCount) => throw null; + // ERR: Stub generator didn't handle member: ~ToBase64Transform + } + + public abstract class TripleDES : System.Security.Cryptography.SymmetricAlgorithm + { + public static System.Security.Cryptography.TripleDES Create() => throw null; + public static System.Security.Cryptography.TripleDES Create(string str) => throw null; + public static bool IsWeakKey(System.Byte[] rgbKey) => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + protected TripleDES() => throw null; + } + + public class TripleDESCng : System.Security.Cryptography.TripleDES + { + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public TripleDESCng() => throw null; + public TripleDESCng(string keyName) => throw null; + public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider) => throw null; + public TripleDESCng(string keyName, System.Security.Cryptography.CngProvider provider, System.Security.Cryptography.CngKeyOpenOptions openOptions) => throw null; + protected override bool TryDecryptCbcCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryDecryptCfbCore(System.ReadOnlySpan ciphertext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + protected override bool TryDecryptEcbCore(System.ReadOnlySpan ciphertext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryEncryptCbcCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + protected override bool TryEncryptCfbCore(System.ReadOnlySpan plaintext, System.ReadOnlySpan iv, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, int feedbackSizeInBits, out int bytesWritten) => throw null; + protected override bool TryEncryptEcbCore(System.ReadOnlySpan plaintext, System.Span destination, System.Security.Cryptography.PaddingMode paddingMode, out int bytesWritten) => throw null; + } + + public class TripleDESCryptoServiceProvider : System.Security.Cryptography.TripleDES + { + public override int BlockSize { get => throw null; set => throw null; } + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateDecryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor() => throw null; + public override System.Security.Cryptography.ICryptoTransform CreateEncryptor(System.Byte[] rgbKey, System.Byte[] rgbIV) => throw null; + protected override void Dispose(bool disposing) => throw null; + public override int FeedbackSize { get => throw null; set => throw null; } + public override void GenerateIV() => throw null; + public override void GenerateKey() => throw null; + public override System.Byte[] IV { get => throw null; set => throw null; } + public override System.Byte[] Key { get => throw null; set => throw null; } + public override int KeySize { get => throw null; set => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalBlockSizes { get => throw null; } + public override System.Security.Cryptography.KeySizes[] LegalKeySizes { get => throw null; } + public override System.Security.Cryptography.CipherMode Mode { get => throw null; set => throw null; } + public override System.Security.Cryptography.PaddingMode Padding { get => throw null; set => throw null; } + public TripleDESCryptoServiceProvider() => throw null; + } + + namespace X509Certificates + { + public class CertificateRequest + { + public System.Collections.ObjectModel.Collection CertificateExtensions { get => throw null; } + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.X509Certificates.PublicKey publicKey, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding rsaSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding)) => throw null; + public CertificateRequest(System.Security.Cryptography.X509Certificates.X500DistinguishedName subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public CertificateRequest(string subjectName, System.Security.Cryptography.ECDsa key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public CertificateRequest(string subjectName, System.Security.Cryptography.RSA key, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding padding) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.Byte[] serialNumber) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.Byte[] serialNumber) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 Create(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.DateTimeOffset notBefore, System.DateTimeOffset notAfter, System.ReadOnlySpan serialNumber) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 CreateSelfSigned(System.DateTimeOffset notBefore, System.DateTimeOffset notAfter) => throw null; + public System.Byte[] CreateSigningRequest() => throw null; + public System.Byte[] CreateSigningRequest(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) => throw null; + public string CreateSigningRequestPem() => throw null; + public string CreateSigningRequestPem(System.Security.Cryptography.X509Certificates.X509SignatureGenerator signatureGenerator) => throw null; + public System.Security.Cryptography.HashAlgorithmName HashAlgorithm { get => throw null; } + public static System.Security.Cryptography.X509Certificates.CertificateRequest LoadSigningRequest(System.Byte[] pkcs10, System.Security.Cryptography.HashAlgorithmName signerHashAlgorithm, System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions options = default(System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions), System.Security.Cryptography.RSASignaturePadding signerSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding)) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRequest LoadSigningRequest(System.ReadOnlySpan pkcs10, System.Security.Cryptography.HashAlgorithmName signerHashAlgorithm, out int bytesConsumed, System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions options = default(System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions), System.Security.Cryptography.RSASignaturePadding signerSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding)) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRequest LoadSigningRequestPem(System.ReadOnlySpan pkcs10Pem, System.Security.Cryptography.HashAlgorithmName signerHashAlgorithm, System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions options = default(System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions), System.Security.Cryptography.RSASignaturePadding signerSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding)) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRequest LoadSigningRequestPem(string pkcs10Pem, System.Security.Cryptography.HashAlgorithmName signerHashAlgorithm, System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions options = default(System.Security.Cryptography.X509Certificates.CertificateRequestLoadOptions), System.Security.Cryptography.RSASignaturePadding signerSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding)) => throw null; + public System.Collections.ObjectModel.Collection OtherRequestAttributes { get => throw null; } + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get => throw null; } + } + + [System.Flags] + public enum CertificateRequestLoadOptions : int + { + Default = 0, + SkipSignatureValidation = 1, + UnsafeLoadCertificateExtensions = 2, + } + + public class CertificateRevocationListBuilder + { + public void AddEntry(System.Byte[] serialNumber, System.DateTimeOffset? revocationTime = default(System.DateTimeOffset?), System.Security.Cryptography.X509Certificates.X509RevocationReason? reason = default(System.Security.Cryptography.X509Certificates.X509RevocationReason?)) => throw null; + public void AddEntry(System.ReadOnlySpan serialNumber, System.DateTimeOffset? revocationTime = default(System.DateTimeOffset?), System.Security.Cryptography.X509Certificates.X509RevocationReason? reason = default(System.Security.Cryptography.X509Certificates.X509RevocationReason?)) => throw null; + public void AddEntry(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.DateTimeOffset? revocationTime = default(System.DateTimeOffset?), System.Security.Cryptography.X509Certificates.X509RevocationReason? reason = default(System.Security.Cryptography.X509Certificates.X509RevocationReason?)) => throw null; + public System.Byte[] Build(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Security.Cryptography.X509Certificates.X509SignatureGenerator generator, System.Numerics.BigInteger crlNumber, System.DateTimeOffset nextUpdate, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension authorityKeyIdentifier, System.DateTimeOffset? thisUpdate = default(System.DateTimeOffset?)) => throw null; + public System.Byte[] Build(System.Security.Cryptography.X509Certificates.X509Certificate2 issuerCertificate, System.Numerics.BigInteger crlNumber, System.DateTimeOffset nextUpdate, System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Security.Cryptography.RSASignaturePadding rsaSignaturePadding = default(System.Security.Cryptography.RSASignaturePadding), System.DateTimeOffset? thisUpdate = default(System.DateTimeOffset?)) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Extension BuildCrlDistributionPointExtension(System.Collections.Generic.IEnumerable uris, bool critical = default(bool)) => throw null; + public CertificateRevocationListBuilder() => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRevocationListBuilder Load(System.Byte[] currentCrl, out System.Numerics.BigInteger currentCrlNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRevocationListBuilder Load(System.ReadOnlySpan currentCrl, out System.Numerics.BigInteger currentCrlNumber, out int bytesConsumed) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRevocationListBuilder LoadPem(System.ReadOnlySpan currentCrl, out System.Numerics.BigInteger currentCrlNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.CertificateRevocationListBuilder LoadPem(string currentCrl, out System.Numerics.BigInteger currentCrlNumber) => throw null; + public bool RemoveEntry(System.Byte[] serialNumber) => throw null; + public bool RemoveEntry(System.ReadOnlySpan serialNumber) => throw null; + } + + public static class DSACertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.DSA privateKey) => throw null; + public static System.Security.Cryptography.DSA GetDSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public static System.Security.Cryptography.DSA GetDSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + } + + public static class ECDsaCertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.ECDsa privateKey) => throw null; + public static System.Security.Cryptography.ECDsa GetECDsaPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public static System.Security.Cryptography.ECDsa GetECDsaPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + } + + [System.Flags] + public enum OpenFlags : int + { + IncludeArchived = 8, + MaxAllowed = 2, + OpenExistingOnly = 4, + ReadOnly = 0, + ReadWrite = 1, + } + + public class PublicKey + { + public static System.Security.Cryptography.X509Certificates.PublicKey CreateFromSubjectPublicKeyInfo(System.ReadOnlySpan source, out int bytesRead) => throw null; + public System.Security.Cryptography.AsnEncodedData EncodedKeyValue { get => throw null; } + public System.Security.Cryptography.AsnEncodedData EncodedParameters { get => throw null; } + public System.Byte[] ExportSubjectPublicKeyInfo() => throw null; + public System.Security.Cryptography.DSA GetDSAPublicKey() => throw null; + public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPublicKey() => throw null; + public System.Security.Cryptography.ECDsa GetECDsaPublicKey() => throw null; + public System.Security.Cryptography.RSA GetRSAPublicKey() => throw null; + public System.Security.Cryptography.AsymmetricAlgorithm Key { get => throw null; } + public System.Security.Cryptography.Oid Oid { get => throw null; } + public PublicKey(System.Security.Cryptography.AsymmetricAlgorithm key) => throw null; + public PublicKey(System.Security.Cryptography.Oid oid, System.Security.Cryptography.AsnEncodedData parameters, System.Security.Cryptography.AsnEncodedData keyValue) => throw null; + public bool TryExportSubjectPublicKeyInfo(System.Span destination, out int bytesWritten) => throw null; + } + + public static class RSACertificateExtensions + { + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, System.Security.Cryptography.RSA privateKey) => throw null; + public static System.Security.Cryptography.RSA GetRSAPrivateKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public static System.Security.Cryptography.RSA GetRSAPublicKey(this System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + } + + public enum StoreLocation : int + { + CurrentUser = 1, + LocalMachine = 2, + } + + public enum StoreName : int + { + AddressBook = 1, + AuthRoot = 2, + CertificateAuthority = 3, + Disallowed = 4, + My = 5, + Root = 6, + TrustedPeople = 7, + TrustedPublisher = 8, + } + + public class SubjectAlternativeNameBuilder + { + public void AddDnsName(string dnsName) => throw null; + public void AddEmailAddress(string emailAddress) => throw null; + public void AddIpAddress(System.Net.IPAddress ipAddress) => throw null; + public void AddUri(System.Uri uri) => throw null; + public void AddUserPrincipalName(string upn) => throw null; + public System.Security.Cryptography.X509Certificates.X509Extension Build(bool critical = default(bool)) => throw null; + public SubjectAlternativeNameBuilder() => throw null; + } + + public class X500DistinguishedName : System.Security.Cryptography.AsnEncodedData + { + public string Decode(System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) => throw null; + public System.Collections.Generic.IEnumerable EnumerateRelativeDistinguishedNames(bool reversed = default(bool)) => throw null; + public override string Format(bool multiLine) => throw null; + public string Name { get => throw null; } + public X500DistinguishedName(System.Security.Cryptography.AsnEncodedData encodedDistinguishedName) => throw null; + public X500DistinguishedName(System.Byte[] encodedDistinguishedName) => throw null; + public X500DistinguishedName(System.ReadOnlySpan encodedDistinguishedName) => throw null; + public X500DistinguishedName(System.Security.Cryptography.X509Certificates.X500DistinguishedName distinguishedName) => throw null; + public X500DistinguishedName(string distinguishedName) => throw null; + public X500DistinguishedName(string distinguishedName, System.Security.Cryptography.X509Certificates.X500DistinguishedNameFlags flag) => throw null; + } + + public class X500DistinguishedNameBuilder + { + public void Add(System.Security.Cryptography.Oid oid, string value, System.Formats.Asn1.UniversalTagNumber? stringEncodingType = default(System.Formats.Asn1.UniversalTagNumber?)) => throw null; + public void Add(string oidValue, string value, System.Formats.Asn1.UniversalTagNumber? stringEncodingType = default(System.Formats.Asn1.UniversalTagNumber?)) => throw null; + public void AddCommonName(string commonName) => throw null; + public void AddCountryOrRegion(string twoLetterCode) => throw null; + public void AddDomainComponent(string domainComponent) => throw null; + public void AddEmailAddress(string emailAddress) => throw null; + public void AddLocalityName(string localityName) => throw null; + public void AddOrganizationName(string organizationName) => throw null; + public void AddOrganizationalUnitName(string organizationalUnitName) => throw null; + public void AddStateOrProvinceName(string stateOrProvinceName) => throw null; + public System.Security.Cryptography.X509Certificates.X500DistinguishedName Build() => throw null; + public X500DistinguishedNameBuilder() => throw null; + } + + [System.Flags] + public enum X500DistinguishedNameFlags : int + { + DoNotUsePlusSign = 32, + DoNotUseQuotes = 64, + ForceUTF8Encoding = 16384, + None = 0, + Reversed = 1, + UseCommas = 128, + UseNewLines = 256, + UseSemicolons = 16, + UseT61Encoding = 8192, + UseUTF8Encoding = 4096, + } + + public class X500RelativeDistinguishedName + { + public System.Security.Cryptography.Oid GetSingleElementType() => throw null; + public string GetSingleElementValue() => throw null; + public bool HasMultipleElements { get => throw null; } + public System.ReadOnlyMemory RawData { get => throw null; } + } + + public class X509AuthorityInformationAccessExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public System.Collections.Generic.IEnumerable EnumerateCAIssuersUris() => throw null; + public System.Collections.Generic.IEnumerable EnumerateOcspUris() => throw null; + public System.Collections.Generic.IEnumerable EnumerateUris(System.Security.Cryptography.Oid accessMethodOid) => throw null; + public System.Collections.Generic.IEnumerable EnumerateUris(string accessMethodOid) => throw null; + public X509AuthorityInformationAccessExtension() => throw null; + public X509AuthorityInformationAccessExtension(System.Byte[] rawData, bool critical = default(bool)) => throw null; + public X509AuthorityInformationAccessExtension(System.Collections.Generic.IEnumerable ocspUris, System.Collections.Generic.IEnumerable caIssuersUris, bool critical = default(bool)) => throw null; + public X509AuthorityInformationAccessExtension(System.ReadOnlySpan rawData, bool critical = default(bool)) => throw null; + } + + public class X509AuthorityKeyIdentifierExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension Create(System.Byte[] keyIdentifier, System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Byte[] serialNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension Create(System.ReadOnlySpan keyIdentifier, System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.ReadOnlySpan serialNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromCertificate(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate, bool includeKeyIdentifier, bool includeIssuerAndSerial) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromIssuerNameAndSerialNumber(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.Byte[] serialNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromIssuerNameAndSerialNumber(System.Security.Cryptography.X509Certificates.X500DistinguishedName issuerName, System.ReadOnlySpan serialNumber) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromSubjectKeyIdentifier(System.Byte[] subjectKeyIdentifier) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromSubjectKeyIdentifier(System.ReadOnlySpan subjectKeyIdentifier) => throw null; + public static System.Security.Cryptography.X509Certificates.X509AuthorityKeyIdentifierExtension CreateFromSubjectKeyIdentifier(System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierExtension subjectKeyIdentifier) => throw null; + public System.ReadOnlyMemory? KeyIdentifier { get => throw null; } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName NamedIssuer { get => throw null; } + public System.ReadOnlyMemory? RawIssuer { get => throw null; } + public System.ReadOnlyMemory? SerialNumber { get => throw null; } + public X509AuthorityKeyIdentifierExtension() => throw null; + public X509AuthorityKeyIdentifierExtension(System.Byte[] rawData, bool critical = default(bool)) => throw null; + public X509AuthorityKeyIdentifierExtension(System.ReadOnlySpan rawData, bool critical = default(bool)) => throw null; + } + + public class X509BasicConstraintsExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public bool CertificateAuthority { get => throw null; } + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public static System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension CreateForCertificateAuthority(int? pathLengthConstraint = default(int?)) => throw null; + public static System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension CreateForEndEntity(bool critical = default(bool)) => throw null; + public bool HasPathLengthConstraint { get => throw null; } + public int PathLengthConstraint { get => throw null; } + public X509BasicConstraintsExtension() => throw null; + public X509BasicConstraintsExtension(System.Security.Cryptography.AsnEncodedData encodedBasicConstraints, bool critical) => throw null; + public X509BasicConstraintsExtension(bool certificateAuthority, bool hasPathLengthConstraint, int pathLengthConstraint, bool critical) => throw null; + } + + public class X509Certificate : System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable + { + public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromCertFile(string filename) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate CreateFromSignedFile(string filename) => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public virtual bool Equals(System.Security.Cryptography.X509Certificates.X509Certificate other) => throw null; + public override bool Equals(object obj) => throw null; + public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) => throw null; + public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, System.Security.SecureString password) => throw null; + public virtual System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string password) => throw null; + protected static string FormatDate(System.DateTime date) => throw null; + public virtual System.Byte[] GetCertHash() => throw null; + public virtual System.Byte[] GetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public virtual string GetCertHashString() => throw null; + public virtual string GetCertHashString(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) => throw null; + public virtual string GetEffectiveDateString() => throw null; + public virtual string GetExpirationDateString() => throw null; + public virtual string GetFormat() => throw null; + public override int GetHashCode() => throw null; + public virtual string GetIssuerName() => throw null; + public virtual string GetKeyAlgorithm() => throw null; + public virtual System.Byte[] GetKeyAlgorithmParameters() => throw null; + public virtual string GetKeyAlgorithmParametersString() => throw null; + public virtual string GetName() => throw null; + void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public virtual System.Byte[] GetPublicKey() => throw null; + public virtual string GetPublicKeyString() => throw null; + public virtual System.Byte[] GetRawCertData() => throw null; + public virtual string GetRawCertDataString() => throw null; + public virtual System.Byte[] GetSerialNumber() => throw null; + public virtual string GetSerialNumberString() => throw null; + public System.IntPtr Handle { get => throw null; } + public virtual void Import(System.Byte[] rawData) => throw null; + public virtual void Import(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public virtual void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public virtual void Import(string fileName) => throw null; + public virtual void Import(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public virtual void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public string Issuer { get => throw null; } + void System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(object sender) => throw null; + public virtual void Reset() => throw null; + public System.ReadOnlyMemory SerialNumberBytes { get => throw null; } + public string Subject { get => throw null; } + public override string ToString() => throw null; + public virtual string ToString(bool fVerbose) => throw null; + public virtual bool TryGetCertHash(System.Security.Cryptography.HashAlgorithmName hashAlgorithm, System.Span destination, out int bytesWritten) => throw null; + public X509Certificate() => throw null; + public X509Certificate(System.Byte[] data) => throw null; + public X509Certificate(System.Byte[] rawData, System.Security.SecureString password) => throw null; + public X509Certificate(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate(System.Byte[] rawData, string password) => throw null; + public X509Certificate(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate(System.IntPtr handle) => throw null; + public X509Certificate(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public X509Certificate(System.Security.Cryptography.X509Certificates.X509Certificate cert) => throw null; + public X509Certificate(string fileName) => throw null; + public X509Certificate(string fileName, System.Security.SecureString password) => throw null; + public X509Certificate(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate(string fileName, string password) => throw null; + public X509Certificate(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + } + + public class X509Certificate2 : System.Security.Cryptography.X509Certificates.X509Certificate + { + public bool Archived { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2 CopyWithPrivateKey(System.Security.Cryptography.ECDiffieHellman privateKey) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem, System.ReadOnlySpan password) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromEncryptedPemFile(string certPemFilePath, System.ReadOnlySpan password, string keyPemFilePath = default(string)) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPem(System.ReadOnlySpan certPem, System.ReadOnlySpan keyPem) => throw null; + public static System.Security.Cryptography.X509Certificates.X509Certificate2 CreateFromPemFile(string certPemFilePath, string keyPemFilePath = default(string)) => throw null; + public string ExportCertificatePem() => throw null; + public System.Security.Cryptography.X509Certificates.X509ExtensionCollection Extensions { get => throw null; } + public string FriendlyName { get => throw null; set => throw null; } + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.Byte[] rawData) => throw null; + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(System.ReadOnlySpan rawData) => throw null; + public static System.Security.Cryptography.X509Certificates.X509ContentType GetCertContentType(string fileName) => throw null; + public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPrivateKey() => throw null; + public System.Security.Cryptography.ECDiffieHellman GetECDiffieHellmanPublicKey() => throw null; + public string GetNameInfo(System.Security.Cryptography.X509Certificates.X509NameType nameType, bool forIssuer) => throw null; + public bool HasPrivateKey { get => throw null; } + public override void Import(System.Byte[] rawData) => throw null; + public override void Import(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public override void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public override void Import(string fileName) => throw null; + public override void Import(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public override void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public System.Security.Cryptography.X509Certificates.X500DistinguishedName IssuerName { get => throw null; } + public bool MatchesHostname(string hostname, bool allowWildcards = default(bool), bool allowCommonName = default(bool)) => throw null; + public System.DateTime NotAfter { get => throw null; } + public System.DateTime NotBefore { get => throw null; } + public System.Security.Cryptography.AsymmetricAlgorithm PrivateKey { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } + public System.Byte[] RawData { get => throw null; } + public System.ReadOnlyMemory RawDataMemory { get => throw null; } + public override void Reset() => throw null; + public string SerialNumber { get => throw null; } + public System.Security.Cryptography.Oid SignatureAlgorithm { get => throw null; } + public System.Security.Cryptography.X509Certificates.X500DistinguishedName SubjectName { get => throw null; } + public string Thumbprint { get => throw null; } + public override string ToString() => throw null; + public override string ToString(bool verbose) => throw null; + public bool TryExportCertificatePem(System.Span destination, out int charsWritten) => throw null; + public bool Verify() => throw null; + public int Version { get => throw null; } + public X509Certificate2() => throw null; + public X509Certificate2(System.Byte[] rawData) => throw null; + public X509Certificate2(System.Byte[] rawData, System.Security.SecureString password) => throw null; + public X509Certificate2(System.Byte[] rawData, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate2(System.Byte[] rawData, string password) => throw null; + public X509Certificate2(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate2(System.IntPtr handle) => throw null; + public X509Certificate2(System.ReadOnlySpan rawData) => throw null; + public X509Certificate2(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + protected X509Certificate2(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; + public X509Certificate2(System.Security.Cryptography.X509Certificates.X509Certificate certificate) => throw null; + public X509Certificate2(string fileName) => throw null; + public X509Certificate2(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public X509Certificate2(string fileName, System.Security.SecureString password) => throw null; + public X509Certificate2(string fileName, System.Security.SecureString password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + public X509Certificate2(string fileName, string password) => throw null; + public X509Certificate2(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags) => throw null; + } + + public class X509Certificate2Collection : System.Security.Cryptography.X509Certificates.X509CertificateCollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable + { + public int Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; + public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType) => throw null; + public System.Byte[] Export(System.Security.Cryptography.X509Certificates.X509ContentType contentType, string password) => throw null; + public string ExportCertificatePems() => throw null; + public string ExportPkcs7Pem() => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Find(System.Security.Cryptography.X509Certificates.X509FindType findType, object findValue, bool validOnly) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2Enumerator GetEnumerator() => throw null; + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + public void Import(System.Byte[] rawData) => throw null; + public void Import(System.Byte[] rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public void Import(System.ReadOnlySpan rawData) => throw null; + public void Import(System.ReadOnlySpan rawData, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public void Import(System.ReadOnlySpan rawData, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public void Import(string fileName) => throw null; + public void Import(string fileName, System.ReadOnlySpan password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public void Import(string fileName, string password, System.Security.Cryptography.X509Certificates.X509KeyStorageFlags keyStorageFlags = default(System.Security.Cryptography.X509Certificates.X509KeyStorageFlags)) => throw null; + public void ImportFromPem(System.ReadOnlySpan certPem) => throw null; + public void ImportFromPemFile(string certPemFilePath) => throw null; + public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2 this[int index] { get => throw null; set => throw null; } + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; + public bool TryExportCertificatePems(System.Span destination, out int charsWritten) => throw null; + public bool TryExportPkcs7Pem(System.Span destination, out int charsWritten) => throw null; + public X509Certificate2Collection() => throw null; + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; + public X509Certificate2Collection(System.Security.Cryptography.X509Certificates.X509Certificate2[] certificates) => throw null; + } + + public class X509Certificate2Enumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + public System.Security.Cryptography.X509Certificates.X509Certificate2 Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + void System.IDisposable.Dispose() => throw null; + public bool MoveNext() => throw null; + bool System.Collections.IEnumerator.MoveNext() => throw null; + public void Reset() => throw null; + void System.Collections.IEnumerator.Reset() => throw null; + } + + public class X509CertificateCollection : System.Collections.CollectionBase + { + public class X509CertificateEnumerator : System.Collections.IEnumerator + { + public System.Security.Cryptography.X509Certificates.X509Certificate Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + public bool MoveNext() => throw null; + bool System.Collections.IEnumerator.MoveNext() => throw null; + public void Reset() => throw null; + void System.Collections.IEnumerator.Reset() => throw null; + public X509CertificateEnumerator(System.Security.Cryptography.X509Certificates.X509CertificateCollection mappings) => throw null; + } + + + public int Add(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; + public void AddRange(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) => throw null; + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate[] value) => throw null; + public bool Contains(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; + public void CopyTo(System.Security.Cryptography.X509Certificates.X509Certificate[] array, int index) => throw null; + public System.Security.Cryptography.X509Certificates.X509CertificateCollection.X509CertificateEnumerator GetEnumerator() => throw null; + public override int GetHashCode() => throw null; + public int IndexOf(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; + public void Insert(int index, System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate this[int index] { get => throw null; set => throw null; } + protected override void OnValidate(object value) => throw null; + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate value) => throw null; + public X509CertificateCollection() => throw null; + public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509CertificateCollection value) => throw null; + public X509CertificateCollection(System.Security.Cryptography.X509Certificates.X509Certificate[] value) => throw null; + } + + public class X509Chain : System.IDisposable + { + public bool Build(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public System.IntPtr ChainContext { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainElementCollection ChainElements { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainPolicy ChainPolicy { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainStatus { get => throw null; } + public static System.Security.Cryptography.X509Certificates.X509Chain Create() => throw null; + public void Dispose() => throw null; + protected virtual void Dispose(bool disposing) => throw null; + public void Reset() => throw null; + public Microsoft.Win32.SafeHandles.SafeX509ChainHandle SafeHandle { get => throw null; } + public X509Chain() => throw null; + public X509Chain(System.IntPtr chainContext) => throw null; + public X509Chain(bool useMachineContext) => throw null; + } + + public class X509ChainElement + { + public System.Security.Cryptography.X509Certificates.X509Certificate2 Certificate { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainStatus[] ChainElementStatus { get => throw null; } + public string Information { get => throw null; } + } + + public class X509ChainElementCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable + { + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(System.Security.Cryptography.X509Certificates.X509ChainElement[] array, int index) => throw null; + public int Count { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainElementEnumerator GetEnumerator() => throw null; + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public bool IsSynchronized { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainElement this[int index] { get => throw null; } + public object SyncRoot { get => throw null; } + } + + public class X509ChainElementEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + public System.Security.Cryptography.X509Certificates.X509ChainElement Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + void System.IDisposable.Dispose() => throw null; + public bool MoveNext() => throw null; + public void Reset() => throw null; + } + + public class X509ChainPolicy + { + public System.Security.Cryptography.OidCollection ApplicationPolicy { get => throw null; } + public System.Security.Cryptography.OidCollection CertificatePolicy { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainPolicy Clone() => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection CustomTrustStore { get => throw null; } + public bool DisableCertificateDownloads { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection ExtraStore { get => throw null; } + public void Reset() => throw null; + public System.Security.Cryptography.X509Certificates.X509RevocationFlag RevocationFlag { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509RevocationMode RevocationMode { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509ChainTrustMode TrustMode { get => throw null; set => throw null; } + public System.TimeSpan UrlRetrievalTimeout { get => throw null; set => throw null; } + public System.Security.Cryptography.X509Certificates.X509VerificationFlags VerificationFlags { get => throw null; set => throw null; } + public System.DateTime VerificationTime { get => throw null; set => throw null; } + public bool VerificationTimeIgnored { get => throw null; set => throw null; } + public X509ChainPolicy() => throw null; + } + + public struct X509ChainStatus + { + public System.Security.Cryptography.X509Certificates.X509ChainStatusFlags Status { get => throw null; set => throw null; } + public string StatusInformation { get => throw null; set => throw null; } + // Stub generator skipped constructor + } + + [System.Flags] + public enum X509ChainStatusFlags : int + { + CtlNotSignatureValid = 262144, + CtlNotTimeValid = 131072, + CtlNotValidForUsage = 524288, + Cyclic = 128, + ExplicitDistrust = 67108864, + HasExcludedNameConstraint = 32768, + HasNotDefinedNameConstraint = 8192, + HasNotPermittedNameConstraint = 16384, + HasNotSupportedCriticalExtension = 134217728, + HasNotSupportedNameConstraint = 4096, + HasWeakSignature = 1048576, + InvalidBasicConstraints = 1024, + InvalidExtension = 256, + InvalidNameConstraints = 2048, + InvalidPolicyConstraints = 512, + NoError = 0, + NoIssuanceChainPolicy = 33554432, + NotSignatureValid = 8, + NotTimeNested = 2, + NotTimeValid = 1, + NotValidForUsage = 16, + OfflineRevocation = 16777216, + PartialChain = 65536, + RevocationStatusUnknown = 64, + Revoked = 4, + UntrustedRoot = 32, + } + + public enum X509ChainTrustMode : int + { + CustomRootTrust = 1, + System = 0, + } + + public enum X509ContentType : int + { + Authenticode = 6, + Cert = 1, + Pfx = 3, + Pkcs12 = 3, + Pkcs7 = 5, + SerializedCert = 2, + SerializedStore = 4, + Unknown = 0, + } + + public class X509EnhancedKeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public System.Security.Cryptography.OidCollection EnhancedKeyUsages { get => throw null; } + public X509EnhancedKeyUsageExtension() => throw null; + public X509EnhancedKeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedEnhancedKeyUsages, bool critical) => throw null; + public X509EnhancedKeyUsageExtension(System.Security.Cryptography.OidCollection enhancedKeyUsages, bool critical) => throw null; + } + + public class X509Extension : System.Security.Cryptography.AsnEncodedData + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public bool Critical { get => throw null; set => throw null; } + protected X509Extension() => throw null; + public X509Extension(System.Security.Cryptography.AsnEncodedData encodedExtension, bool critical) => throw null; + public X509Extension(System.Security.Cryptography.Oid oid, System.Byte[] rawData, bool critical) => throw null; + public X509Extension(System.Security.Cryptography.Oid oid, System.ReadOnlySpan rawData, bool critical) => throw null; + public X509Extension(string oid, System.Byte[] rawData, bool critical) => throw null; + public X509Extension(string oid, System.ReadOnlySpan rawData, bool critical) => throw null; + } + + public class X509ExtensionCollection : System.Collections.Generic.IEnumerable, System.Collections.ICollection, System.Collections.IEnumerable + { + public int Add(System.Security.Cryptography.X509Certificates.X509Extension extension) => throw null; + void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null; + public void CopyTo(System.Security.Cryptography.X509Certificates.X509Extension[] array, int index) => throw null; + public int Count { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509ExtensionEnumerator GetEnumerator() => throw null; + System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator() => throw null; + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null; + public bool IsSynchronized { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509Extension this[int index] { get => throw null; } + public System.Security.Cryptography.X509Certificates.X509Extension this[string oid] { get => throw null; } + public object SyncRoot { get => throw null; } + public X509ExtensionCollection() => throw null; + } + + public class X509ExtensionEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable + { + public System.Security.Cryptography.X509Certificates.X509Extension Current { get => throw null; } + object System.Collections.IEnumerator.Current { get => throw null; } + void System.IDisposable.Dispose() => throw null; + public bool MoveNext() => throw null; + public void Reset() => throw null; + } + + public enum X509FindType : int + { + FindByApplicationPolicy = 10, + FindByCertificatePolicy = 11, + FindByExtension = 12, + FindByIssuerDistinguishedName = 4, + FindByIssuerName = 3, + FindByKeyUsage = 13, + FindBySerialNumber = 5, + FindBySubjectDistinguishedName = 2, + FindBySubjectKeyIdentifier = 14, + FindBySubjectName = 1, + FindByTemplateName = 9, + FindByThumbprint = 0, + FindByTimeExpired = 8, + FindByTimeNotYetValid = 7, + FindByTimeValid = 6, + } + + public enum X509IncludeOption : int + { + EndCertOnly = 2, + ExcludeRoot = 1, + None = 0, + WholeChain = 3, + } + + [System.Flags] + public enum X509KeyStorageFlags : int + { + DefaultKeySet = 0, + EphemeralKeySet = 32, + Exportable = 4, + MachineKeySet = 2, + PersistKeySet = 16, + UserKeySet = 1, + UserProtected = 8, + } + + public class X509KeyUsageExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public System.Security.Cryptography.X509Certificates.X509KeyUsageFlags KeyUsages { get => throw null; } + public X509KeyUsageExtension() => throw null; + public X509KeyUsageExtension(System.Security.Cryptography.AsnEncodedData encodedKeyUsage, bool critical) => throw null; + public X509KeyUsageExtension(System.Security.Cryptography.X509Certificates.X509KeyUsageFlags keyUsages, bool critical) => throw null; + } + + [System.Flags] + public enum X509KeyUsageFlags : int + { + CrlSign = 2, + DataEncipherment = 16, + DecipherOnly = 32768, + DigitalSignature = 128, + EncipherOnly = 1, + KeyAgreement = 8, + KeyCertSign = 4, + KeyEncipherment = 32, + NonRepudiation = 64, + None = 0, + } + + public enum X509NameType : int + { + DnsFromAlternativeName = 4, + DnsName = 3, + EmailName = 1, + SimpleName = 0, + UpnName = 2, + UrlName = 5, + } + + public enum X509RevocationFlag : int + { + EndCertificateOnly = 0, + EntireChain = 1, + ExcludeRoot = 2, + } + + public enum X509RevocationMode : int + { + NoCheck = 0, + Offline = 2, + Online = 1, + } + + public enum X509RevocationReason : int + { + AACompromise = 10, + AffiliationChanged = 3, + CACompromise = 2, + CertificateHold = 6, + CessationOfOperation = 5, + KeyCompromise = 1, + PrivilegeWithdrawn = 9, + RemoveFromCrl = 8, + Superseded = 4, + Unspecified = 0, + WeakAlgorithmOrKey = 11, + } + + public abstract class X509SignatureGenerator + { + protected abstract System.Security.Cryptography.X509Certificates.PublicKey BuildPublicKey(); + public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForECDsa(System.Security.Cryptography.ECDsa key) => throw null; + public static System.Security.Cryptography.X509Certificates.X509SignatureGenerator CreateForRSA(System.Security.Cryptography.RSA key, System.Security.Cryptography.RSASignaturePadding signaturePadding) => throw null; + public abstract System.Byte[] GetSignatureAlgorithmIdentifier(System.Security.Cryptography.HashAlgorithmName hashAlgorithm); + public System.Security.Cryptography.X509Certificates.PublicKey PublicKey { get => throw null; } + public abstract System.Byte[] SignData(System.Byte[] data, System.Security.Cryptography.HashAlgorithmName hashAlgorithm); + protected X509SignatureGenerator() => throw null; + } + + public class X509Store : System.IDisposable + { + public void Add(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public void AddRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; + public System.Security.Cryptography.X509Certificates.X509Certificate2Collection Certificates { get => throw null; } + public void Close() => throw null; + public void Dispose() => throw null; + public bool IsOpen { get => throw null; } + public System.Security.Cryptography.X509Certificates.StoreLocation Location { get => throw null; } + public string Name { get => throw null; } + public void Open(System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; + public void Remove(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate) => throw null; + public void RemoveRange(System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates) => throw null; + public System.IntPtr StoreHandle { get => throw null; } + public X509Store() => throw null; + public X509Store(System.IntPtr storeHandle) => throw null; + public X509Store(System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName) => throw null; + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; + public X509Store(System.Security.Cryptography.X509Certificates.StoreName storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; + public X509Store(string storeName) => throw null; + public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation) => throw null; + public X509Store(string storeName, System.Security.Cryptography.X509Certificates.StoreLocation storeLocation, System.Security.Cryptography.X509Certificates.OpenFlags flags) => throw null; + } + + public class X509SubjectAlternativeNameExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public System.Collections.Generic.IEnumerable EnumerateDnsNames() => throw null; + public System.Collections.Generic.IEnumerable EnumerateIPAddresses() => throw null; + public X509SubjectAlternativeNameExtension() => throw null; + public X509SubjectAlternativeNameExtension(System.Byte[] rawData, bool critical = default(bool)) => throw null; + public X509SubjectAlternativeNameExtension(System.ReadOnlySpan rawData, bool critical = default(bool)) => throw null; + } + + public class X509SubjectKeyIdentifierExtension : System.Security.Cryptography.X509Certificates.X509Extension + { + public override void CopyFrom(System.Security.Cryptography.AsnEncodedData asnEncodedData) => throw null; + public string SubjectKeyIdentifier { get => throw null; } + public System.ReadOnlyMemory SubjectKeyIdentifierBytes { get => throw null; } + public X509SubjectKeyIdentifierExtension() => throw null; + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.AsnEncodedData encodedSubjectKeyIdentifier, bool critical) => throw null; + public X509SubjectKeyIdentifierExtension(System.Byte[] subjectKeyIdentifier, bool critical) => throw null; + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, System.Security.Cryptography.X509Certificates.X509SubjectKeyIdentifierHashAlgorithm algorithm, bool critical) => throw null; + public X509SubjectKeyIdentifierExtension(System.Security.Cryptography.X509Certificates.PublicKey key, bool critical) => throw null; + public X509SubjectKeyIdentifierExtension(System.ReadOnlySpan subjectKeyIdentifier, bool critical) => throw null; + public X509SubjectKeyIdentifierExtension(string subjectKeyIdentifier, bool critical) => throw null; + } + + public enum X509SubjectKeyIdentifierHashAlgorithm : int + { + CapiSha1 = 2, + Sha1 = 0, + ShortSha1 = 1, + } + + [System.Flags] + public enum X509VerificationFlags : int + { + AllFlags = 4095, + AllowUnknownCertificateAuthority = 16, + IgnoreCertificateAuthorityRevocationUnknown = 1024, + IgnoreCtlNotTimeValid = 2, + IgnoreCtlSignerRevocationUnknown = 512, + IgnoreEndRevocationUnknown = 256, + IgnoreInvalidBasicConstraints = 8, + IgnoreInvalidName = 64, + IgnoreInvalidPolicy = 128, + IgnoreNotTimeNested = 4, + IgnoreNotTimeValid = 1, + IgnoreRootRevocationUnknown = 2048, + IgnoreWrongUsage = 32, + NoFlag = 0, + } + + } + } + } +} diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Principal.Windows.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Principal.Windows.cs index e3a98486457..2b35db3bc00 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Principal.Windows.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Security.Principal.Windows.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Security.Principal.Windows, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace Microsoft { @@ -6,7 +7,6 @@ namespace Microsoft { namespace SafeHandles { - // Generated from `Microsoft.Win32.SafeHandles.SafeAccessTokenHandle` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SafeAccessTokenHandle : System.Runtime.InteropServices.SafeHandle { public static Microsoft.Win32.SafeHandles.SafeAccessTokenHandle InvalidHandle { get => throw null; } @@ -25,7 +25,6 @@ namespace System { namespace Principal { - // Generated from `System.Security.Principal.IdentityNotMappedException` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IdentityNotMappedException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo serializationInfo, System.Runtime.Serialization.StreamingContext streamingContext) => throw null; @@ -35,7 +34,6 @@ namespace System public System.Security.Principal.IdentityReferenceCollection UnmappedIdentities { get => throw null; } } - // Generated from `System.Security.Principal.IdentityReference` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class IdentityReference { public static bool operator !=(System.Security.Principal.IdentityReference left, System.Security.Principal.IdentityReference right) => throw null; @@ -49,7 +47,6 @@ namespace System public abstract string Value { get; } } - // Generated from `System.Security.Principal.IdentityReferenceCollection` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class IdentityReferenceCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public void Add(System.Security.Principal.IdentityReference identity) => throw null; @@ -68,7 +65,6 @@ namespace System public System.Security.Principal.IdentityReferenceCollection Translate(System.Type targetType, bool forceSuccess) => throw null; } - // Generated from `System.Security.Principal.NTAccount` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NTAccount : System.Security.Principal.IdentityReference { public static bool operator !=(System.Security.Principal.NTAccount left, System.Security.Principal.NTAccount right) => throw null; @@ -83,7 +79,6 @@ namespace System public override string Value { get => throw null; } } - // Generated from `System.Security.Principal.SecurityIdentifier` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SecurityIdentifier : System.Security.Principal.IdentityReference, System.IComparable { public static bool operator !=(System.Security.Principal.SecurityIdentifier left, System.Security.Principal.SecurityIdentifier right) => throw null; @@ -110,7 +105,6 @@ namespace System public override string Value { get => throw null; } } - // Generated from `System.Security.Principal.TokenAccessLevels` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum TokenAccessLevels : int { @@ -129,7 +123,6 @@ namespace System Write = 131296, } - // Generated from `System.Security.Principal.WellKnownSidType` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WellKnownSidType : int { AccountAdministratorSid = 38, @@ -230,7 +223,6 @@ namespace System WorldSid = 1, } - // Generated from `System.Security.Principal.WindowsAccountType` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WindowsAccountType : int { Anonymous = 3, @@ -239,7 +231,6 @@ namespace System System = 2, } - // Generated from `System.Security.Principal.WindowsBuiltInRole` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WindowsBuiltInRole : int { AccountOperator = 548, @@ -253,7 +244,6 @@ namespace System User = 545, } - // Generated from `System.Security.Principal.WindowsIdentity` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WindowsIdentity : System.Security.Claims.ClaimsIdentity, System.IDisposable, System.Runtime.Serialization.IDeserializationCallback, System.Runtime.Serialization.ISerializable { public Microsoft.Win32.SafeHandles.SafeAccessTokenHandle AccessToken { get => throw null; } @@ -294,7 +284,6 @@ namespace System public WindowsIdentity(string sUserPrincipalName) => throw null; } - // Generated from `System.Security.Principal.WindowsPrincipal` in `System.Security.Principal.Windows, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WindowsPrincipal : System.Security.Claims.ClaimsPrincipal { public virtual System.Collections.Generic.IEnumerable DeviceClaims { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.CodePages.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.CodePages.cs index 7d62b664685..4ea79881dce 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.CodePages.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.CodePages.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Text.Encoding.CodePages, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Text { - // Generated from `System.Text.CodePagesEncodingProvider` in `System.Text.Encoding.CodePages, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CodePagesEncodingProvider : System.Text.EncodingProvider { public override System.Text.Encoding GetEncoding(int codepage) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.Extensions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.Extensions.cs index 310193c3e58..cf256dec475 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.Extensions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encoding.Extensions.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Text.Encoding.Extensions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Text { - // Generated from `System.Text.ASCIIEncoding` in `System.Text.Encoding.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ASCIIEncoding : System.Text.Encoding { public ASCIIEncoding() => throw null; @@ -30,7 +30,6 @@ namespace System public override bool IsSingleByte { get => throw null; } } - // Generated from `System.Text.UTF32Encoding` in `System.Text.Encoding.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UTF32Encoding : System.Text.Encoding { public override bool Equals(object value) => throw null; @@ -57,7 +56,6 @@ namespace System public UTF32Encoding(bool bigEndian, bool byteOrderMark, bool throwOnInvalidCharacters) => throw null; } - // Generated from `System.Text.UTF7Encoding` in `System.Text.Encoding.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UTF7Encoding : System.Text.Encoding { public override bool Equals(object value) => throw null; @@ -81,7 +79,6 @@ namespace System public UTF7Encoding(bool allowOptionals) => throw null; } - // Generated from `System.Text.UTF8Encoding` in `System.Text.Encoding.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UTF8Encoding : System.Text.Encoding { public override bool Equals(object value) => throw null; @@ -112,7 +109,6 @@ namespace System public UTF8Encoding(bool encoderShouldEmitUTF8Identifier, bool throwOnInvalidBytes) => throw null; } - // Generated from `System.Text.UnicodeEncoding` in `System.Text.Encoding.Extensions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnicodeEncoding : System.Text.Encoding { public const int CharSize = default; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encodings.Web.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encodings.Web.cs index 2801844f0fd..19f4b843376 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encodings.Web.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Encodings.Web.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Text.Encodings.Web, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -8,7 +9,6 @@ namespace System { namespace Web { - // Generated from `System.Text.Encodings.Web.HtmlEncoder` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class HtmlEncoder : System.Text.Encodings.Web.TextEncoder { public static System.Text.Encodings.Web.HtmlEncoder Create(System.Text.Encodings.Web.TextEncoderSettings settings) => throw null; @@ -17,7 +17,6 @@ namespace System protected HtmlEncoder() => throw null; } - // Generated from `System.Text.Encodings.Web.JavaScriptEncoder` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JavaScriptEncoder : System.Text.Encodings.Web.TextEncoder { public static System.Text.Encodings.Web.JavaScriptEncoder Create(System.Text.Encodings.Web.TextEncoderSettings settings) => throw null; @@ -27,7 +26,6 @@ namespace System public static System.Text.Encodings.Web.JavaScriptEncoder UnsafeRelaxedJsonEscaping { get => throw null; } } - // Generated from `System.Text.Encodings.Web.TextEncoder` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class TextEncoder { public virtual System.Buffers.OperationStatus Encode(System.ReadOnlySpan source, System.Span destination, out int charsConsumed, out int charsWritten, bool isFinalBlock = default(bool)) => throw null; @@ -44,7 +42,6 @@ namespace System public abstract bool WillEncode(int unicodeScalar); } - // Generated from `System.Text.Encodings.Web.TextEncoderSettings` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TextEncoderSettings { public virtual void AllowCharacter(System.Char character) => throw null; @@ -63,7 +60,6 @@ namespace System public TextEncoderSettings(params System.Text.Unicode.UnicodeRange[] allowedRanges) => throw null; } - // Generated from `System.Text.Encodings.Web.UrlEncoder` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class UrlEncoder : System.Text.Encodings.Web.TextEncoder { public static System.Text.Encodings.Web.UrlEncoder Create(System.Text.Encodings.Web.TextEncoderSettings settings) => throw null; @@ -76,7 +72,6 @@ namespace System } namespace Unicode { - // Generated from `System.Text.Unicode.UnicodeRange` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UnicodeRange { public static System.Text.Unicode.UnicodeRange Create(System.Char firstCharacter, System.Char lastCharacter) => throw null; @@ -85,13 +80,13 @@ namespace System public UnicodeRange(int firstCodePoint, int length) => throw null; } - // Generated from `System.Text.Unicode.UnicodeRanges` in `System.Text.Encodings.Web, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class UnicodeRanges { public static System.Text.Unicode.UnicodeRange All { get => throw null; } public static System.Text.Unicode.UnicodeRange AlphabeticPresentationForms { get => throw null; } public static System.Text.Unicode.UnicodeRange Arabic { get => throw null; } public static System.Text.Unicode.UnicodeRange ArabicExtendedA { get => throw null; } + public static System.Text.Unicode.UnicodeRange ArabicExtendedB { get => throw null; } public static System.Text.Unicode.UnicodeRange ArabicPresentationFormsA { get => throw null; } public static System.Text.Unicode.UnicodeRange ArabicPresentationFormsB { get => throw null; } public static System.Text.Unicode.UnicodeRange ArabicSupplement { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Json.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Json.cs index a54b0b4c83e..7c5954e05ca 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Json.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.Json.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Text.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Json { - // Generated from `System.Text.Json.JsonCommentHandling` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonCommentHandling : byte { Allow = 2, @@ -14,7 +14,6 @@ namespace System Skip = 1, } - // Generated from `System.Text.Json.JsonDocument` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonDocument : System.IDisposable { public void Dispose() => throw null; @@ -30,7 +29,6 @@ namespace System public void WriteTo(System.Text.Json.Utf8JsonWriter writer) => throw null; } - // Generated from `System.Text.Json.JsonDocumentOptions` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonDocumentOptions { public bool AllowTrailingCommas { get => throw null; set => throw null; } @@ -39,10 +37,8 @@ namespace System public int MaxDepth { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.JsonElement` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonElement { - // Generated from `System.Text.Json.JsonElement+ArrayEnumerator` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ArrayEnumerator : System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerator, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable { // Stub generator skipped constructor @@ -57,7 +53,6 @@ namespace System } - // Generated from `System.Text.Json.JsonElement+ObjectEnumerator` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct ObjectEnumerator : System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerator, System.Collections.IEnumerable, System.Collections.IEnumerator, System.IDisposable { public System.Text.Json.JsonProperty Current { get => throw null; } @@ -127,7 +122,6 @@ namespace System public void WriteTo(System.Text.Json.Utf8JsonWriter writer) => throw null; } - // Generated from `System.Text.Json.JsonEncodedText` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonEncodedText : System.IEquatable { public static System.Text.Json.JsonEncodedText Encode(System.ReadOnlySpan utf8Value, System.Text.Encodings.Web.JavaScriptEncoder encoder = default(System.Text.Encodings.Web.JavaScriptEncoder)) => throw null; @@ -141,7 +135,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Text.Json.JsonException` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonException : System.Exception { public System.Int64? BytePositionInLine { get => throw null; } @@ -157,7 +150,6 @@ namespace System public string Path { get => throw null; } } - // Generated from `System.Text.Json.JsonNamingPolicy` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonNamingPolicy { public static System.Text.Json.JsonNamingPolicy CamelCase { get => throw null; } @@ -165,7 +157,6 @@ namespace System protected JsonNamingPolicy() => throw null; } - // Generated from `System.Text.Json.JsonProperty` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonProperty { // Stub generator skipped constructor @@ -178,7 +169,6 @@ namespace System public void WriteTo(System.Text.Json.Utf8JsonWriter writer) => throw null; } - // Generated from `System.Text.Json.JsonReaderOptions` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonReaderOptions { public bool AllowTrailingCommas { get => throw null; set => throw null; } @@ -187,7 +177,6 @@ namespace System public int MaxDepth { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.JsonReaderState` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonReaderState { // Stub generator skipped constructor @@ -195,7 +184,6 @@ namespace System public System.Text.Json.JsonReaderOptions Options { get => throw null; } } - // Generated from `System.Text.Json.JsonSerializer` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class JsonSerializer { public static object Deserialize(this System.Text.Json.JsonDocument document, System.Type returnType, System.Text.Json.Serialization.JsonSerializerContext context) => throw null; @@ -235,6 +223,7 @@ namespace System public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static System.Collections.Generic.IAsyncEnumerable DeserializeAsyncEnumerable(System.IO.Stream utf8Json, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions), System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; + public static System.Collections.Generic.IAsyncEnumerable DeserializeAsyncEnumerable(System.IO.Stream utf8Json, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; public static void Serialize(System.IO.Stream utf8Json, object value, System.Type inputType, System.Text.Json.Serialization.JsonSerializerContext context) => throw null; public static void Serialize(System.IO.Stream utf8Json, object value, System.Type inputType, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions)) => throw null; public static void Serialize(System.Text.Json.Utf8JsonWriter writer, object value, System.Type inputType, System.Text.Json.Serialization.JsonSerializerContext context) => throw null; @@ -269,24 +258,24 @@ namespace System public static System.Byte[] SerializeToUtf8Bytes(TValue value, System.Text.Json.Serialization.Metadata.JsonTypeInfo jsonTypeInfo) => throw null; } - // Generated from `System.Text.Json.JsonSerializerDefaults` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonSerializerDefaults : int { General = 0, Web = 1, } - // Generated from `System.Text.Json.JsonSerializerOptions` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonSerializerOptions { public void AddContext() where TContext : System.Text.Json.Serialization.JsonSerializerContext, new() => throw null; public bool AllowTrailingCommas { get => throw null; set => throw null; } public System.Collections.Generic.IList Converters { get => throw null; } + public static System.Text.Json.JsonSerializerOptions Default { get => throw null; } public int DefaultBufferSize { get => throw null; set => throw null; } public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get => throw null; set => throw null; } public System.Text.Json.JsonNamingPolicy DictionaryKeyPolicy { get => throw null; set => throw null; } public System.Text.Encodings.Web.JavaScriptEncoder Encoder { get => throw null; set => throw null; } public System.Text.Json.Serialization.JsonConverter GetConverter(System.Type typeToConvert) => throw null; + public System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(System.Type type) => throw null; public bool IgnoreNullValues { get => throw null; set => throw null; } public bool IgnoreReadOnlyFields { get => throw null; set => throw null; } public bool IgnoreReadOnlyProperties { get => throw null; set => throw null; } @@ -300,11 +289,11 @@ namespace System public System.Text.Json.JsonNamingPolicy PropertyNamingPolicy { get => throw null; set => throw null; } public System.Text.Json.JsonCommentHandling ReadCommentHandling { get => throw null; set => throw null; } public System.Text.Json.Serialization.ReferenceHandler ReferenceHandler { get => throw null; set => throw null; } + public System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver TypeInfoResolver { get => throw null; set => throw null; } public System.Text.Json.Serialization.JsonUnknownTypeHandling UnknownTypeHandling { get => throw null; set => throw null; } public bool WriteIndented { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.JsonTokenType` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonTokenType : byte { Comment = 6, @@ -321,7 +310,6 @@ namespace System True = 9, } - // Generated from `System.Text.Json.JsonValueKind` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonValueKind : byte { Array = 2, @@ -334,19 +322,20 @@ namespace System Undefined = 0, } - // Generated from `System.Text.Json.JsonWriterOptions` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonWriterOptions { public System.Text.Encodings.Web.JavaScriptEncoder Encoder { get => throw null; set => throw null; } public bool Indented { get => throw null; set => throw null; } // Stub generator skipped constructor + public int MaxDepth { get => throw null; set => throw null; } public bool SkipValidation { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Utf8JsonReader` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct Utf8JsonReader { public System.Int64 BytesConsumed { get => throw null; } + public int CopyString(System.Span utf8Destination) => throw null; + public int CopyString(System.Span destination) => throw null; public int CurrentDepth { get => throw null; } public System.Text.Json.JsonReaderState CurrentState { get => throw null; } public bool GetBoolean() => throw null; @@ -395,6 +384,7 @@ namespace System public Utf8JsonReader(System.Buffers.ReadOnlySequence jsonData, bool isFinalBlock, System.Text.Json.JsonReaderState state) => throw null; public Utf8JsonReader(System.ReadOnlySpan jsonData, System.Text.Json.JsonReaderOptions options = default(System.Text.Json.JsonReaderOptions)) => throw null; public Utf8JsonReader(System.ReadOnlySpan jsonData, bool isFinalBlock, System.Text.Json.JsonReaderState state) => throw null; + public bool ValueIsEscaped { get => throw null; } public System.Buffers.ReadOnlySequence ValueSequence { get => throw null; } public System.ReadOnlySpan ValueSpan { get => throw null; } public bool ValueTextEquals(System.ReadOnlySpan utf8Text) => throw null; @@ -402,7 +392,6 @@ namespace System public bool ValueTextEquals(string text) => throw null; } - // Generated from `System.Text.Json.Utf8JsonWriter` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Utf8JsonWriter : System.IAsyncDisposable, System.IDisposable { public System.Int64 BytesCommitted { get => throw null; } @@ -529,7 +518,6 @@ namespace System namespace Nodes { - // Generated from `System.Text.Json.Nodes.JsonArray` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonArray : System.Text.Json.Nodes.JsonNode, System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.IEnumerable { public void Add(System.Text.Json.Nodes.JsonNode item) => throw null; @@ -552,7 +540,6 @@ namespace System public override void WriteTo(System.Text.Json.Utf8JsonWriter writer, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions)) => throw null; } - // Generated from `System.Text.Json.Nodes.JsonNode` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonNode { public System.Text.Json.Nodes.JsonArray AsArray() => throw null; @@ -641,14 +628,12 @@ namespace System public static implicit operator System.Text.Json.Nodes.JsonNode(System.UInt16? value) => throw null; } - // Generated from `System.Text.Json.Nodes.JsonNodeOptions` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public struct JsonNodeOptions { // Stub generator skipped constructor public bool PropertyNameCaseInsensitive { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Nodes.JsonObject` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonObject : System.Text.Json.Nodes.JsonNode, System.Collections.Generic.ICollection>, System.Collections.Generic.IDictionary, System.Collections.Generic.IEnumerable>, System.Collections.IEnumerable { public void Add(System.Collections.Generic.KeyValuePair property) => throw null; @@ -673,7 +658,6 @@ namespace System public override void WriteTo(System.Text.Json.Utf8JsonWriter writer, System.Text.Json.JsonSerializerOptions options = default(System.Text.Json.JsonSerializerOptions)) => throw null; } - // Generated from `System.Text.Json.Nodes.JsonValue` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonValue : System.Text.Json.Nodes.JsonNode { public static System.Text.Json.Nodes.JsonValue Create(System.DateTime value, System.Text.Json.Nodes.JsonNodeOptions? options = default(System.Text.Json.Nodes.JsonNodeOptions?)) => throw null; @@ -719,50 +703,42 @@ namespace System } namespace Serialization { - // Generated from `System.Text.Json.Serialization.IJsonOnDeserialized` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IJsonOnDeserialized { void OnDeserialized(); } - // Generated from `System.Text.Json.Serialization.IJsonOnDeserializing` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IJsonOnDeserializing { void OnDeserializing(); } - // Generated from `System.Text.Json.Serialization.IJsonOnSerialized` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IJsonOnSerialized { void OnSerialized(); } - // Generated from `System.Text.Json.Serialization.IJsonOnSerializing` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IJsonOnSerializing { void OnSerializing(); } - // Generated from `System.Text.Json.Serialization.JsonAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonAttribute : System.Attribute { protected JsonAttribute() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonConstructorAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonConstructorAttribute : System.Text.Json.Serialization.JsonAttribute { public JsonConstructorAttribute() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonConverter` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonConverter { public abstract bool CanConvert(System.Type typeToConvert); internal JsonConverter() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonConverter<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonConverter : System.Text.Json.Serialization.JsonConverter { public override bool CanConvert(System.Type typeToConvert) => throw null; @@ -774,7 +750,6 @@ namespace System public virtual void WriteAsPropertyName(System.Text.Json.Utf8JsonWriter writer, T value, System.Text.Json.JsonSerializerOptions options) => throw null; } - // Generated from `System.Text.Json.Serialization.JsonConverterAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute { public System.Type ConverterType { get => throw null; } @@ -783,27 +758,32 @@ namespace System public JsonConverterAttribute(System.Type converterType) => throw null; } - // Generated from `System.Text.Json.Serialization.JsonConverterFactory` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonConverterFactory : System.Text.Json.Serialization.JsonConverter { public abstract System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options); protected JsonConverterFactory() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonExtensionDataAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public class JsonDerivedTypeAttribute : System.Text.Json.Serialization.JsonAttribute + { + public System.Type DerivedType { get => throw null; } + public JsonDerivedTypeAttribute(System.Type derivedType) => throw null; + public JsonDerivedTypeAttribute(System.Type derivedType, int typeDiscriminator) => throw null; + public JsonDerivedTypeAttribute(System.Type derivedType, string typeDiscriminator) => throw null; + public object TypeDiscriminator { get => throw null; } + } + public class JsonExtensionDataAttribute : System.Text.Json.Serialization.JsonAttribute { public JsonExtensionDataAttribute() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonIgnoreAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonIgnoreAttribute : System.Text.Json.Serialization.JsonAttribute { public System.Text.Json.Serialization.JsonIgnoreCondition Condition { get => throw null; set => throw null; } public JsonIgnoreAttribute() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonIgnoreCondition` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonIgnoreCondition : int { Always = 1, @@ -812,20 +792,17 @@ namespace System WhenWritingNull = 3, } - // Generated from `System.Text.Json.Serialization.JsonIncludeAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonIncludeAttribute : System.Text.Json.Serialization.JsonAttribute { public JsonIncludeAttribute() => throw null; } - // Generated from `System.Text.Json.Serialization.JsonKnownNamingPolicy` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum JsonKnownNamingPolicy : int { CamelCase = 1, Unspecified = 0, } - // Generated from `System.Text.Json.Serialization.JsonNumberHandling` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum JsonNumberHandling : int { @@ -835,28 +812,37 @@ namespace System WriteAsString = 2, } - // Generated from `System.Text.Json.Serialization.JsonNumberHandlingAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonNumberHandlingAttribute : System.Text.Json.Serialization.JsonAttribute { public System.Text.Json.Serialization.JsonNumberHandling Handling { get => throw null; } public JsonNumberHandlingAttribute(System.Text.Json.Serialization.JsonNumberHandling handling) => throw null; } - // Generated from `System.Text.Json.Serialization.JsonPropertyNameAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public class JsonPolymorphicAttribute : System.Text.Json.Serialization.JsonAttribute + { + public bool IgnoreUnrecognizedTypeDiscriminators { get => throw null; set => throw null; } + public JsonPolymorphicAttribute() => throw null; + public string TypeDiscriminatorPropertyName { get => throw null; set => throw null; } + public System.Text.Json.Serialization.JsonUnknownDerivedTypeHandling UnknownDerivedTypeHandling { get => throw null; set => throw null; } + } + public class JsonPropertyNameAttribute : System.Text.Json.Serialization.JsonAttribute { public JsonPropertyNameAttribute(string name) => throw null; public string Name { get => throw null; } } - // Generated from `System.Text.Json.Serialization.JsonPropertyOrderAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonPropertyOrderAttribute : System.Text.Json.Serialization.JsonAttribute { public JsonPropertyOrderAttribute(int order) => throw null; public int Order { get => throw null; } } - // Generated from `System.Text.Json.Serialization.JsonSerializableAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public class JsonRequiredAttribute : System.Text.Json.Serialization.JsonAttribute + { + public JsonRequiredAttribute() => throw null; + } + public class JsonSerializableAttribute : System.Text.Json.Serialization.JsonAttribute { public System.Text.Json.Serialization.JsonSourceGenerationMode GenerationMode { get => throw null; set => throw null; } @@ -864,16 +850,15 @@ namespace System public string TypeInfoPropertyName { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.JsonSerializerContext` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` - public abstract class JsonSerializerContext + public abstract class JsonSerializerContext : System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver { protected abstract System.Text.Json.JsonSerializerOptions GeneratedSerializerOptions { get; } public abstract System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(System.Type type); + System.Text.Json.Serialization.Metadata.JsonTypeInfo System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver.GetTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options) => throw null; protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions options) => throw null; public System.Text.Json.JsonSerializerOptions Options { get => throw null; } } - // Generated from `System.Text.Json.Serialization.JsonSourceGenerationMode` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum JsonSourceGenerationMode : int { @@ -882,7 +867,6 @@ namespace System Serialization = 2, } - // Generated from `System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonSourceGenerationOptionsAttribute : System.Text.Json.Serialization.JsonAttribute { public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get => throw null; set => throw null; } @@ -895,7 +879,6 @@ namespace System public bool WriteIndented { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.JsonStringEnumConverter` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonStringEnumConverter : System.Text.Json.Serialization.JsonConverterFactory { public override bool CanConvert(System.Type typeToConvert) => throw null; @@ -904,14 +887,19 @@ namespace System public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy namingPolicy = default(System.Text.Json.JsonNamingPolicy), bool allowIntegerValues = default(bool)) => throw null; } - // Generated from `System.Text.Json.Serialization.JsonUnknownTypeHandling` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public enum JsonUnknownDerivedTypeHandling : int + { + FailSerialization = 0, + FallBackToBaseType = 1, + FallBackToNearestAncestor = 2, + } + public enum JsonUnknownTypeHandling : int { JsonElement = 0, JsonNode = 1, } - // Generated from `System.Text.Json.Serialization.ReferenceHandler` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ReferenceHandler { public abstract System.Text.Json.Serialization.ReferenceResolver CreateResolver(); @@ -920,14 +908,12 @@ namespace System protected ReferenceHandler() => throw null; } - // Generated from `System.Text.Json.Serialization.ReferenceHandler<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ReferenceHandler : System.Text.Json.Serialization.ReferenceHandler where T : System.Text.Json.Serialization.ReferenceResolver, new() { public override System.Text.Json.Serialization.ReferenceResolver CreateResolver() => throw null; public ReferenceHandler() => throw null; } - // Generated from `System.Text.Json.Serialization.ReferenceResolver` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ReferenceResolver { public abstract void AddReference(string referenceId, object value); @@ -938,7 +924,18 @@ namespace System namespace Metadata { - // Generated from `System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public class DefaultJsonTypeInfoResolver : System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver + { + public DefaultJsonTypeInfoResolver() => throw null; + public virtual System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options) => throw null; + public System.Collections.Generic.IList> Modifiers { get => throw null; } + } + + public interface IJsonTypeInfoResolver + { + System.Text.Json.Serialization.Metadata.JsonTypeInfo GetTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options); + } + public class JsonCollectionInfoValues { public System.Text.Json.Serialization.Metadata.JsonTypeInfo ElementInfo { get => throw null; set => throw null; } @@ -949,7 +946,16 @@ namespace System public System.Action SerializeHandler { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonMetadataServices` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` + public struct JsonDerivedType + { + public System.Type DerivedType { get => throw null; } + // Stub generator skipped constructor + public JsonDerivedType(System.Type derivedType) => throw null; + public JsonDerivedType(System.Type derivedType, int typeDiscriminator) => throw null; + public JsonDerivedType(System.Type derivedType, string typeDiscriminator) => throw null; + public object TypeDiscriminator { get => throw null; } + } + public static class JsonMetadataServices { public static System.Text.Json.Serialization.JsonConverter BooleanConverter { get => throw null; } @@ -960,6 +966,7 @@ namespace System public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentQueue => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentStack => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Dictionary => throw null; + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIAsyncEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IAsyncEnumerable => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateICollectionInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.ICollection => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IDictionary => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IDictionary => throw null; @@ -979,11 +986,13 @@ namespace System public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Stack => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable => throw null; public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateValueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) => throw null; + public static System.Text.Json.Serialization.JsonConverter DateOnlyConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter DateTimeConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter DateTimeOffsetConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter DecimalConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter DoubleConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter GetEnumConverter(System.Text.Json.JsonSerializerOptions options) where T : struct => throw null; + public static System.Text.Json.Serialization.JsonConverter GetNullableConverter(System.Text.Json.JsonSerializerOptions options) where T : struct => throw null; public static System.Text.Json.Serialization.JsonConverter GetNullableConverter(System.Text.Json.Serialization.Metadata.JsonTypeInfo underlyingTypeInfo) where T : struct => throw null; public static System.Text.Json.Serialization.JsonConverter GetUnsupportedTypeConverter() => throw null; public static System.Text.Json.Serialization.JsonConverter GuidConverter { get => throw null; } @@ -991,6 +1000,7 @@ namespace System public static System.Text.Json.Serialization.JsonConverter Int32Converter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter Int64Converter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter JsonArrayConverter { get => throw null; } + public static System.Text.Json.Serialization.JsonConverter JsonDocumentConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter JsonElementConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter JsonNodeConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter JsonObjectConverter { get => throw null; } @@ -999,6 +1009,7 @@ namespace System public static System.Text.Json.Serialization.JsonConverter SByteConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter SingleConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter StringConverter { get => throw null; } + public static System.Text.Json.Serialization.JsonConverter TimeOnlyConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter TimeSpanConverter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter UInt16Converter { get => throw null; } public static System.Text.Json.Serialization.JsonConverter UInt32Converter { get => throw null; } @@ -1007,7 +1018,6 @@ namespace System public static System.Text.Json.Serialization.JsonConverter VersionConverter { get => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonObjectInfoValues { public System.Func ConstructorParameterMetadataInitializer { get => throw null; set => throw null; } @@ -1019,7 +1029,6 @@ namespace System public System.Action SerializeHandler { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonParameterInfoValues` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonParameterInfoValues { public object DefaultValue { get => throw null; set => throw null; } @@ -1030,12 +1039,31 @@ namespace System public int Position { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonPropertyInfo` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` - public abstract class JsonPropertyInfo + public class JsonPolymorphismOptions { + public System.Collections.Generic.IList DerivedTypes { get => throw null; } + public bool IgnoreUnrecognizedTypeDiscriminators { get => throw null; set => throw null; } + public JsonPolymorphismOptions() => throw null; + public string TypeDiscriminatorPropertyName { get => throw null; set => throw null; } + public System.Text.Json.Serialization.JsonUnknownDerivedTypeHandling UnknownDerivedTypeHandling { get => throw null; set => throw null; } + } + + public abstract class JsonPropertyInfo + { + public System.Reflection.ICustomAttributeProvider AttributeProvider { get => throw null; set => throw null; } + public System.Text.Json.Serialization.JsonConverter CustomConverter { get => throw null; set => throw null; } + public System.Func Get { get => throw null; set => throw null; } + public bool IsExtensionData { get => throw null; set => throw null; } + public bool IsRequired { get => throw null; set => throw null; } + public string Name { get => throw null; set => throw null; } + public System.Text.Json.Serialization.JsonNumberHandling? NumberHandling { get => throw null; set => throw null; } + public System.Text.Json.JsonSerializerOptions Options { get => throw null; } + public int Order { get => throw null; set => throw null; } + public System.Type PropertyType { get => throw null; } + public System.Action Set { get => throw null; set => throw null; } + public System.Func ShouldSerialize { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class JsonPropertyInfoValues { public System.Text.Json.Serialization.JsonConverter Converter { get => throw null; set => throw null; } @@ -1055,18 +1083,47 @@ namespace System public System.Action Setter { get => throw null; set => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonTypeInfo` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` - public class JsonTypeInfo + public abstract class JsonTypeInfo { + public System.Text.Json.Serialization.JsonConverter Converter { get => throw null; } + public System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreateJsonPropertyInfo(System.Type propertyType, string name) => throw null; + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateJsonTypeInfo(System.Type type, System.Text.Json.JsonSerializerOptions options) => throw null; + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateJsonTypeInfo(System.Text.Json.JsonSerializerOptions options) => throw null; + public System.Func CreateObject { get => throw null; set => throw null; } + public bool IsReadOnly { get => throw null; } internal JsonTypeInfo() => throw null; + public System.Text.Json.Serialization.Metadata.JsonTypeInfoKind Kind { get => throw null; } + public void MakeReadOnly() => throw null; + public System.Text.Json.Serialization.JsonNumberHandling? NumberHandling { get => throw null; set => throw null; } + public System.Action OnDeserialized { get => throw null; set => throw null; } + public System.Action OnDeserializing { get => throw null; set => throw null; } + public System.Action OnSerialized { get => throw null; set => throw null; } + public System.Action OnSerializing { get => throw null; set => throw null; } + public System.Text.Json.JsonSerializerOptions Options { get => throw null; } + public System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions PolymorphismOptions { get => throw null; set => throw null; } + public System.Collections.Generic.IList Properties { get => throw null; } + public System.Type Type { get => throw null; } } - // Generated from `System.Text.Json.Serialization.Metadata.JsonTypeInfo<>` in `System.Text.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class JsonTypeInfo : System.Text.Json.Serialization.Metadata.JsonTypeInfo { + public System.Func CreateObject { get => throw null; set => throw null; } public System.Action SerializeHandler { get => throw null; } } + public enum JsonTypeInfoKind : int + { + Dictionary = 3, + Enumerable = 2, + None = 0, + Object = 1, + } + + public static class JsonTypeInfoResolver + { + public static System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver Combine(params System.Text.Json.Serialization.Metadata.IJsonTypeInfoResolver[] resolvers) => throw null; + } + } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.RegularExpressions.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.RegularExpressions.cs index ee63bfff6fd..327a4efb7aa 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.RegularExpressions.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Text.RegularExpressions.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Text.RegularExpressions, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace RegularExpressions { - // Generated from `System.Text.RegularExpressions.Capture` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Capture { internal Capture() => throw null; @@ -17,7 +17,6 @@ namespace System public System.ReadOnlySpan ValueSpan { get => throw null; } } - // Generated from `System.Text.RegularExpressions.CaptureCollection` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CaptureCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { void System.Collections.Generic.ICollection.Add(System.Text.RegularExpressions.Capture item) => throw null; @@ -48,7 +47,19 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Text.RegularExpressions.Group` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` + public class GeneratedRegexAttribute : System.Attribute + { + public string CultureName { get => throw null; } + public GeneratedRegexAttribute(string pattern) => throw null; + public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null; + public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds) => throw null; + public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, int matchTimeoutMilliseconds, string cultureName) => throw null; + public GeneratedRegexAttribute(string pattern, System.Text.RegularExpressions.RegexOptions options, string cultureName) => throw null; + public int MatchTimeoutMilliseconds { get => throw null; } + public System.Text.RegularExpressions.RegexOptions Options { get => throw null; } + public string Pattern { get => throw null; } + } + public class Group : System.Text.RegularExpressions.Capture { public System.Text.RegularExpressions.CaptureCollection Captures { get => throw null; } @@ -58,7 +69,6 @@ namespace System public static System.Text.RegularExpressions.Group Synchronized(System.Text.RegularExpressions.Group inner) => throw null; } - // Generated from `System.Text.RegularExpressions.GroupCollection` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GroupCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable>, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection>, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyDictionary, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { void System.Collections.Generic.ICollection.Add(System.Text.RegularExpressions.Group item) => throw null; @@ -95,7 +105,6 @@ namespace System public System.Collections.Generic.IEnumerable Values { get => throw null; } } - // Generated from `System.Text.RegularExpressions.Match` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Match : System.Text.RegularExpressions.Group { public static System.Text.RegularExpressions.Match Empty { get => throw null; } @@ -105,7 +114,6 @@ namespace System public static System.Text.RegularExpressions.Match Synchronized(System.Text.RegularExpressions.Match inner) => throw null; } - // Generated from `System.Text.RegularExpressions.MatchCollection` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class MatchCollection : System.Collections.Generic.ICollection, System.Collections.Generic.IEnumerable, System.Collections.Generic.IList, System.Collections.Generic.IReadOnlyCollection, System.Collections.Generic.IReadOnlyList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.IList { void System.Collections.Generic.ICollection.Add(System.Text.RegularExpressions.Match item) => throw null; @@ -136,18 +144,39 @@ namespace System public object SyncRoot { get => throw null; } } - // Generated from `System.Text.RegularExpressions.MatchEvaluator` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate string MatchEvaluator(System.Text.RegularExpressions.Match match); - // Generated from `System.Text.RegularExpressions.Regex` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Regex : System.Runtime.Serialization.ISerializable { + public struct ValueMatchEnumerator + { + public System.Text.RegularExpressions.ValueMatch Current { get => throw null; } + public System.Text.RegularExpressions.Regex.ValueMatchEnumerator GetEnumerator() => throw null; + public bool MoveNext() => throw null; + // Stub generator skipped constructor + } + + public static int CacheSize { get => throw null; set => throw null; } protected System.Collections.IDictionary CapNames { get => throw null; set => throw null; } protected System.Collections.IDictionary Caps { get => throw null; set => throw null; } public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompilationInfo[] regexinfos, System.Reflection.AssemblyName assemblyname) => throw null; public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompilationInfo[] regexinfos, System.Reflection.AssemblyName assemblyname, System.Reflection.Emit.CustomAttributeBuilder[] attributes) => throw null; public static void CompileToAssembly(System.Text.RegularExpressions.RegexCompilationInfo[] regexinfos, System.Reflection.AssemblyName assemblyname, System.Reflection.Emit.CustomAttributeBuilder[] attributes, string resourceFile) => throw null; + public int Count(System.ReadOnlySpan input) => throw null; + public int Count(System.ReadOnlySpan input, int startat) => throw null; + public static int Count(System.ReadOnlySpan input, string pattern) => throw null; + public static int Count(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null; + public static int Count(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null; + public int Count(string input) => throw null; + public static int Count(string input, string pattern) => throw null; + public static int Count(string input, string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null; + public static int Count(string input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null; + public System.Text.RegularExpressions.Regex.ValueMatchEnumerator EnumerateMatches(System.ReadOnlySpan input) => throw null; + public System.Text.RegularExpressions.Regex.ValueMatchEnumerator EnumerateMatches(System.ReadOnlySpan input, int startat) => throw null; + public static System.Text.RegularExpressions.Regex.ValueMatchEnumerator EnumerateMatches(System.ReadOnlySpan input, string pattern) => throw null; + public static System.Text.RegularExpressions.Regex.ValueMatchEnumerator EnumerateMatches(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null; + public static System.Text.RegularExpressions.Regex.ValueMatchEnumerator EnumerateMatches(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null; public static string Escape(string str) => throw null; public string[] GetGroupNames() => throw null; public int[] GetGroupNumbers() => throw null; @@ -156,6 +185,11 @@ namespace System public int GroupNumberFromName(string name) => throw null; public static System.TimeSpan InfiniteMatchTimeout; protected void InitializeReferences() => throw null; + public bool IsMatch(System.ReadOnlySpan input) => throw null; + public bool IsMatch(System.ReadOnlySpan input, int startat) => throw null; + public static bool IsMatch(System.ReadOnlySpan input, string pattern) => throw null; + public static bool IsMatch(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options) => throw null; + public static bool IsMatch(System.ReadOnlySpan input, string pattern, System.Text.RegularExpressions.RegexOptions options, System.TimeSpan matchTimeout) => throw null; public bool IsMatch(string input) => throw null; public bool IsMatch(string input, int startat) => throw null; public static bool IsMatch(string input, string pattern) => throw null; @@ -213,7 +247,6 @@ namespace System protected internal System.Text.RegularExpressions.RegexOptions roptions; } - // Generated from `System.Text.RegularExpressions.RegexCompilationInfo` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegexCompilationInfo { public bool IsPublic { get => throw null; set => throw null; } @@ -226,7 +259,6 @@ namespace System public RegexCompilationInfo(string pattern, System.Text.RegularExpressions.RegexOptions options, string name, string fullnamespace, bool ispublic, System.TimeSpan matchTimeout) => throw null; } - // Generated from `System.Text.RegularExpressions.RegexMatchTimeoutException` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegexMatchTimeoutException : System.TimeoutException, System.Runtime.Serialization.ISerializable { void System.Runtime.Serialization.ISerializable.GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -240,7 +272,6 @@ namespace System public RegexMatchTimeoutException(string regexInput, string regexPattern, System.TimeSpan matchTimeout) => throw null; } - // Generated from `System.Text.RegularExpressions.RegexOptions` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum RegexOptions : int { @@ -251,12 +282,12 @@ namespace System IgnoreCase = 1, IgnorePatternWhitespace = 32, Multiline = 2, + NonBacktracking = 1024, None = 0, RightToLeft = 64, Singleline = 16, } - // Generated from `System.Text.RegularExpressions.RegexParseError` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum RegexParseError : int { AlternationHasComment = 17, @@ -293,7 +324,6 @@ namespace System UnterminatedComment = 14, } - // Generated from `System.Text.RegularExpressions.RegexParseException` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegexParseException : System.ArgumentException { public System.Text.RegularExpressions.RegexParseError Error { get => throw null; } @@ -301,7 +331,6 @@ namespace System public int Offset { get => throw null; } } - // Generated from `System.Text.RegularExpressions.RegexRunner` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class RegexRunner { protected void Capture(int capnum, int start, int end) => throw null; @@ -314,9 +343,9 @@ namespace System protected void DoubleStack() => throw null; protected void DoubleTrack() => throw null; protected void EnsureStorage() => throw null; - protected abstract bool FindFirstChar(); - protected abstract void Go(); - protected abstract void InitTrackCount(); + protected virtual bool FindFirstChar() => throw null; + protected virtual void Go() => throw null; + protected virtual void InitTrackCount() => throw null; protected bool IsBoundary(int index, int startpos, int endpos) => throw null; protected bool IsECMABoundary(int index, int startpos, int endpos) => throw null; protected bool IsMatched(int cap) => throw null; @@ -324,6 +353,7 @@ namespace System protected int MatchLength(int cap) => throw null; protected int Popcrawl() => throw null; protected internal RegexRunner() => throw null; + protected internal virtual void Scan(System.ReadOnlySpan text) => throw null; protected internal System.Text.RegularExpressions.Match Scan(System.Text.RegularExpressions.Regex regex, string text, int textbeg, int textend, int textstart, int prevlen, bool quick) => throw null; protected internal System.Text.RegularExpressions.Match Scan(System.Text.RegularExpressions.Regex regex, string text, int textbeg, int textend, int textstart, int prevlen, bool quick, System.TimeSpan timeout) => throw null; protected void TransferCapture(int capnum, int uncapnum, int start, int end) => throw null; @@ -344,13 +374,19 @@ namespace System protected internal int runtrackpos; } - // Generated from `System.Text.RegularExpressions.RegexRunnerFactory` in `System.Text.RegularExpressions, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class RegexRunnerFactory { protected internal abstract System.Text.RegularExpressions.RegexRunner CreateInstance(); protected RegexRunnerFactory() => throw null; } + public struct ValueMatch + { + public int Index { get => throw null; } + public int Length { get => throw null; } + // Stub generator skipped constructor + } + } } } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Channels.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Channels.cs index 6e076885906..f898283d56e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Channels.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Channels.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Threading.Channels, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Channels { - // Generated from `System.Threading.Channels.BoundedChannelFullMode` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum BoundedChannelFullMode : int { DropNewest = 1, @@ -15,7 +15,6 @@ namespace System Wait = 0, } - // Generated from `System.Threading.Channels.BoundedChannelOptions` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class BoundedChannelOptions : System.Threading.Channels.ChannelOptions { public BoundedChannelOptions(int capacity) => throw null; @@ -23,7 +22,6 @@ namespace System public System.Threading.Channels.BoundedChannelFullMode FullMode { get => throw null; set => throw null; } } - // Generated from `System.Threading.Channels.Channel` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class Channel { public static System.Threading.Channels.Channel CreateBounded(System.Threading.Channels.BoundedChannelOptions options) => throw null; @@ -33,7 +31,6 @@ namespace System public static System.Threading.Channels.Channel CreateUnbounded(System.Threading.Channels.UnboundedChannelOptions options) => throw null; } - // Generated from `System.Threading.Channels.Channel<,>` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Channel { protected Channel() => throw null; @@ -43,13 +40,11 @@ namespace System public static implicit operator System.Threading.Channels.ChannelWriter(System.Threading.Channels.Channel channel) => throw null; } - // Generated from `System.Threading.Channels.Channel<>` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class Channel : System.Threading.Channels.Channel { protected Channel() => throw null; } - // Generated from `System.Threading.Channels.ChannelClosedException` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class ChannelClosedException : System.InvalidOperationException { public ChannelClosedException() => throw null; @@ -59,7 +54,6 @@ namespace System public ChannelClosedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.Channels.ChannelOptions` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ChannelOptions { public bool AllowSynchronousContinuations { get => throw null; set => throw null; } @@ -68,7 +62,6 @@ namespace System public bool SingleWriter { get => throw null; set => throw null; } } - // Generated from `System.Threading.Channels.ChannelReader<>` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ChannelReader { public virtual bool CanCount { get => throw null; } @@ -83,7 +76,6 @@ namespace System public abstract System.Threading.Tasks.ValueTask WaitToReadAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - // Generated from `System.Threading.Channels.ChannelWriter<>` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public abstract class ChannelWriter { protected ChannelWriter() => throw null; @@ -94,7 +86,6 @@ namespace System public virtual System.Threading.Tasks.ValueTask WriteAsync(T item, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) => throw null; } - // Generated from `System.Threading.Channels.UnboundedChannelOptions` in `System.Threading.Channels, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class UnboundedChannelOptions : System.Threading.Channels.ChannelOptions { public UnboundedChannelOptions() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Overlapped.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Overlapped.cs index b9fb80be02d..59532065c20 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Overlapped.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Overlapped.cs @@ -1,13 +1,12 @@ // This file contains auto-generated code. +// Generated from `System.Threading.Overlapped, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Threading { - // Generated from `System.Threading.IOCompletionCallback` in `System.Threading.Overlapped, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` unsafe public delegate void IOCompletionCallback(System.UInt32 errorCode, System.UInt32 numBytes, System.Threading.NativeOverlapped* pOVERLAP); - // Generated from `System.Threading.NativeOverlapped` in `System.Threading.Overlapped, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct NativeOverlapped { public System.IntPtr EventHandle; @@ -18,7 +17,6 @@ namespace System public int OffsetLow; } - // Generated from `System.Threading.Overlapped` in `System.Threading.Overlapped, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Overlapped { public System.IAsyncResult AsyncResult { get => throw null; set => throw null; } @@ -37,7 +35,6 @@ namespace System unsafe public System.Threading.NativeOverlapped* UnsafePack(System.Threading.IOCompletionCallback iocb, object userData) => throw null; } - // Generated from `System.Threading.PreAllocatedOverlapped` in `System.Threading.Overlapped, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class PreAllocatedOverlapped : System.IDisposable { public void Dispose() => throw null; @@ -46,7 +43,6 @@ namespace System // ERR: Stub generator didn't handle member: ~PreAllocatedOverlapped } - // Generated from `System.Threading.ThreadPoolBoundHandle` in `System.Threading.Overlapped, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadPoolBoundHandle : System.IDisposable { unsafe public System.Threading.NativeOverlapped* AllocateNativeOverlapped(System.Threading.IOCompletionCallback callback, object state, object pinData) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Dataflow.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Dataflow.cs index a4d85274e18..83cf3572c14 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Dataflow.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Dataflow.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Threading.Tasks.Dataflow, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -8,7 +9,6 @@ namespace System { namespace Dataflow { - // Generated from `System.Threading.Tasks.Dataflow.ActionBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ActionBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public ActionBlock(System.Action action) => throw null; @@ -24,7 +24,6 @@ namespace System public override string ToString() => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.BatchBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BatchBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public BatchBlock(int batchSize) => throw null; @@ -45,7 +44,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.BatchedJoinBlock<,,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BatchedJoinBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Collections.Generic.IList, System.Collections.Generic.IList>>, System.Threading.Tasks.Dataflow.ISourceBlock, System.Collections.Generic.IList, System.Collections.Generic.IList>> { public int BatchSize { get => throw null; } @@ -67,7 +65,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList, System.Collections.Generic.IList, System.Collections.Generic.IList>> items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.BatchedJoinBlock<,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BatchedJoinBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Collections.Generic.IList>>, System.Threading.Tasks.Dataflow.ISourceBlock, System.Collections.Generic.IList>> { public int BatchSize { get => throw null; } @@ -88,7 +85,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList, System.Collections.Generic.IList>> items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.BroadcastBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BroadcastBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public BroadcastBlock(System.Func cloningFunction) => throw null; @@ -106,7 +102,6 @@ namespace System bool System.Threading.Tasks.Dataflow.IReceivableSourceBlock.TryReceiveAll(out System.Collections.Generic.IList items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.BufferBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BufferBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public BufferBlock() => throw null; @@ -125,7 +120,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.DataflowBlock` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class DataflowBlock { public static System.IObservable AsObservable(this System.Threading.Tasks.Dataflow.ISourceBlock source) => throw null; @@ -156,7 +150,6 @@ namespace System public static bool TryReceive(this System.Threading.Tasks.Dataflow.IReceivableSourceBlock source, out TOutput item) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.DataflowBlockOptions` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataflowBlockOptions { public int BoundedCapacity { get => throw null; set => throw null; } @@ -169,7 +162,6 @@ namespace System public const int Unbounded = default; } - // Generated from `System.Threading.Tasks.Dataflow.DataflowLinkOptions` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class DataflowLinkOptions { public bool Append { get => throw null; set => throw null; } @@ -178,7 +170,6 @@ namespace System public bool PropagateCompletion { get => throw null; set => throw null; } } - // Generated from `System.Threading.Tasks.Dataflow.DataflowMessageHeader` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct DataflowMessageHeader : System.IEquatable { public static bool operator !=(System.Threading.Tasks.Dataflow.DataflowMessageHeader left, System.Threading.Tasks.Dataflow.DataflowMessageHeader right) => throw null; @@ -192,7 +183,6 @@ namespace System public bool IsValid { get => throw null; } } - // Generated from `System.Threading.Tasks.Dataflow.DataflowMessageStatus` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DataflowMessageStatus : int { Accepted = 0, @@ -202,7 +192,6 @@ namespace System Postponed = 2, } - // Generated from `System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExecutionDataflowBlockOptions : System.Threading.Tasks.Dataflow.DataflowBlockOptions { public ExecutionDataflowBlockOptions() => throw null; @@ -210,7 +199,6 @@ namespace System public bool SingleProducerConstrained { get => throw null; set => throw null; } } - // Generated from `System.Threading.Tasks.Dataflow.GroupingDataflowBlockOptions` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class GroupingDataflowBlockOptions : System.Threading.Tasks.Dataflow.DataflowBlockOptions { public bool Greedy { get => throw null; set => throw null; } @@ -218,7 +206,6 @@ namespace System public System.Int64 MaxNumberOfGroups { get => throw null; set => throw null; } } - // Generated from `System.Threading.Tasks.Dataflow.IDataflowBlock` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IDataflowBlock { void Complete(); @@ -226,19 +213,16 @@ namespace System void Fault(System.Exception exception); } - // Generated from `System.Threading.Tasks.Dataflow.IPropagatorBlock<,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IPropagatorBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { } - // Generated from `System.Threading.Tasks.Dataflow.IReceivableSourceBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IReceivableSourceBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.ISourceBlock { bool TryReceive(System.Predicate filter, out TOutput item); bool TryReceiveAll(out System.Collections.Generic.IList items); } - // Generated from `System.Threading.Tasks.Dataflow.ISourceBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ISourceBlock : System.Threading.Tasks.Dataflow.IDataflowBlock { TOutput ConsumeMessage(System.Threading.Tasks.Dataflow.DataflowMessageHeader messageHeader, System.Threading.Tasks.Dataflow.ITargetBlock target, out bool messageConsumed); @@ -247,13 +231,11 @@ namespace System bool ReserveMessage(System.Threading.Tasks.Dataflow.DataflowMessageHeader messageHeader, System.Threading.Tasks.Dataflow.ITargetBlock target); } - // Generated from `System.Threading.Tasks.Dataflow.ITargetBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface ITargetBlock : System.Threading.Tasks.Dataflow.IDataflowBlock { System.Threading.Tasks.Dataflow.DataflowMessageStatus OfferMessage(System.Threading.Tasks.Dataflow.DataflowMessageHeader messageHeader, TInput messageValue, System.Threading.Tasks.Dataflow.ISourceBlock source, bool consumeToAccept); } - // Generated from `System.Threading.Tasks.Dataflow.JoinBlock<,,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class JoinBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock>, System.Threading.Tasks.Dataflow.ISourceBlock> { public void Complete() => throw null; @@ -274,7 +256,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList> items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.JoinBlock<,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class JoinBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock>, System.Threading.Tasks.Dataflow.ISourceBlock> { public void Complete() => throw null; @@ -294,7 +275,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList> items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.TransformBlock<,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TransformBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public void Complete() => throw null; @@ -316,7 +296,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.TransformManyBlock<,>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class TransformManyBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public void Complete() => throw null; @@ -330,6 +309,8 @@ namespace System void System.Threading.Tasks.Dataflow.ISourceBlock.ReleaseReservation(System.Threading.Tasks.Dataflow.DataflowMessageHeader messageHeader, System.Threading.Tasks.Dataflow.ITargetBlock target) => throw null; bool System.Threading.Tasks.Dataflow.ISourceBlock.ReserveMessage(System.Threading.Tasks.Dataflow.DataflowMessageHeader messageHeader, System.Threading.Tasks.Dataflow.ITargetBlock target) => throw null; public override string ToString() => throw null; + public TransformManyBlock(System.Func> transform) => throw null; + public TransformManyBlock(System.Func> transform, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions dataflowBlockOptions) => throw null; public TransformManyBlock(System.Func> transform) => throw null; public TransformManyBlock(System.Func> transform, System.Threading.Tasks.Dataflow.ExecutionDataflowBlockOptions dataflowBlockOptions) => throw null; public TransformManyBlock(System.Func>> transform) => throw null; @@ -338,7 +319,6 @@ namespace System public bool TryReceiveAll(out System.Collections.Generic.IList items) => throw null; } - // Generated from `System.Threading.Tasks.Dataflow.WriteOnceBlock<>` in `System.Threading.Tasks.Dataflow, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WriteOnceBlock : System.Threading.Tasks.Dataflow.IDataflowBlock, System.Threading.Tasks.Dataflow.IPropagatorBlock, System.Threading.Tasks.Dataflow.IReceivableSourceBlock, System.Threading.Tasks.Dataflow.ISourceBlock, System.Threading.Tasks.Dataflow.ITargetBlock { public void Complete() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Parallel.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Parallel.cs index 598ad1d2393..7d73c62a13f 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Parallel.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Tasks.Parallel.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Threading.Tasks.Parallel, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Tasks { - // Generated from `System.Threading.Tasks.Parallel` in `System.Threading.Tasks.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Parallel { public static System.Threading.Tasks.ParallelLoopResult For(int fromInclusive, int toExclusive, System.Action body) => throw null; @@ -51,7 +51,6 @@ namespace System public static void Invoke(params System.Action[] actions) => throw null; } - // Generated from `System.Threading.Tasks.ParallelLoopResult` in `System.Threading.Tasks.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct ParallelLoopResult { public bool IsCompleted { get => throw null; } @@ -59,7 +58,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Threading.Tasks.ParallelLoopState` in `System.Threading.Tasks.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParallelLoopState { public void Break() => throw null; @@ -70,7 +68,6 @@ namespace System public void Stop() => throw null; } - // Generated from `System.Threading.Tasks.ParallelOptions` in `System.Threading.Tasks.Parallel, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ParallelOptions { public System.Threading.CancellationToken CancellationToken { get => throw null; set => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Thread.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Thread.cs index 1f3e228c6a0..ee5ec8959b9 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Thread.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.Thread.cs @@ -1,8 +1,8 @@ // This file contains auto-generated code. +// Generated from `System.Threading.Thread, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { - // Generated from `System.LocalDataStoreSlot` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LocalDataStoreSlot { // ERR: Stub generator didn't handle member: ~LocalDataStoreSlot @@ -10,7 +10,6 @@ namespace System namespace Threading { - // Generated from `System.Threading.ApartmentState` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ApartmentState : int { MTA = 1, @@ -18,7 +17,6 @@ namespace System Unknown = 2, } - // Generated from `System.Threading.CompressedStack` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CompressedStack : System.Runtime.Serialization.ISerializable { public static System.Threading.CompressedStack Capture() => throw null; @@ -28,10 +26,8 @@ namespace System public static void Run(System.Threading.CompressedStack compressedStack, System.Threading.ContextCallback callback, object state) => throw null; } - // Generated from `System.Threading.ParameterizedThreadStart` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ParameterizedThreadStart(object obj); - // Generated from `System.Threading.Thread` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Thread : System.Runtime.ConstrainedExecution.CriticalFinalizerObject { public void Abort() => throw null; @@ -118,23 +114,19 @@ namespace System // ERR: Stub generator didn't handle member: ~Thread } - // Generated from `System.Threading.ThreadAbortException` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadAbortException : System.SystemException { public object ExceptionState { get => throw null; } } - // Generated from `System.Threading.ThreadExceptionEventArgs` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadExceptionEventArgs : System.EventArgs { public System.Exception Exception { get => throw null; } public ThreadExceptionEventArgs(System.Exception t) => throw null; } - // Generated from `System.Threading.ThreadExceptionEventHandler` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ThreadExceptionEventHandler(object sender, System.Threading.ThreadExceptionEventArgs e); - // Generated from `System.Threading.ThreadInterruptedException` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadInterruptedException : System.SystemException { public ThreadInterruptedException() => throw null; @@ -143,7 +135,6 @@ namespace System public ThreadInterruptedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.ThreadPriority` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ThreadPriority : int { AboveNormal = 3, @@ -153,15 +144,12 @@ namespace System Normal = 2, } - // Generated from `System.Threading.ThreadStart` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ThreadStart(); - // Generated from `System.Threading.ThreadStartException` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadStartException : System.SystemException { } - // Generated from `System.Threading.ThreadState` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ThreadState : int { @@ -177,7 +165,6 @@ namespace System WaitSleepJoin = 32, } - // Generated from `System.Threading.ThreadStateException` in `System.Threading.Thread, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadStateException : System.SystemException { public ThreadStateException() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.ThreadPool.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.ThreadPool.cs index 0dadac294dc..0b672acd53e 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.ThreadPool.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.ThreadPool.cs @@ -1,22 +1,20 @@ // This file contains auto-generated code. +// Generated from `System.Threading.ThreadPool, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Threading { - // Generated from `System.Threading.IThreadPoolWorkItem` in `System.Threading.ThreadPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IThreadPoolWorkItem { void Execute(); } - // Generated from `System.Threading.RegisteredWaitHandle` in `System.Threading.ThreadPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class RegisteredWaitHandle : System.MarshalByRefObject { public bool Unregister(System.Threading.WaitHandle waitObject) => throw null; } - // Generated from `System.Threading.ThreadPool` in `System.Threading.ThreadPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class ThreadPool { public static bool BindHandle(System.IntPtr osHandle) => throw null; @@ -46,10 +44,8 @@ namespace System public static System.Threading.RegisteredWaitHandle UnsafeRegisterWaitForSingleObject(System.Threading.WaitHandle waitObject, System.Threading.WaitOrTimerCallback callBack, object state, System.UInt32 millisecondsTimeOutInterval, bool executeOnlyOnce) => throw null; } - // Generated from `System.Threading.WaitCallback` in `System.Threading.ThreadPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void WaitCallback(object state); - // Generated from `System.Threading.WaitOrTimerCallback` in `System.Threading.ThreadPool, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void WaitOrTimerCallback(object state, bool timedOut); } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.cs index 04111625dbb..ee58958e493 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Threading.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Threading, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Threading { - // Generated from `System.Threading.AbandonedMutexException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AbandonedMutexException : System.SystemException { public AbandonedMutexException() => throw null; @@ -18,7 +18,6 @@ namespace System public int MutexIndex { get => throw null; } } - // Generated from `System.Threading.AsyncFlowControl` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncFlowControl : System.IDisposable, System.IEquatable { public static bool operator !=(System.Threading.AsyncFlowControl a, System.Threading.AsyncFlowControl b) => throw null; @@ -31,7 +30,6 @@ namespace System public void Undo() => throw null; } - // Generated from `System.Threading.AsyncLocal<>` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AsyncLocal { public AsyncLocal() => throw null; @@ -39,7 +37,6 @@ namespace System public T Value { get => throw null; set => throw null; } } - // Generated from `System.Threading.AsyncLocalValueChangedArgs<>` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct AsyncLocalValueChangedArgs { // Stub generator skipped constructor @@ -48,13 +45,11 @@ namespace System public bool ThreadContextChanged { get => throw null; } } - // Generated from `System.Threading.AutoResetEvent` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class AutoResetEvent : System.Threading.EventWaitHandle { public AutoResetEvent(bool initialState) : base(default(bool), default(System.Threading.EventResetMode)) => throw null; } - // Generated from `System.Threading.Barrier` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Barrier : System.IDisposable { public System.Int64 AddParticipant() => throw null; @@ -76,7 +71,6 @@ namespace System public bool SignalAndWait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Threading.BarrierPostPhaseException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class BarrierPostPhaseException : System.Exception { public BarrierPostPhaseException() => throw null; @@ -86,10 +80,8 @@ namespace System public BarrierPostPhaseException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.ContextCallback` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ContextCallback(object state); - // Generated from `System.Threading.CountdownEvent` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CountdownEvent : System.IDisposable { public void AddCount() => throw null; @@ -115,14 +107,12 @@ namespace System public System.Threading.WaitHandle WaitHandle { get => throw null; } } - // Generated from `System.Threading.EventResetMode` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EventResetMode : int { AutoReset = 0, ManualReset = 1, } - // Generated from `System.Threading.EventWaitHandle` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class EventWaitHandle : System.Threading.WaitHandle { public EventWaitHandle(bool initialState, System.Threading.EventResetMode mode) => throw null; @@ -134,7 +124,6 @@ namespace System public static bool TryOpenExisting(string name, out System.Threading.EventWaitHandle result) => throw null; } - // Generated from `System.Threading.ExecutionContext` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ExecutionContext : System.IDisposable, System.Runtime.Serialization.ISerializable { public static System.Threading.ExecutionContext Capture() => throw null; @@ -148,7 +137,6 @@ namespace System public static System.Threading.AsyncFlowControl SuppressFlow() => throw null; } - // Generated from `System.Threading.HostExecutionContext` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HostExecutionContext : System.IDisposable { public virtual System.Threading.HostExecutionContext CreateCopy() => throw null; @@ -159,7 +147,6 @@ namespace System protected internal object State { get => throw null; set => throw null; } } - // Generated from `System.Threading.HostExecutionContextManager` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class HostExecutionContextManager { public virtual System.Threading.HostExecutionContext Capture() => throw null; @@ -168,7 +155,6 @@ namespace System public virtual object SetHostExecutionContext(System.Threading.HostExecutionContext hostExecutionContext) => throw null; } - // Generated from `System.Threading.Interlocked` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Interlocked { public static int Add(ref int location1, int value) => throw null; @@ -180,6 +166,7 @@ namespace System public static System.UInt32 And(ref System.UInt32 location1, System.UInt32 value) => throw null; public static System.UInt64 And(ref System.UInt64 location1, System.UInt64 value) => throw null; public static System.IntPtr CompareExchange(ref System.IntPtr location1, System.IntPtr value, System.IntPtr comparand) => throw null; + public static System.UIntPtr CompareExchange(ref System.UIntPtr location1, System.UIntPtr value, System.UIntPtr comparand) => throw null; public static double CompareExchange(ref double location1, double value, double comparand) => throw null; public static float CompareExchange(ref float location1, float value, float comparand) => throw null; public static int CompareExchange(ref int location1, int value, int comparand) => throw null; @@ -193,6 +180,7 @@ namespace System public static System.UInt32 Decrement(ref System.UInt32 location) => throw null; public static System.UInt64 Decrement(ref System.UInt64 location) => throw null; public static System.IntPtr Exchange(ref System.IntPtr location1, System.IntPtr value) => throw null; + public static System.UIntPtr Exchange(ref System.UIntPtr location1, System.UIntPtr value) => throw null; public static double Exchange(ref double location1, double value) => throw null; public static float Exchange(ref float location1, float value) => throw null; public static int Exchange(ref int location1, int value) => throw null; @@ -215,7 +203,6 @@ namespace System public static System.UInt64 Read(ref System.UInt64 location) => throw null; } - // Generated from `System.Threading.LazyInitializer` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class LazyInitializer { public static T EnsureInitialized(ref T target) where T : class => throw null; @@ -225,8 +212,7 @@ namespace System public static T EnsureInitialized(ref T target, ref object syncLock, System.Func valueFactory) where T : class => throw null; } - // Generated from `System.Threading.LockCookie` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` - public struct LockCookie + public struct LockCookie : System.IEquatable { public static bool operator !=(System.Threading.LockCookie a, System.Threading.LockCookie b) => throw null; public static bool operator ==(System.Threading.LockCookie a, System.Threading.LockCookie b) => throw null; @@ -236,7 +222,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Threading.LockRecursionException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class LockRecursionException : System.Exception { public LockRecursionException() => throw null; @@ -245,20 +230,17 @@ namespace System public LockRecursionException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.LockRecursionPolicy` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum LockRecursionPolicy : int { NoRecursion = 0, SupportsRecursion = 1, } - // Generated from `System.Threading.ManualResetEvent` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ManualResetEvent : System.Threading.EventWaitHandle { public ManualResetEvent(bool initialState) : base(default(bool), default(System.Threading.EventResetMode)) => throw null; } - // Generated from `System.Threading.ManualResetEventSlim` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ManualResetEventSlim : System.IDisposable { public void Dispose() => throw null; @@ -279,7 +261,6 @@ namespace System public System.Threading.WaitHandle WaitHandle { get => throw null; } } - // Generated from `System.Threading.Monitor` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Monitor { public static void Enter(object obj) => throw null; @@ -302,7 +283,6 @@ namespace System public static bool Wait(object obj, int millisecondsTimeout, bool exitContext) => throw null; } - // Generated from `System.Threading.Mutex` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Mutex : System.Threading.WaitHandle { public Mutex() => throw null; @@ -314,7 +294,6 @@ namespace System public static bool TryOpenExisting(string name, out System.Threading.Mutex result) => throw null; } - // Generated from `System.Threading.ReaderWriterLock` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReaderWriterLock : System.Runtime.ConstrainedExecution.CriticalFinalizerObject { public void AcquireReaderLock(System.TimeSpan timeout) => throw null; @@ -335,7 +314,6 @@ namespace System public int WriterSeqNum { get => throw null; } } - // Generated from `System.Threading.ReaderWriterLockSlim` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ReaderWriterLockSlim : System.IDisposable { public int CurrentReadCount { get => throw null; } @@ -366,7 +344,6 @@ namespace System public int WaitingWriteCount { get => throw null; } } - // Generated from `System.Threading.Semaphore` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class Semaphore : System.Threading.WaitHandle { public static System.Threading.Semaphore OpenExisting(string name) => throw null; @@ -378,7 +355,6 @@ namespace System public static bool TryOpenExisting(string name, out System.Threading.Semaphore result) => throw null; } - // Generated from `System.Threading.SemaphoreFullException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SemaphoreFullException : System.SystemException { public SemaphoreFullException() => throw null; @@ -387,7 +363,6 @@ namespace System public SemaphoreFullException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.SemaphoreSlim` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SemaphoreSlim : System.IDisposable { public System.Threading.WaitHandle AvailableWaitHandle { get => throw null; } @@ -412,10 +387,8 @@ namespace System public System.Threading.Tasks.Task WaitAsync(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) => throw null; } - // Generated from `System.Threading.SendOrPostCallback` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void SendOrPostCallback(object state); - // Generated from `System.Threading.SpinLock` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SpinLock { public void Enter(ref bool lockTaken) => throw null; @@ -431,7 +404,6 @@ namespace System public void TryEnter(ref bool lockTaken) => throw null; } - // Generated from `System.Threading.SpinWait` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct SpinWait { public int Count { get => throw null; } @@ -445,7 +417,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Threading.SynchronizationContext` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SynchronizationContext { public virtual System.Threading.SynchronizationContext CreateCopy() => throw null; @@ -462,7 +433,6 @@ namespace System protected static int WaitHelper(System.IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout) => throw null; } - // Generated from `System.Threading.SynchronizationLockException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SynchronizationLockException : System.SystemException { public SynchronizationLockException() => throw null; @@ -471,7 +441,6 @@ namespace System public SynchronizationLockException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Threading.ThreadLocal<>` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ThreadLocal : System.IDisposable { public void Dispose() => throw null; @@ -487,7 +456,6 @@ namespace System // ERR: Stub generator didn't handle member: ~ThreadLocal } - // Generated from `System.Threading.Volatile` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Volatile { public static System.IntPtr Read(ref System.IntPtr location) => throw null; @@ -520,7 +488,6 @@ namespace System public static void Write(ref T location, T value) where T : class => throw null; } - // Generated from `System.Threading.WaitHandleCannotBeOpenedException` in `System.Threading, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class WaitHandleCannotBeOpenedException : System.ApplicationException { public WaitHandleCannotBeOpenedException() => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Transactions.Local.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Transactions.Local.cs index 1851691a6a0..3ace7f93f48 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Transactions.Local.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Transactions.Local.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Transactions.Local, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Transactions { - // Generated from `System.Transactions.CommittableTransaction` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class CommittableTransaction : System.Transactions.Transaction, System.IAsyncResult { object System.IAsyncResult.AsyncState { get => throw null; } @@ -19,27 +19,23 @@ namespace System bool System.IAsyncResult.IsCompleted { get => throw null; } } - // Generated from `System.Transactions.DependentCloneOption` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum DependentCloneOption : int { BlockCommitUntilComplete = 0, RollbackIfNotComplete = 1, } - // Generated from `System.Transactions.DependentTransaction` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class DependentTransaction : System.Transactions.Transaction { public void Complete() => throw null; } - // Generated from `System.Transactions.Enlistment` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Enlistment { public void Done() => throw null; internal Enlistment() => throw null; } - // Generated from `System.Transactions.EnlistmentOptions` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` [System.Flags] public enum EnlistmentOptions : int { @@ -47,7 +43,6 @@ namespace System None = 0, } - // Generated from `System.Transactions.EnterpriseServicesInteropOption` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum EnterpriseServicesInteropOption : int { Automatic = 1, @@ -55,10 +50,8 @@ namespace System None = 0, } - // Generated from `System.Transactions.HostCurrentTransactionCallback` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate System.Transactions.Transaction HostCurrentTransactionCallback(); - // Generated from `System.Transactions.IDtcTransaction` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IDtcTransaction { void Abort(System.IntPtr reason, int retaining, int async); @@ -66,7 +59,6 @@ namespace System void GetTransactionInfo(System.IntPtr transactionInformation); } - // Generated from `System.Transactions.IEnlistmentNotification` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IEnlistmentNotification { void Commit(System.Transactions.Enlistment enlistment); @@ -75,7 +67,6 @@ namespace System void Rollback(System.Transactions.Enlistment enlistment); } - // Generated from `System.Transactions.IPromotableSinglePhaseNotification` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface IPromotableSinglePhaseNotification : System.Transactions.ITransactionPromoter { void Initialize(); @@ -83,25 +74,21 @@ namespace System void SinglePhaseCommit(System.Transactions.SinglePhaseEnlistment singlePhaseEnlistment); } - // Generated from `System.Transactions.ISimpleTransactionSuperior` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface ISimpleTransactionSuperior : System.Transactions.ITransactionPromoter { void Rollback(); } - // Generated from `System.Transactions.ISinglePhaseNotification` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface ISinglePhaseNotification : System.Transactions.IEnlistmentNotification { void SinglePhaseCommit(System.Transactions.SinglePhaseEnlistment singlePhaseEnlistment); } - // Generated from `System.Transactions.ITransactionPromoter` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public interface ITransactionPromoter { System.Byte[] Promote(); } - // Generated from `System.Transactions.IsolationLevel` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum IsolationLevel : int { Chaos = 5, @@ -113,7 +100,6 @@ namespace System Unspecified = 6, } - // Generated from `System.Transactions.PreparingEnlistment` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class PreparingEnlistment : System.Transactions.Enlistment { public void ForceRollback() => throw null; @@ -122,7 +108,6 @@ namespace System public System.Byte[] RecoveryInformation() => throw null; } - // Generated from `System.Transactions.SinglePhaseEnlistment` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SinglePhaseEnlistment : System.Transactions.Enlistment { public void Aborted() => throw null; @@ -132,13 +117,11 @@ namespace System public void InDoubt(System.Exception e) => throw null; } - // Generated from `System.Transactions.SubordinateTransaction` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class SubordinateTransaction : System.Transactions.Transaction { public SubordinateTransaction(System.Transactions.IsolationLevel isoLevel, System.Transactions.ISimpleTransactionSuperior superior) => throw null; } - // Generated from `System.Transactions.Transaction` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class Transaction : System.IDisposable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Transactions.Transaction x, System.Transactions.Transaction y) => throw null; @@ -168,7 +151,6 @@ namespace System public System.Transactions.TransactionInformation TransactionInformation { get => throw null; } } - // Generated from `System.Transactions.TransactionAbortedException` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionAbortedException : System.Transactions.TransactionException { public TransactionAbortedException() => throw null; @@ -177,17 +159,14 @@ namespace System public TransactionAbortedException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Transactions.TransactionCompletedEventHandler` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void TransactionCompletedEventHandler(object sender, System.Transactions.TransactionEventArgs e); - // Generated from `System.Transactions.TransactionEventArgs` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionEventArgs : System.EventArgs { public System.Transactions.Transaction Transaction { get => throw null; } public TransactionEventArgs() => throw null; } - // Generated from `System.Transactions.TransactionException` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionException : System.SystemException { public TransactionException() => throw null; @@ -196,7 +175,6 @@ namespace System public TransactionException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Transactions.TransactionInDoubtException` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionInDoubtException : System.Transactions.TransactionException { public TransactionInDoubtException() => throw null; @@ -205,7 +183,6 @@ namespace System public TransactionInDoubtException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Transactions.TransactionInformation` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionInformation { public System.DateTime CreationTime { get => throw null; } @@ -214,7 +191,6 @@ namespace System public System.Transactions.TransactionStatus Status { get => throw null; } } - // Generated from `System.Transactions.TransactionInterop` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class TransactionInterop { public static System.Transactions.IDtcTransaction GetDtcTransaction(System.Transactions.Transaction transaction) => throw null; @@ -227,18 +203,17 @@ namespace System public static System.Guid PromoterTypeDtc; } - // Generated from `System.Transactions.TransactionManager` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public static class TransactionManager { - public static System.TimeSpan DefaultTimeout { get => throw null; } + public static System.TimeSpan DefaultTimeout { get => throw null; set => throw null; } public static event System.Transactions.TransactionStartedEventHandler DistributedTransactionStarted; public static System.Transactions.HostCurrentTransactionCallback HostCurrentCallback { get => throw null; set => throw null; } - public static System.TimeSpan MaximumTimeout { get => throw null; } + public static bool ImplicitDistributedTransactions { get => throw null; set => throw null; } + public static System.TimeSpan MaximumTimeout { get => throw null; set => throw null; } public static void RecoveryComplete(System.Guid resourceManagerIdentifier) => throw null; public static System.Transactions.Enlistment Reenlist(System.Guid resourceManagerIdentifier, System.Byte[] recoveryInformation, System.Transactions.IEnlistmentNotification enlistmentNotification) => throw null; } - // Generated from `System.Transactions.TransactionManagerCommunicationException` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionManagerCommunicationException : System.Transactions.TransactionException { public TransactionManagerCommunicationException() => throw null; @@ -247,11 +222,11 @@ namespace System public TransactionManagerCommunicationException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Transactions.TransactionOptions` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` - public struct TransactionOptions + public struct TransactionOptions : System.IEquatable { public static bool operator !=(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) => throw null; public static bool operator ==(System.Transactions.TransactionOptions x, System.Transactions.TransactionOptions y) => throw null; + public bool Equals(System.Transactions.TransactionOptions other) => throw null; public override bool Equals(object obj) => throw null; public override int GetHashCode() => throw null; public System.Transactions.IsolationLevel IsolationLevel { get => throw null; set => throw null; } @@ -259,7 +234,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Transactions.TransactionPromotionException` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionPromotionException : System.Transactions.TransactionException { public TransactionPromotionException() => throw null; @@ -268,7 +242,6 @@ namespace System public TransactionPromotionException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Transactions.TransactionScope` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class TransactionScope : System.IDisposable { public void Complete() => throw null; @@ -289,14 +262,12 @@ namespace System public TransactionScope(System.Transactions.TransactionScopeOption scopeOption, System.Transactions.TransactionScopeAsyncFlowOption asyncFlowOption) => throw null; } - // Generated from `System.Transactions.TransactionScopeAsyncFlowOption` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum TransactionScopeAsyncFlowOption : int { Enabled = 1, Suppress = 0, } - // Generated from `System.Transactions.TransactionScopeOption` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum TransactionScopeOption : int { Required = 0, @@ -304,10 +275,8 @@ namespace System Suppress = 2, } - // Generated from `System.Transactions.TransactionStartedEventHandler` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public delegate void TransactionStartedEventHandler(object sender, System.Transactions.TransactionEventArgs e); - // Generated from `System.Transactions.TransactionStatus` in `System.Transactions.Local, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public enum TransactionStatus : int { Aborted = 2, diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Web.HttpUtility.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Web.HttpUtility.cs index b0420c2dc3f..6a83230211c 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Web.HttpUtility.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Web.HttpUtility.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Web.HttpUtility, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51`. namespace System { namespace Web { - // Generated from `System.Web.HttpUtility` in `System.Web.HttpUtility, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51` public class HttpUtility { public static string HtmlAttributeEncode(string s) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.ReaderWriter.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.ReaderWriter.cs index 87c2b5b1210..6895809f5b6 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.ReaderWriter.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.ReaderWriter.cs @@ -1,10 +1,10 @@ // This file contains auto-generated code. +// Generated from `System.Xml.ReaderWriter, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { namespace Xml { - // Generated from `System.Xml.ConformanceLevel` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ConformanceLevel : int { Auto = 0, @@ -12,7 +12,6 @@ namespace System Fragment = 1, } - // Generated from `System.Xml.DtdProcessing` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum DtdProcessing : int { Ignore = 1, @@ -20,33 +19,28 @@ namespace System Prohibit = 0, } - // Generated from `System.Xml.EntityHandling` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum EntityHandling : int { ExpandCharEntities = 2, ExpandEntities = 1, } - // Generated from `System.Xml.Formatting` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum Formatting : int { Indented = 1, None = 0, } - // Generated from `System.Xml.IApplicationResourceStreamResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IApplicationResourceStreamResolver { System.IO.Stream GetApplicationResourceStream(System.Uri relativeUri); } - // Generated from `System.Xml.IHasXmlNode` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IHasXmlNode { System.Xml.XmlNode GetNode(); } - // Generated from `System.Xml.IXmlLineInfo` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlLineInfo { bool HasLineInfo(); @@ -54,7 +48,6 @@ namespace System int LinePosition { get; } } - // Generated from `System.Xml.IXmlNamespaceResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlNamespaceResolver { System.Collections.Generic.IDictionary GetNamespacesInScope(System.Xml.XmlNamespaceScope scope); @@ -62,7 +55,6 @@ namespace System string LookupPrefix(string namespaceName); } - // Generated from `System.Xml.NameTable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class NameTable : System.Xml.XmlNameTable { public override string Add(System.Char[] key, int start, int len) => throw null; @@ -72,7 +64,6 @@ namespace System public NameTable() => throw null; } - // Generated from `System.Xml.NamespaceHandling` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum NamespaceHandling : int { @@ -80,7 +71,6 @@ namespace System OmitDuplicates = 1, } - // Generated from `System.Xml.NewLineHandling` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum NewLineHandling : int { Entitize = 1, @@ -88,7 +78,6 @@ namespace System Replace = 0, } - // Generated from `System.Xml.ReadState` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ReadState : int { Closed = 4, @@ -98,7 +87,6 @@ namespace System Interactive = 1, } - // Generated from `System.Xml.ValidationType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum ValidationType : int { Auto = 1, @@ -108,7 +96,6 @@ namespace System XDR = 3, } - // Generated from `System.Xml.WhitespaceHandling` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WhitespaceHandling : int { All = 0, @@ -116,7 +103,6 @@ namespace System Significant = 1, } - // Generated from `System.Xml.WriteState` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum WriteState : int { Attribute = 3, @@ -128,7 +114,6 @@ namespace System Start = 0, } - // Generated from `System.Xml.XmlAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttribute : System.Xml.XmlNode { public override System.Xml.XmlNode AppendChild(System.Xml.XmlNode newChild) => throw null; @@ -157,7 +142,6 @@ namespace System protected internal XmlAttribute(string prefix, string localName, string namespaceURI, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlAttributeCollection` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttributeCollection : System.Xml.XmlNamedNodeMap, System.Collections.ICollection, System.Collections.IEnumerable { public System.Xml.XmlAttribute Append(System.Xml.XmlAttribute node) => throw null; @@ -181,7 +165,6 @@ namespace System object System.Collections.ICollection.SyncRoot { get => throw null; } } - // Generated from `System.Xml.XmlCDataSection` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlCDataSection : System.Xml.XmlCharacterData { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -195,7 +178,6 @@ namespace System protected internal XmlCDataSection(string data, System.Xml.XmlDocument doc) : base(default(string), default(System.Xml.XmlDocument)) => throw null; } - // Generated from `System.Xml.XmlCharacterData` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlCharacterData : System.Xml.XmlLinkedNode { public virtual void AppendData(string strData) => throw null; @@ -210,7 +192,6 @@ namespace System protected internal XmlCharacterData(string data, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlComment` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlComment : System.Xml.XmlCharacterData { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -222,7 +203,6 @@ namespace System protected internal XmlComment(string comment, System.Xml.XmlDocument doc) : base(default(string), default(System.Xml.XmlDocument)) => throw null; } - // Generated from `System.Xml.XmlConvert` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlConvert { public static string DecodeName(string name) => throw null; @@ -287,7 +267,6 @@ namespace System public XmlConvert() => throw null; } - // Generated from `System.Xml.XmlDateTimeSerializationMode` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlDateTimeSerializationMode : int { Local = 0, @@ -296,7 +275,6 @@ namespace System Utc = 1, } - // Generated from `System.Xml.XmlDeclaration` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDeclaration : System.Xml.XmlLinkedNode { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -313,7 +291,6 @@ namespace System protected internal XmlDeclaration(string version, string encoding, string standalone, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlDocument` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDocument : System.Xml.XmlNode { public override string BaseURI { get => throw null; } @@ -385,7 +362,6 @@ namespace System public virtual System.Xml.XmlResolver XmlResolver { set => throw null; } } - // Generated from `System.Xml.XmlDocumentFragment` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDocumentFragment : System.Xml.XmlNode { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -400,7 +376,6 @@ namespace System protected internal XmlDocumentFragment(System.Xml.XmlDocument ownerDocument) => throw null; } - // Generated from `System.Xml.XmlDocumentType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlDocumentType : System.Xml.XmlLinkedNode { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -418,7 +393,6 @@ namespace System protected internal XmlDocumentType(string name, string publicId, string systemId, string internalSubset, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlElement` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlElement : System.Xml.XmlLinkedNode { public override System.Xml.XmlAttributeCollection Attributes { get => throw null; } @@ -460,7 +434,6 @@ namespace System protected internal XmlElement(string prefix, string localName, string namespaceURI, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlEntity` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlEntity : System.Xml.XmlNode { public override string BaseURI { get => throw null; } @@ -479,7 +452,6 @@ namespace System public override void WriteTo(System.Xml.XmlWriter w) => throw null; } - // Generated from `System.Xml.XmlEntityReference` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlEntityReference : System.Xml.XmlLinkedNode { public override string BaseURI { get => throw null; } @@ -494,7 +466,6 @@ namespace System protected internal XmlEntityReference(string name, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -509,7 +480,6 @@ namespace System public XmlException(string message, System.Exception innerException, int lineNumber, int linePosition) => throw null; } - // Generated from `System.Xml.XmlImplementation` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlImplementation { public virtual System.Xml.XmlDocument CreateDocument() => throw null; @@ -518,7 +488,6 @@ namespace System public XmlImplementation(System.Xml.XmlNameTable nt) => throw null; } - // Generated from `System.Xml.XmlLinkedNode` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlLinkedNode : System.Xml.XmlNode { public override System.Xml.XmlNode NextSibling { get => throw null; } @@ -526,7 +495,6 @@ namespace System internal XmlLinkedNode() => throw null; } - // Generated from `System.Xml.XmlNameTable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlNameTable { public abstract string Add(System.Char[] array, int offset, int length); @@ -536,7 +504,6 @@ namespace System protected XmlNameTable() => throw null; } - // Generated from `System.Xml.XmlNamedNodeMap` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNamedNodeMap : System.Collections.IEnumerable { public virtual int Count { get => throw null; } @@ -550,7 +517,6 @@ namespace System internal XmlNamedNodeMap() => throw null; } - // Generated from `System.Xml.XmlNamespaceManager` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNamespaceManager : System.Collections.IEnumerable, System.Xml.IXmlNamespaceResolver { public virtual void AddNamespace(string prefix, string uri) => throw null; @@ -567,7 +533,6 @@ namespace System public XmlNamespaceManager(System.Xml.XmlNameTable nameTable) => throw null; } - // Generated from `System.Xml.XmlNamespaceScope` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlNamespaceScope : int { All = 0, @@ -575,7 +540,6 @@ namespace System Local = 2, } - // Generated from `System.Xml.XmlNode` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlNode : System.Collections.IEnumerable, System.ICloneable, System.Xml.XPath.IXPathNavigable { public virtual System.Xml.XmlNode AppendChild(System.Xml.XmlNode newChild) => throw null; @@ -628,7 +592,6 @@ namespace System internal XmlNode() => throw null; } - // Generated from `System.Xml.XmlNodeChangedAction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlNodeChangedAction : int { Change = 2, @@ -636,7 +599,6 @@ namespace System Remove = 1, } - // Generated from `System.Xml.XmlNodeChangedEventArgs` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNodeChangedEventArgs : System.EventArgs { public System.Xml.XmlNodeChangedAction Action { get => throw null; } @@ -648,10 +610,8 @@ namespace System public XmlNodeChangedEventArgs(System.Xml.XmlNode node, System.Xml.XmlNode oldParent, System.Xml.XmlNode newParent, string oldValue, string newValue, System.Xml.XmlNodeChangedAction action) => throw null; } - // Generated from `System.Xml.XmlNodeChangedEventHandler` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlNodeChangedEventHandler(object sender, System.Xml.XmlNodeChangedEventArgs e); - // Generated from `System.Xml.XmlNodeList` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlNodeList : System.Collections.IEnumerable, System.IDisposable { public abstract int Count { get; } @@ -664,7 +624,6 @@ namespace System protected XmlNodeList() => throw null; } - // Generated from `System.Xml.XmlNodeOrder` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlNodeOrder : int { After = 1, @@ -673,7 +632,6 @@ namespace System Unknown = 3, } - // Generated from `System.Xml.XmlNodeReader` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNodeReader : System.Xml.XmlReader, System.Xml.IXmlNamespaceResolver { public override int AttributeCount { get => throw null; } @@ -723,7 +681,6 @@ namespace System public override System.Xml.XmlSpace XmlSpace { get => throw null; } } - // Generated from `System.Xml.XmlNodeType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlNodeType : int { Attribute = 2, @@ -746,7 +703,6 @@ namespace System XmlDeclaration = 17, } - // Generated from `System.Xml.XmlNotation` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNotation : System.Xml.XmlNode { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -762,7 +718,6 @@ namespace System public override void WriteTo(System.Xml.XmlWriter w) => throw null; } - // Generated from `System.Xml.XmlOutputMethod` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlOutputMethod : int { AutoDetect = 3, @@ -771,7 +726,6 @@ namespace System Xml = 0, } - // Generated from `System.Xml.XmlParserContext` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlParserContext { public string BaseURI { get => throw null; set => throw null; } @@ -790,7 +744,6 @@ namespace System public System.Xml.XmlSpace XmlSpace { get => throw null; set => throw null; } } - // Generated from `System.Xml.XmlProcessingInstruction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlProcessingInstruction : System.Xml.XmlLinkedNode { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -806,7 +759,6 @@ namespace System protected internal XmlProcessingInstruction(string target, string data, System.Xml.XmlDocument doc) => throw null; } - // Generated from `System.Xml.XmlQualifiedName` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlQualifiedName { public static bool operator !=(System.Xml.XmlQualifiedName a, System.Xml.XmlQualifiedName b) => throw null; @@ -824,7 +776,6 @@ namespace System public XmlQualifiedName(string name, string ns) => throw null; } - // Generated from `System.Xml.XmlReader` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlReader : System.IDisposable { public abstract int AttributeCount { get; } @@ -963,7 +914,6 @@ namespace System public virtual System.Xml.XmlSpace XmlSpace { get => throw null; } } - // Generated from `System.Xml.XmlReaderSettings` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlReaderSettings { public bool Async { get => throw null; set => throw null; } @@ -990,7 +940,6 @@ namespace System public System.Xml.XmlResolver XmlResolver { set => throw null; } } - // Generated from `System.Xml.XmlResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlResolver { public virtual System.Net.ICredentials Credentials { set => throw null; } @@ -998,10 +947,10 @@ namespace System public virtual System.Threading.Tasks.Task GetEntityAsync(System.Uri absoluteUri, string role, System.Type ofObjectToReturn) => throw null; public virtual System.Uri ResolveUri(System.Uri baseUri, string relativeUri) => throw null; public virtual bool SupportsType(System.Uri absoluteUri, System.Type type) => throw null; + public static System.Xml.XmlResolver ThrowingResolver { get => throw null; } protected XmlResolver() => throw null; } - // Generated from `System.Xml.XmlSecureResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSecureResolver : System.Xml.XmlResolver { public override System.Net.ICredentials Credentials { set => throw null; } @@ -1011,7 +960,6 @@ namespace System public XmlSecureResolver(System.Xml.XmlResolver resolver, string securityUrl) => throw null; } - // Generated from `System.Xml.XmlSignificantWhitespace` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSignificantWhitespace : System.Xml.XmlCharacterData { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -1026,7 +974,6 @@ namespace System protected internal XmlSignificantWhitespace(string strData, System.Xml.XmlDocument doc) : base(default(string), default(System.Xml.XmlDocument)) => throw null; } - // Generated from `System.Xml.XmlSpace` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSpace : int { Default = 1, @@ -1034,7 +981,6 @@ namespace System Preserve = 2, } - // Generated from `System.Xml.XmlText` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlText : System.Xml.XmlCharacterData { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -1050,7 +996,6 @@ namespace System protected internal XmlText(string strData, System.Xml.XmlDocument doc) : base(default(string), default(System.Xml.XmlDocument)) => throw null; } - // Generated from `System.Xml.XmlTextReader` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlTextReader : System.Xml.XmlReader, System.Xml.IXmlLineInfo, System.Xml.IXmlNamespaceResolver { public override int AttributeCount { get => throw null; } @@ -1130,7 +1075,6 @@ namespace System public XmlTextReader(string xmlFragment, System.Xml.XmlNodeType fragType, System.Xml.XmlParserContext context) => throw null; } - // Generated from `System.Xml.XmlTextWriter` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlTextWriter : System.Xml.XmlWriter { public System.IO.Stream BaseStream { get => throw null; } @@ -1175,7 +1119,6 @@ namespace System public XmlTextWriter(string filename, System.Text.Encoding encoding) => throw null; } - // Generated from `System.Xml.XmlTokenizedType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlTokenizedType : int { CDATA = 0, @@ -1193,7 +1136,6 @@ namespace System QName = 10, } - // Generated from `System.Xml.XmlUrlResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlUrlResolver : System.Xml.XmlResolver { public System.Net.Cache.RequestCachePolicy CachePolicy { set => throw null; } @@ -1205,7 +1147,6 @@ namespace System public XmlUrlResolver() => throw null; } - // Generated from `System.Xml.XmlValidatingReader` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlValidatingReader : System.Xml.XmlReader, System.Xml.IXmlLineInfo, System.Xml.IXmlNamespaceResolver { public override int AttributeCount { get => throw null; } @@ -1268,7 +1209,6 @@ namespace System public XmlValidatingReader(string xmlFragment, System.Xml.XmlNodeType fragType, System.Xml.XmlParserContext context) => throw null; } - // Generated from `System.Xml.XmlWhitespace` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlWhitespace : System.Xml.XmlCharacterData { public override System.Xml.XmlNode CloneNode(bool deep) => throw null; @@ -1283,7 +1223,6 @@ namespace System protected internal XmlWhitespace(string strData, System.Xml.XmlDocument doc) : base(default(string), default(System.Xml.XmlDocument)) => throw null; } - // Generated from `System.Xml.XmlWriter` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlWriter : System.IAsyncDisposable, System.IDisposable { public virtual void Close() => throw null; @@ -1389,7 +1328,6 @@ namespace System protected XmlWriter() => throw null; } - // Generated from `System.Xml.XmlWriterSettings` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlWriterSettings { public bool Async { get => throw null; set => throw null; } @@ -1414,7 +1352,6 @@ namespace System namespace Resolvers { - // Generated from `System.Xml.Resolvers.XmlKnownDtds` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum XmlKnownDtds : int { @@ -1424,7 +1361,6 @@ namespace System Xhtml10 = 1, } - // Generated from `System.Xml.Resolvers.XmlPreloadedResolver` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlPreloadedResolver : System.Xml.XmlResolver { public void Add(System.Uri uri, System.Byte[] value) => throw null; @@ -1448,7 +1384,6 @@ namespace System } namespace Schema { - // Generated from `System.Xml.Schema.IXmlSchemaInfo` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlSchemaInfo { bool IsDefault { get; } @@ -1460,7 +1395,6 @@ namespace System System.Xml.Schema.XmlSchemaValidity Validity { get; } } - // Generated from `System.Xml.Schema.ValidationEventArgs` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ValidationEventArgs : System.EventArgs { public System.Xml.Schema.XmlSchemaException Exception { get => throw null; } @@ -1468,10 +1402,8 @@ namespace System public System.Xml.Schema.XmlSeverityType Severity { get => throw null; } } - // Generated from `System.Xml.Schema.ValidationEventHandler` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void ValidationEventHandler(object sender, System.Xml.Schema.ValidationEventArgs e); - // Generated from `System.Xml.Schema.XmlAtomicValue` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAtomicValue : System.Xml.XPath.XPathItem, System.ICloneable { public System.Xml.Schema.XmlAtomicValue Clone() => throw null; @@ -1490,7 +1422,6 @@ namespace System public override System.Xml.Schema.XmlSchemaType XmlType { get => throw null; } } - // Generated from `System.Xml.Schema.XmlSchema` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchema : System.Xml.Schema.XmlSchemaObject { public System.Xml.Schema.XmlSchemaForm AttributeFormDefault { get => throw null; set => throw null; } @@ -1526,14 +1457,12 @@ namespace System public XmlSchema() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAll` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAll : System.Xml.Schema.XmlSchemaGroupBase { public override System.Xml.Schema.XmlSchemaObjectCollection Items { get => throw null; } public XmlSchemaAll() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAnnotated` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAnnotated : System.Xml.Schema.XmlSchemaObject { public System.Xml.Schema.XmlSchemaAnnotation Annotation { get => throw null; set => throw null; } @@ -1542,7 +1471,6 @@ namespace System public XmlSchemaAnnotated() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAnnotation` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAnnotation : System.Xml.Schema.XmlSchemaObject { public string Id { get => throw null; set => throw null; } @@ -1551,7 +1479,6 @@ namespace System public XmlSchemaAnnotation() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAny` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAny : System.Xml.Schema.XmlSchemaParticle { public string Namespace { get => throw null; set => throw null; } @@ -1559,7 +1486,6 @@ namespace System public XmlSchemaAny() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAnyAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAnyAttribute : System.Xml.Schema.XmlSchemaAnnotated { public string Namespace { get => throw null; set => throw null; } @@ -1567,7 +1493,6 @@ namespace System public XmlSchemaAnyAttribute() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAppInfo` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAppInfo : System.Xml.Schema.XmlSchemaObject { public System.Xml.XmlNode[] Markup { get => throw null; set => throw null; } @@ -1575,7 +1500,6 @@ namespace System public XmlSchemaAppInfo() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAttribute : System.Xml.Schema.XmlSchemaAnnotated { public System.Xml.Schema.XmlSchemaSimpleType AttributeSchemaType { get => throw null; } @@ -1592,7 +1516,6 @@ namespace System public XmlSchemaAttribute() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAttributeGroup` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAttributeGroup : System.Xml.Schema.XmlSchemaAnnotated { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -1603,21 +1526,18 @@ namespace System public XmlSchemaAttributeGroup() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaAttributeGroupRef` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaAttributeGroupRef : System.Xml.Schema.XmlSchemaAnnotated { public System.Xml.XmlQualifiedName RefName { get => throw null; set => throw null; } public XmlSchemaAttributeGroupRef() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaChoice` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaChoice : System.Xml.Schema.XmlSchemaGroupBase { public override System.Xml.Schema.XmlSchemaObjectCollection Items { get => throw null; } public XmlSchemaChoice() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaCollection` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaCollection : System.Collections.ICollection, System.Collections.IEnumerable { public System.Xml.Schema.XmlSchema Add(System.Xml.Schema.XmlSchema schema) => throw null; @@ -1643,7 +1563,6 @@ namespace System public XmlSchemaCollection(System.Xml.XmlNameTable nametable) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaCollectionEnumerator` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaCollectionEnumerator : System.Collections.IEnumerator { public System.Xml.Schema.XmlSchema Current { get => throw null; } @@ -1653,14 +1572,12 @@ namespace System void System.Collections.IEnumerator.Reset() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaCompilationSettings` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaCompilationSettings { public bool EnableUpaCheck { get => throw null; set => throw null; } public XmlSchemaCompilationSettings() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaComplexContent` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaComplexContent : System.Xml.Schema.XmlSchemaContentModel { public override System.Xml.Schema.XmlSchemaContent Content { get => throw null; set => throw null; } @@ -1668,7 +1585,6 @@ namespace System public XmlSchemaComplexContent() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaComplexContentExtension` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaComplexContentExtension : System.Xml.Schema.XmlSchemaContent { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -1678,7 +1594,6 @@ namespace System public XmlSchemaComplexContentExtension() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaComplexContentRestriction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaComplexContentRestriction : System.Xml.Schema.XmlSchemaContent { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -1688,7 +1603,6 @@ namespace System public XmlSchemaComplexContentRestriction() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaComplexType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaComplexType : System.Xml.Schema.XmlSchemaType { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -1706,20 +1620,17 @@ namespace System public XmlSchemaComplexType() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaContent` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaContent : System.Xml.Schema.XmlSchemaAnnotated { protected XmlSchemaContent() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaContentModel` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaContentModel : System.Xml.Schema.XmlSchemaAnnotated { public abstract System.Xml.Schema.XmlSchemaContent Content { get; set; } protected XmlSchemaContentModel() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaContentProcessing` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaContentProcessing : int { Lax = 2, @@ -1728,7 +1639,6 @@ namespace System Strict = 3, } - // Generated from `System.Xml.Schema.XmlSchemaContentType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaContentType : int { ElementOnly = 2, @@ -1737,7 +1647,6 @@ namespace System TextOnly = 0, } - // Generated from `System.Xml.Schema.XmlSchemaDatatype` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaDatatype { public virtual object ChangeType(object value, System.Type targetType) => throw null; @@ -1750,7 +1659,6 @@ namespace System public virtual System.Xml.Schema.XmlSchemaDatatypeVariety Variety { get => throw null; } } - // Generated from `System.Xml.Schema.XmlSchemaDatatypeVariety` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaDatatypeVariety : int { Atomic = 0, @@ -1758,7 +1666,6 @@ namespace System Union = 2, } - // Generated from `System.Xml.Schema.XmlSchemaDerivationMethod` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum XmlSchemaDerivationMethod : int { @@ -1772,7 +1679,6 @@ namespace System Union = 16, } - // Generated from `System.Xml.Schema.XmlSchemaDocumentation` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaDocumentation : System.Xml.Schema.XmlSchemaObject { public string Language { get => throw null; set => throw null; } @@ -1781,7 +1687,6 @@ namespace System public XmlSchemaDocumentation() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaElement` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaElement : System.Xml.Schema.XmlSchemaParticle { public System.Xml.Schema.XmlSchemaDerivationMethod Block { get => throw null; set => throw null; } @@ -1805,13 +1710,11 @@ namespace System public XmlSchemaElement() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaEnumerationFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaEnumerationFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaEnumerationFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -1827,7 +1730,6 @@ namespace System public XmlSchemaException(string message, System.Exception innerException, int lineNumber, int linePosition) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaExternal` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaExternal : System.Xml.Schema.XmlSchemaObject { public string Id { get => throw null; set => throw null; } @@ -1837,7 +1739,6 @@ namespace System protected XmlSchemaExternal() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaFacet : System.Xml.Schema.XmlSchemaAnnotated { public virtual bool IsFixed { get => throw null; set => throw null; } @@ -1845,7 +1746,6 @@ namespace System protected XmlSchemaFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaForm` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaForm : int { None = 0, @@ -1853,13 +1753,11 @@ namespace System Unqualified = 2, } - // Generated from `System.Xml.Schema.XmlSchemaFractionDigitsFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaFractionDigitsFacet : System.Xml.Schema.XmlSchemaNumericFacet { public XmlSchemaFractionDigitsFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaGroup` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaGroup : System.Xml.Schema.XmlSchemaAnnotated { public string Name { get => throw null; set => throw null; } @@ -1868,14 +1766,12 @@ namespace System public XmlSchemaGroup() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaGroupBase` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaGroupBase : System.Xml.Schema.XmlSchemaParticle { public abstract System.Xml.Schema.XmlSchemaObjectCollection Items { get; } internal XmlSchemaGroupBase() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaGroupRef` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaGroupRef : System.Xml.Schema.XmlSchemaParticle { public System.Xml.Schema.XmlSchemaGroupBase Particle { get => throw null; } @@ -1883,7 +1779,6 @@ namespace System public XmlSchemaGroupRef() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaIdentityConstraint` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaIdentityConstraint : System.Xml.Schema.XmlSchemaAnnotated { public System.Xml.Schema.XmlSchemaObjectCollection Fields { get => throw null; } @@ -1893,7 +1788,6 @@ namespace System public XmlSchemaIdentityConstraint() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaImport` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaImport : System.Xml.Schema.XmlSchemaExternal { public System.Xml.Schema.XmlSchemaAnnotation Annotation { get => throw null; set => throw null; } @@ -1901,17 +1795,14 @@ namespace System public XmlSchemaImport() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaInclude` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaInclude : System.Xml.Schema.XmlSchemaExternal { public System.Xml.Schema.XmlSchemaAnnotation Annotation { get => throw null; set => throw null; } public XmlSchemaInclude() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaInference` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaInference { - // Generated from `System.Xml.Schema.XmlSchemaInference+InferenceOption` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum InferenceOption : int { Relaxed = 1, @@ -1926,7 +1817,6 @@ namespace System public XmlSchemaInference() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaInferenceException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaInferenceException : System.Xml.Schema.XmlSchemaException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -1937,7 +1827,6 @@ namespace System public XmlSchemaInferenceException(string message, System.Exception innerException, int lineNumber, int linePosition) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaInfo` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaInfo : System.Xml.Schema.IXmlSchemaInfo { public System.Xml.Schema.XmlSchemaContentType ContentType { get => throw null; set => throw null; } @@ -1951,62 +1840,52 @@ namespace System public XmlSchemaInfo() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaKey` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaKey : System.Xml.Schema.XmlSchemaIdentityConstraint { public XmlSchemaKey() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaKeyref` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaKeyref : System.Xml.Schema.XmlSchemaIdentityConstraint { public System.Xml.XmlQualifiedName Refer { get => throw null; set => throw null; } public XmlSchemaKeyref() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaLengthFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaLengthFacet : System.Xml.Schema.XmlSchemaNumericFacet { public XmlSchemaLengthFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMaxExclusiveFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMaxExclusiveFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaMaxExclusiveFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMaxInclusiveFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMaxInclusiveFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaMaxInclusiveFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMaxLengthFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMaxLengthFacet : System.Xml.Schema.XmlSchemaNumericFacet { public XmlSchemaMaxLengthFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMinExclusiveFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMinExclusiveFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaMinExclusiveFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMinInclusiveFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMinInclusiveFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaMinInclusiveFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaMinLengthFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaMinLengthFacet : System.Xml.Schema.XmlSchemaNumericFacet { public XmlSchemaMinLengthFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaNotation` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaNotation : System.Xml.Schema.XmlSchemaAnnotated { public string Name { get => throw null; set => throw null; } @@ -2015,13 +1894,11 @@ namespace System public XmlSchemaNotation() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaNumericFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaNumericFacet : System.Xml.Schema.XmlSchemaFacet { protected XmlSchemaNumericFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaObject` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaObject { public int LineNumber { get => throw null; set => throw null; } @@ -2032,7 +1909,6 @@ namespace System protected XmlSchemaObject() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaObjectCollection` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaObjectCollection : System.Collections.CollectionBase { public int Add(System.Xml.Schema.XmlSchemaObject item) => throw null; @@ -2051,7 +1927,6 @@ namespace System public XmlSchemaObjectCollection(System.Xml.Schema.XmlSchemaObject parent) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaObjectEnumerator` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaObjectEnumerator : System.Collections.IEnumerator { public System.Xml.Schema.XmlSchemaObject Current { get => throw null; } @@ -2062,7 +1937,6 @@ namespace System void System.Collections.IEnumerator.Reset() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaObjectTable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaObjectTable { public bool Contains(System.Xml.XmlQualifiedName name) => throw null; @@ -2073,7 +1947,6 @@ namespace System public System.Collections.ICollection Values { get => throw null; } } - // Generated from `System.Xml.Schema.XmlSchemaParticle` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaParticle : System.Xml.Schema.XmlSchemaAnnotated { public System.Decimal MaxOccurs { get => throw null; set => throw null; } @@ -2083,13 +1956,11 @@ namespace System protected XmlSchemaParticle() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaPatternFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaPatternFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaPatternFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaRedefine` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaRedefine : System.Xml.Schema.XmlSchemaExternal { public System.Xml.Schema.XmlSchemaObjectTable AttributeGroups { get => throw null; } @@ -2099,14 +1970,12 @@ namespace System public XmlSchemaRedefine() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSequence` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSequence : System.Xml.Schema.XmlSchemaGroupBase { public override System.Xml.Schema.XmlSchemaObjectCollection Items { get => throw null; } public XmlSchemaSequence() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSet { public System.Xml.Schema.XmlSchema Add(System.Xml.Schema.XmlSchema schema) => throw null; @@ -2135,14 +2004,12 @@ namespace System public XmlSchemaSet(System.Xml.XmlNameTable nameTable) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleContent` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleContent : System.Xml.Schema.XmlSchemaContentModel { public override System.Xml.Schema.XmlSchemaContent Content { get => throw null; set => throw null; } public XmlSchemaSimpleContent() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleContentExtension` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleContentExtension : System.Xml.Schema.XmlSchemaContent { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -2151,7 +2018,6 @@ namespace System public XmlSchemaSimpleContentExtension() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleContentRestriction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleContentRestriction : System.Xml.Schema.XmlSchemaContent { public System.Xml.Schema.XmlSchemaAnyAttribute AnyAttribute { get => throw null; set => throw null; } @@ -2162,20 +2028,17 @@ namespace System public XmlSchemaSimpleContentRestriction() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleType : System.Xml.Schema.XmlSchemaType { public System.Xml.Schema.XmlSchemaSimpleTypeContent Content { get => throw null; set => throw null; } public XmlSchemaSimpleType() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleTypeContent` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSchemaSimpleTypeContent : System.Xml.Schema.XmlSchemaAnnotated { protected XmlSchemaSimpleTypeContent() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleTypeList` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleTypeList : System.Xml.Schema.XmlSchemaSimpleTypeContent { public System.Xml.Schema.XmlSchemaSimpleType BaseItemType { get => throw null; set => throw null; } @@ -2184,7 +2047,6 @@ namespace System public XmlSchemaSimpleTypeList() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleTypeRestriction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleTypeRestriction : System.Xml.Schema.XmlSchemaSimpleTypeContent { public System.Xml.Schema.XmlSchemaSimpleType BaseType { get => throw null; set => throw null; } @@ -2193,7 +2055,6 @@ namespace System public XmlSchemaSimpleTypeRestriction() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaSimpleTypeUnion` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaSimpleTypeUnion : System.Xml.Schema.XmlSchemaSimpleTypeContent { public System.Xml.Schema.XmlSchemaSimpleType[] BaseMemberTypes { get => throw null; } @@ -2202,13 +2063,11 @@ namespace System public XmlSchemaSimpleTypeUnion() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaTotalDigitsFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaTotalDigitsFacet : System.Xml.Schema.XmlSchemaNumericFacet { public XmlSchemaTotalDigitsFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaType : System.Xml.Schema.XmlSchemaAnnotated { public object BaseSchemaType { get => throw null; } @@ -2229,13 +2088,11 @@ namespace System public XmlSchemaType() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaUnique` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaUnique : System.Xml.Schema.XmlSchemaIdentityConstraint { public XmlSchemaUnique() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaUse` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaUse : int { None = 0, @@ -2244,7 +2101,6 @@ namespace System Required = 3, } - // Generated from `System.Xml.Schema.XmlSchemaValidationException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaValidationException : System.Xml.Schema.XmlSchemaException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -2257,7 +2113,6 @@ namespace System public XmlSchemaValidationException(string message, System.Exception innerException, int lineNumber, int linePosition) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaValidationFlags` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum XmlSchemaValidationFlags : int { @@ -2269,7 +2124,6 @@ namespace System ReportValidationWarnings = 4, } - // Generated from `System.Xml.Schema.XmlSchemaValidator` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaValidator { public void AddSchema(System.Xml.Schema.XmlSchema schema) => throw null; @@ -2299,7 +2153,6 @@ namespace System public XmlSchemaValidator(System.Xml.XmlNameTable nameTable, System.Xml.Schema.XmlSchemaSet schemas, System.Xml.IXmlNamespaceResolver namespaceResolver, System.Xml.Schema.XmlSchemaValidationFlags validationFlags) => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaValidity` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSchemaValidity : int { Invalid = 2, @@ -2307,27 +2160,23 @@ namespace System Valid = 1, } - // Generated from `System.Xml.Schema.XmlSchemaWhiteSpaceFacet` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaWhiteSpaceFacet : System.Xml.Schema.XmlSchemaFacet { public XmlSchemaWhiteSpaceFacet() => throw null; } - // Generated from `System.Xml.Schema.XmlSchemaXPath` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaXPath : System.Xml.Schema.XmlSchemaAnnotated { public string XPath { get => throw null; set => throw null; } public XmlSchemaXPath() => throw null; } - // Generated from `System.Xml.Schema.XmlSeverityType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSeverityType : int { Error = 0, Warning = 1, } - // Generated from `System.Xml.Schema.XmlTypeCode` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlTypeCode : int { AnyAtomicType = 10, @@ -2387,13 +2236,11 @@ namespace System YearMonthDuration = 53, } - // Generated from `System.Xml.Schema.XmlValueGetter` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate object XmlValueGetter(); } namespace Serialization { - // Generated from `System.Xml.Serialization.IXmlSerializable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlSerializable { System.Xml.Schema.XmlSchema GetSchema(); @@ -2401,13 +2248,11 @@ namespace System void WriteXml(System.Xml.XmlWriter writer); } - // Generated from `System.Xml.Serialization.XmlAnyAttributeAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAnyAttributeAttribute : System.Attribute { public XmlAnyAttributeAttribute() => throw null; } - // Generated from `System.Xml.Serialization.XmlAnyElementAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAnyElementAttribute : System.Attribute { public string Name { get => throw null; set => throw null; } @@ -2418,7 +2263,6 @@ namespace System public XmlAnyElementAttribute(string name, string ns) => throw null; } - // Generated from `System.Xml.Serialization.XmlAttributeAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttributeAttribute : System.Attribute { public string AttributeName { get => throw null; set => throw null; } @@ -2432,7 +2276,6 @@ namespace System public XmlAttributeAttribute(string attributeName, System.Type type) => throw null; } - // Generated from `System.Xml.Serialization.XmlElementAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlElementAttribute : System.Attribute { public string DataType { get => throw null; set => throw null; } @@ -2448,7 +2291,6 @@ namespace System public XmlElementAttribute(string elementName, System.Type type) => throw null; } - // Generated from `System.Xml.Serialization.XmlEnumAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlEnumAttribute : System.Attribute { public string Name { get => throw null; set => throw null; } @@ -2456,19 +2298,16 @@ namespace System public XmlEnumAttribute(string name) => throw null; } - // Generated from `System.Xml.Serialization.XmlIgnoreAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlIgnoreAttribute : System.Attribute { public XmlIgnoreAttribute() => throw null; } - // Generated from `System.Xml.Serialization.XmlNamespaceDeclarationsAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNamespaceDeclarationsAttribute : System.Attribute { public XmlNamespaceDeclarationsAttribute() => throw null; } - // Generated from `System.Xml.Serialization.XmlRootAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlRootAttribute : System.Attribute { public string DataType { get => throw null; set => throw null; } @@ -2479,7 +2318,6 @@ namespace System public XmlRootAttribute(string elementName) => throw null; } - // Generated from `System.Xml.Serialization.XmlSchemaProviderAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaProviderAttribute : System.Attribute { public bool IsAny { get => throw null; set => throw null; } @@ -2487,7 +2325,6 @@ namespace System public XmlSchemaProviderAttribute(string methodName) => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializerNamespaces` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSerializerNamespaces { public void Add(string prefix, string ns) => throw null; @@ -2498,7 +2335,6 @@ namespace System public XmlSerializerNamespaces(System.Xml.Serialization.XmlSerializerNamespaces namespaces) => throw null; } - // Generated from `System.Xml.Serialization.XmlTextAttribute` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlTextAttribute : System.Attribute { public string DataType { get => throw null; set => throw null; } @@ -2510,13 +2346,11 @@ namespace System } namespace XPath { - // Generated from `System.Xml.XPath.IXPathNavigable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXPathNavigable { System.Xml.XPath.XPathNavigator CreateNavigator(); } - // Generated from `System.Xml.XPath.XPathExpression` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XPathExpression { public abstract void AddSort(object expr, System.Collections.IComparer comparer); @@ -2530,7 +2364,6 @@ namespace System public abstract void SetContext(System.Xml.XmlNamespaceManager nsManager); } - // Generated from `System.Xml.XPath.XPathItem` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XPathItem { public abstract bool IsNode { get; } @@ -2548,7 +2381,6 @@ namespace System public abstract System.Xml.Schema.XmlSchemaType XmlType { get; } } - // Generated from `System.Xml.XPath.XPathNamespaceScope` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XPathNamespaceScope : int { All = 0, @@ -2556,7 +2388,6 @@ namespace System Local = 2, } - // Generated from `System.Xml.XPath.XPathNavigator` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XPathNavigator : System.Xml.XPath.XPathItem, System.ICloneable, System.Xml.IXmlNamespaceResolver, System.Xml.XPath.IXPathNavigable { public virtual System.Xml.XmlWriter AppendChild() => throw null; @@ -2677,7 +2508,6 @@ namespace System public override System.Xml.Schema.XmlSchemaType XmlType { get => throw null; } } - // Generated from `System.Xml.XPath.XPathNodeIterator` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XPathNodeIterator : System.Collections.IEnumerable, System.ICloneable { public abstract System.Xml.XPath.XPathNodeIterator Clone(); @@ -2690,7 +2520,6 @@ namespace System protected XPathNodeIterator() => throw null; } - // Generated from `System.Xml.XPath.XPathNodeType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XPathNodeType : int { All = 9, @@ -2705,7 +2534,6 @@ namespace System Whitespace = 6, } - // Generated from `System.Xml.XPath.XPathResultType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XPathResultType : int { Any = 5, @@ -2717,7 +2545,6 @@ namespace System String = 1, } - // Generated from `System.Xml.XPath.XmlCaseOrder` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlCaseOrder : int { LowerFirst = 2, @@ -2725,14 +2552,12 @@ namespace System UpperFirst = 1, } - // Generated from `System.Xml.XPath.XmlDataType` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlDataType : int { Number = 2, Text = 1, } - // Generated from `System.Xml.XPath.XmlSortOrder` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XmlSortOrder : int { Ascending = 1, @@ -2742,7 +2567,6 @@ namespace System } namespace Xsl { - // Generated from `System.Xml.Xsl.IXsltContextFunction` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXsltContextFunction { System.Xml.XPath.XPathResultType[] ArgTypes { get; } @@ -2752,7 +2576,6 @@ namespace System System.Xml.XPath.XPathResultType ReturnType { get; } } - // Generated from `System.Xml.Xsl.IXsltContextVariable` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXsltContextVariable { object Evaluate(System.Xml.Xsl.XsltContext xsltContext); @@ -2761,7 +2584,6 @@ namespace System System.Xml.XPath.XPathResultType VariableType { get; } } - // Generated from `System.Xml.Xsl.XslCompiledTransform` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XslCompiledTransform { public void Load(System.Xml.XPath.IXPathNavigable stylesheet) => throw null; @@ -2792,7 +2614,6 @@ namespace System public XslCompiledTransform(bool enableDebug) => throw null; } - // Generated from `System.Xml.Xsl.XslTransform` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XslTransform { public void Load(System.Xml.XPath.IXPathNavigable stylesheet) => throw null; @@ -2825,7 +2646,6 @@ namespace System public XslTransform() => throw null; } - // Generated from `System.Xml.Xsl.XsltArgumentList` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XsltArgumentList { public void AddExtensionObject(string namespaceUri, object extension) => throw null; @@ -2839,7 +2659,6 @@ namespace System public event System.Xml.Xsl.XsltMessageEncounteredEventHandler XsltMessageEncountered; } - // Generated from `System.Xml.Xsl.XsltCompileException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XsltCompileException : System.Xml.Xsl.XsltException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -2850,7 +2669,6 @@ namespace System public XsltCompileException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Xml.Xsl.XsltContext` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XsltContext : System.Xml.XmlNamespaceManager { public abstract int CompareDocument(string baseUri, string nextbaseUri); @@ -2862,7 +2680,6 @@ namespace System protected XsltContext(System.Xml.NameTable table) : base(default(System.Xml.XmlNameTable)) => throw null; } - // Generated from `System.Xml.Xsl.XsltException` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XsltException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; @@ -2876,17 +2693,14 @@ namespace System public XsltException(string message, System.Exception innerException) => throw null; } - // Generated from `System.Xml.Xsl.XsltMessageEncounteredEventArgs` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XsltMessageEncounteredEventArgs : System.EventArgs { public abstract string Message { get; } protected XsltMessageEncounteredEventArgs() => throw null; } - // Generated from `System.Xml.Xsl.XsltMessageEncounteredEventHandler` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XsltMessageEncounteredEventHandler(object sender, System.Xml.Xsl.XsltMessageEncounteredEventArgs e); - // Generated from `System.Xml.Xsl.XsltSettings` in `System.Xml.ReaderWriter, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XsltSettings { public static System.Xml.Xsl.XsltSettings Default { get => throw null; } diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XDocument.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XDocument.cs index 25d2e33c43d..d060d6c424a 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XDocument.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XDocument.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Xml.XDocument, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Linq { - // Generated from `System.Xml.Linq.Extensions` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Extensions { public static System.Collections.Generic.IEnumerable Ancestors(this System.Collections.Generic.IEnumerable source) where T : System.Xml.Linq.XNode => throw null; @@ -29,7 +29,6 @@ namespace System public static void Remove(this System.Collections.Generic.IEnumerable source) where T : System.Xml.Linq.XNode => throw null; } - // Generated from `System.Xml.Linq.LoadOptions` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum LoadOptions : int { @@ -39,7 +38,6 @@ namespace System SetLineInfo = 4, } - // Generated from `System.Xml.Linq.ReaderOptions` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum ReaderOptions : int { @@ -47,7 +45,6 @@ namespace System OmitDuplicateNamespaces = 1, } - // Generated from `System.Xml.Linq.SaveOptions` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum SaveOptions : int { @@ -56,7 +53,6 @@ namespace System OmitDuplicateNamespaces = 2, } - // Generated from `System.Xml.Linq.XAttribute` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XAttribute : System.Xml.Linq.XObject { public static System.Collections.Generic.IEnumerable EmptySequence { get => throw null; } @@ -98,7 +94,6 @@ namespace System public static explicit operator string(System.Xml.Linq.XAttribute attribute) => throw null; } - // Generated from `System.Xml.Linq.XCData` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XCData : System.Xml.Linq.XText { public override System.Xml.XmlNodeType NodeType { get => throw null; } @@ -108,7 +103,6 @@ namespace System public XCData(string value) : base(default(System.Xml.Linq.XText)) => throw null; } - // Generated from `System.Xml.Linq.XComment` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XComment : System.Xml.Linq.XNode { public override System.Xml.XmlNodeType NodeType { get => throw null; } @@ -119,7 +113,6 @@ namespace System public XComment(string value) => throw null; } - // Generated from `System.Xml.Linq.XContainer` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XContainer : System.Xml.Linq.XNode { public void Add(object content) => throw null; @@ -142,7 +135,6 @@ namespace System internal XContainer() => throw null; } - // Generated from `System.Xml.Linq.XDeclaration` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XDeclaration { public string Encoding { get => throw null; set => throw null; } @@ -153,7 +145,6 @@ namespace System public XDeclaration(string version, string encoding, string standalone) => throw null; } - // Generated from `System.Xml.Linq.XDocument` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XDocument : System.Xml.Linq.XContainer { public System.Xml.Linq.XDeclaration Declaration { get => throw null; set => throw null; } @@ -191,7 +182,6 @@ namespace System public XDocument(params object[] content) => throw null; } - // Generated from `System.Xml.Linq.XDocumentType` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XDocumentType : System.Xml.Linq.XNode { public string InternalSubset { get => throw null; set => throw null; } @@ -205,7 +195,6 @@ namespace System public XDocumentType(string name, string publicId, string systemId, string internalSubset) => throw null; } - // Generated from `System.Xml.Linq.XElement` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XElement : System.Xml.Linq.XContainer, System.Xml.Serialization.IXmlSerializable { public System.Collections.Generic.IEnumerable AncestorsAndSelf() => throw null; @@ -297,7 +286,6 @@ namespace System public static explicit operator string(System.Xml.Linq.XElement element) => throw null; } - // Generated from `System.Xml.Linq.XName` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XName : System.IEquatable, System.Runtime.Serialization.ISerializable { public static bool operator !=(System.Xml.Linq.XName left, System.Xml.Linq.XName right) => throw null; @@ -315,7 +303,6 @@ namespace System public static implicit operator System.Xml.Linq.XName(string expandedName) => throw null; } - // Generated from `System.Xml.Linq.XNamespace` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XNamespace { public static bool operator !=(System.Xml.Linq.XNamespace left, System.Xml.Linq.XNamespace right) => throw null; @@ -333,7 +320,6 @@ namespace System public static implicit operator System.Xml.Linq.XNamespace(string namespaceName) => throw null; } - // Generated from `System.Xml.Linq.XNode` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XNode : System.Xml.Linq.XObject { public void AddAfterSelf(object content) => throw null; @@ -370,7 +356,6 @@ namespace System internal XNode() => throw null; } - // Generated from `System.Xml.Linq.XNodeDocumentOrderComparer` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XNodeDocumentOrderComparer : System.Collections.Generic.IComparer, System.Collections.IComparer { public int Compare(System.Xml.Linq.XNode x, System.Xml.Linq.XNode y) => throw null; @@ -378,7 +363,6 @@ namespace System public XNodeDocumentOrderComparer() => throw null; } - // Generated from `System.Xml.Linq.XNodeEqualityComparer` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XNodeEqualityComparer : System.Collections.Generic.IEqualityComparer, System.Collections.IEqualityComparer { public bool Equals(System.Xml.Linq.XNode x, System.Xml.Linq.XNode y) => throw null; @@ -388,7 +372,6 @@ namespace System public XNodeEqualityComparer() => throw null; } - // Generated from `System.Xml.Linq.XObject` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XObject : System.Xml.IXmlLineInfo { public void AddAnnotation(object annotation) => throw null; @@ -410,7 +393,6 @@ namespace System internal XObject() => throw null; } - // Generated from `System.Xml.Linq.XObjectChange` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public enum XObjectChange : int { Add = 0, @@ -419,7 +401,6 @@ namespace System Value = 3, } - // Generated from `System.Xml.Linq.XObjectChangeEventArgs` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XObjectChangeEventArgs : System.EventArgs { public static System.Xml.Linq.XObjectChangeEventArgs Add; @@ -430,7 +411,6 @@ namespace System public XObjectChangeEventArgs(System.Xml.Linq.XObjectChange objectChange) => throw null; } - // Generated from `System.Xml.Linq.XProcessingInstruction` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XProcessingInstruction : System.Xml.Linq.XNode { public string Data { get => throw null; set => throw null; } @@ -442,7 +422,6 @@ namespace System public XProcessingInstruction(string target, string data) => throw null; } - // Generated from `System.Xml.Linq.XStreamingElement` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XStreamingElement { public void Add(object content) => throw null; @@ -463,7 +442,6 @@ namespace System public XStreamingElement(System.Xml.Linq.XName name, params object[] content) => throw null; } - // Generated from `System.Xml.Linq.XText` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XText : System.Xml.Linq.XNode { public override System.Xml.XmlNodeType NodeType { get => throw null; } @@ -477,7 +455,6 @@ namespace System } namespace Schema { - // Generated from `System.Xml.Schema.Extensions` in `System.Xml.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Extensions { public static System.Xml.Schema.IXmlSchemaInfo GetSchemaInfo(this System.Xml.Linq.XAttribute source) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.XDocument.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.XDocument.cs index ee8b0ec0f95..08eb0a49e18 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.XDocument.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.XDocument.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Xml.XPath.XDocument, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace XPath { - // Generated from `System.Xml.XPath.Extensions` in `System.Xml.XPath.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class Extensions { public static System.Xml.XPath.XPathNavigator CreateNavigator(this System.Xml.Linq.XNode node) => throw null; @@ -19,7 +19,6 @@ namespace System public static System.Collections.Generic.IEnumerable XPathSelectElements(this System.Xml.Linq.XNode node, string expression, System.Xml.IXmlNamespaceResolver resolver) => throw null; } - // Generated from `System.Xml.XPath.XDocumentExtensions` in `System.Xml.XPath.XDocument, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public static class XDocumentExtensions { public static System.Xml.XPath.IXPathNavigable ToXPathNavigable(this System.Xml.Linq.XNode node) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.cs index f92e22f5228..ec7ea32f149 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XPath.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Xml.XPath, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace XPath { - // Generated from `System.Xml.XPath.XPathDocument` in `System.Xml.XPath, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XPathDocument : System.Xml.XPath.IXPathNavigable { public System.Xml.XPath.XPathNavigator CreateNavigator() => throw null; @@ -18,7 +18,6 @@ namespace System public XPathDocument(string uri, System.Xml.XmlSpace space) => throw null; } - // Generated from `System.Xml.XPath.XPathException` in `System.Xml.XPath, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XPathException : System.SystemException { public override void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) => throw null; diff --git a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XmlSerializer.cs b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XmlSerializer.cs index 05ffee9e018..b811f7d0a4d 100644 --- a/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XmlSerializer.cs +++ b/csharp/ql/test/resources/stubs/_frameworks/Microsoft.NETCore.App/System.Xml.XmlSerializer.cs @@ -1,4 +1,5 @@ // This file contains auto-generated code. +// Generated from `System.Xml.XmlSerializer, Version=7.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`. namespace System { @@ -6,7 +7,6 @@ namespace System { namespace Serialization { - // Generated from `System.Xml.Serialization.CodeGenerationOptions` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum CodeGenerationOptions : int { @@ -18,7 +18,6 @@ namespace System None = 0, } - // Generated from `System.Xml.Serialization.CodeIdentifier` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CodeIdentifier { public CodeIdentifier() => throw null; @@ -27,7 +26,6 @@ namespace System public static string MakeValid(string identifier) => throw null; } - // Generated from `System.Xml.Serialization.CodeIdentifiers` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class CodeIdentifiers { public void Add(string identifier, object value) => throw null; @@ -45,14 +43,12 @@ namespace System public bool UseCamelCasing { get => throw null; set => throw null; } } - // Generated from `System.Xml.Serialization.IXmlTextParser` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public interface IXmlTextParser { bool Normalized { get; set; } System.Xml.WhitespaceHandling WhitespaceHandling { get; set; } } - // Generated from `System.Xml.Serialization.ImportContext` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class ImportContext { public ImportContext(System.Xml.Serialization.CodeIdentifiers identifiers, bool shareTypes) => throw null; @@ -61,13 +57,11 @@ namespace System public System.Collections.Specialized.StringCollection Warnings { get => throw null; } } - // Generated from `System.Xml.Serialization.SchemaImporter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class SchemaImporter { internal SchemaImporter() => throw null; } - // Generated from `System.Xml.Serialization.SoapAttributeAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapAttributeAttribute : System.Attribute { public string AttributeName { get => throw null; set => throw null; } @@ -77,7 +71,6 @@ namespace System public SoapAttributeAttribute(string attributeName) => throw null; } - // Generated from `System.Xml.Serialization.SoapAttributeOverrides` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapAttributeOverrides { public void Add(System.Type type, System.Xml.Serialization.SoapAttributes attributes) => throw null; @@ -87,7 +80,6 @@ namespace System public SoapAttributeOverrides() => throw null; } - // Generated from `System.Xml.Serialization.SoapAttributes` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapAttributes { public System.Xml.Serialization.SoapAttributeAttribute SoapAttribute { get => throw null; set => throw null; } @@ -100,7 +92,6 @@ namespace System public System.Xml.Serialization.SoapTypeAttribute SoapType { get => throw null; set => throw null; } } - // Generated from `System.Xml.Serialization.SoapElementAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapElementAttribute : System.Attribute { public string DataType { get => throw null; set => throw null; } @@ -110,7 +101,6 @@ namespace System public SoapElementAttribute(string elementName) => throw null; } - // Generated from `System.Xml.Serialization.SoapEnumAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapEnumAttribute : System.Attribute { public string Name { get => throw null; set => throw null; } @@ -118,20 +108,17 @@ namespace System public SoapEnumAttribute(string name) => throw null; } - // Generated from `System.Xml.Serialization.SoapIgnoreAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapIgnoreAttribute : System.Attribute { public SoapIgnoreAttribute() => throw null; } - // Generated from `System.Xml.Serialization.SoapIncludeAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapIncludeAttribute : System.Attribute { public SoapIncludeAttribute(System.Type type) => throw null; public System.Type Type { get => throw null; set => throw null; } } - // Generated from `System.Xml.Serialization.SoapReflectionImporter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapReflectionImporter { public System.Xml.Serialization.XmlMembersMapping ImportMembersMapping(string elementName, string ns, System.Xml.Serialization.XmlReflectionMember[] members) => throw null; @@ -148,7 +135,6 @@ namespace System public SoapReflectionImporter(string defaultNamespace) => throw null; } - // Generated from `System.Xml.Serialization.SoapSchemaMember` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapSchemaMember { public string MemberName { get => throw null; set => throw null; } @@ -156,7 +142,6 @@ namespace System public SoapSchemaMember() => throw null; } - // Generated from `System.Xml.Serialization.SoapTypeAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class SoapTypeAttribute : System.Attribute { public bool IncludeInSchema { get => throw null; set => throw null; } @@ -167,7 +152,6 @@ namespace System public string TypeName { get => throw null; set => throw null; } } - // Generated from `System.Xml.Serialization.UnreferencedObjectEventArgs` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class UnreferencedObjectEventArgs : System.EventArgs { public string UnreferencedId { get => throw null; } @@ -175,10 +159,8 @@ namespace System public UnreferencedObjectEventArgs(object o, string id) => throw null; } - // Generated from `System.Xml.Serialization.UnreferencedObjectEventHandler` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void UnreferencedObjectEventHandler(object sender, System.Xml.Serialization.UnreferencedObjectEventArgs e); - // Generated from `System.Xml.Serialization.XmlAnyElementAttributes` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAnyElementAttributes : System.Collections.CollectionBase { public int Add(System.Xml.Serialization.XmlAnyElementAttribute attribute) => throw null; @@ -191,7 +173,6 @@ namespace System public XmlAnyElementAttributes() => throw null; } - // Generated from `System.Xml.Serialization.XmlArrayAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlArrayAttribute : System.Attribute { public string ElementName { get => throw null; set => throw null; } @@ -203,7 +184,6 @@ namespace System public XmlArrayAttribute(string elementName) => throw null; } - // Generated from `System.Xml.Serialization.XmlArrayItemAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlArrayItemAttribute : System.Attribute { public string DataType { get => throw null; set => throw null; } @@ -219,7 +199,6 @@ namespace System public XmlArrayItemAttribute(string elementName, System.Type type) => throw null; } - // Generated from `System.Xml.Serialization.XmlArrayItemAttributes` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlArrayItemAttributes : System.Collections.CollectionBase { public int Add(System.Xml.Serialization.XmlArrayItemAttribute attribute) => throw null; @@ -232,7 +211,6 @@ namespace System public XmlArrayItemAttributes() => throw null; } - // Generated from `System.Xml.Serialization.XmlAttributeEventArgs` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttributeEventArgs : System.EventArgs { public System.Xml.XmlAttribute Attr { get => throw null; } @@ -242,10 +220,8 @@ namespace System public object ObjectBeingDeserialized { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlAttributeEventHandler` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlAttributeEventHandler(object sender, System.Xml.Serialization.XmlAttributeEventArgs e); - // Generated from `System.Xml.Serialization.XmlAttributeOverrides` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttributeOverrides { public void Add(System.Type type, System.Xml.Serialization.XmlAttributes attributes) => throw null; @@ -255,7 +231,6 @@ namespace System public XmlAttributeOverrides() => throw null; } - // Generated from `System.Xml.Serialization.XmlAttributes` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlAttributes { public System.Xml.Serialization.XmlAnyAttributeAttribute XmlAnyAttribute { get => throw null; set => throw null; } @@ -276,7 +251,6 @@ namespace System public bool Xmlns { get => throw null; set => throw null; } } - // Generated from `System.Xml.Serialization.XmlChoiceIdentifierAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlChoiceIdentifierAttribute : System.Attribute { public string MemberName { get => throw null; set => throw null; } @@ -284,7 +258,6 @@ namespace System public XmlChoiceIdentifierAttribute(string name) => throw null; } - // Generated from `System.Xml.Serialization.XmlDeserializationEvents` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public struct XmlDeserializationEvents { public System.Xml.Serialization.XmlAttributeEventHandler OnUnknownAttribute { get => throw null; set => throw null; } @@ -294,7 +267,6 @@ namespace System // Stub generator skipped constructor } - // Generated from `System.Xml.Serialization.XmlElementAttributes` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlElementAttributes : System.Collections.CollectionBase { public int Add(System.Xml.Serialization.XmlElementAttribute attribute) => throw null; @@ -307,7 +279,6 @@ namespace System public XmlElementAttributes() => throw null; } - // Generated from `System.Xml.Serialization.XmlElementEventArgs` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlElementEventArgs : System.EventArgs { public System.Xml.XmlElement Element { get => throw null; } @@ -317,17 +288,14 @@ namespace System public object ObjectBeingDeserialized { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlElementEventHandler` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlElementEventHandler(object sender, System.Xml.Serialization.XmlElementEventArgs e); - // Generated from `System.Xml.Serialization.XmlIncludeAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlIncludeAttribute : System.Attribute { public System.Type Type { get => throw null; set => throw null; } public XmlIncludeAttribute(System.Type type) => throw null; } - // Generated from `System.Xml.Serialization.XmlMapping` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlMapping { public string ElementName { get => throw null; } @@ -337,7 +305,6 @@ namespace System public string XsdElementName { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlMappingAccess` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` [System.Flags] public enum XmlMappingAccess : int { @@ -346,7 +313,6 @@ namespace System Write = 2, } - // Generated from `System.Xml.Serialization.XmlMemberMapping` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlMemberMapping { public bool Any { get => throw null; } @@ -360,7 +326,6 @@ namespace System public string XsdElementName { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlMembersMapping` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlMembersMapping : System.Xml.Serialization.XmlMapping { public int Count { get => throw null; } @@ -369,7 +334,6 @@ namespace System public string TypeNamespace { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlNodeEventArgs` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlNodeEventArgs : System.EventArgs { public int LineNumber { get => throw null; } @@ -382,10 +346,8 @@ namespace System public string Text { get => throw null; } } - // Generated from `System.Xml.Serialization.XmlNodeEventHandler` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlNodeEventHandler(object sender, System.Xml.Serialization.XmlNodeEventArgs e); - // Generated from `System.Xml.Serialization.XmlReflectionImporter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlReflectionImporter { public System.Xml.Serialization.XmlMembersMapping ImportMembersMapping(string elementName, string ns, System.Xml.Serialization.XmlReflectionMember[] members, bool hasWrapperElement) => throw null; @@ -404,7 +366,6 @@ namespace System public XmlReflectionImporter(string defaultNamespace) => throw null; } - // Generated from `System.Xml.Serialization.XmlReflectionMember` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlReflectionMember { public bool IsReturnValue { get => throw null; set => throw null; } @@ -416,7 +377,6 @@ namespace System public XmlReflectionMember() => throw null; } - // Generated from `System.Xml.Serialization.XmlSchemaEnumerator` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaEnumerator : System.Collections.Generic.IEnumerator, System.Collections.IEnumerator, System.IDisposable { public System.Xml.Schema.XmlSchema Current { get => throw null; } @@ -427,7 +387,6 @@ namespace System public XmlSchemaEnumerator(System.Xml.Serialization.XmlSchemas list) => throw null; } - // Generated from `System.Xml.Serialization.XmlSchemaExporter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaExporter { public string ExportAnyType(System.Xml.Serialization.XmlMembersMapping members) => throw null; @@ -439,7 +398,6 @@ namespace System public XmlSchemaExporter(System.Xml.Serialization.XmlSchemas schemas) => throw null; } - // Generated from `System.Xml.Serialization.XmlSchemaImporter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemaImporter : System.Xml.Serialization.SchemaImporter { public System.Xml.Serialization.XmlMembersMapping ImportAnyType(System.Xml.XmlQualifiedName typeName, string elementName) => throw null; @@ -457,7 +415,6 @@ namespace System public XmlSchemaImporter(System.Xml.Serialization.XmlSchemas schemas, System.Xml.Serialization.CodeIdentifiers typeIdentifiers) => throw null; } - // Generated from `System.Xml.Serialization.XmlSchemas` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSchemas : System.Collections.CollectionBase, System.Collections.Generic.IEnumerable, System.Collections.IEnumerable { public int Add(System.Xml.Schema.XmlSchema schema) => throw null; @@ -485,25 +442,19 @@ namespace System public XmlSchemas() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializationCollectionFixupCallback` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlSerializationCollectionFixupCallback(object collection, object collectionItems); - // Generated from `System.Xml.Serialization.XmlSerializationFixupCallback` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlSerializationFixupCallback(object fixup); - // Generated from `System.Xml.Serialization.XmlSerializationGeneratedCode` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSerializationGeneratedCode { protected XmlSerializationGeneratedCode() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializationReadCallback` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate object XmlSerializationReadCallback(); - // Generated from `System.Xml.Serialization.XmlSerializationReader` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSerializationReader : System.Xml.Serialization.XmlSerializationGeneratedCode { - // Generated from `System.Xml.Serialization.XmlSerializationReader+CollectionFixup` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected class CollectionFixup { public System.Xml.Serialization.XmlSerializationCollectionFixupCallback Callback { get => throw null; } @@ -513,7 +464,6 @@ namespace System } - // Generated from `System.Xml.Serialization.XmlSerializationReader+Fixup` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` protected class Fixup { public System.Xml.Serialization.XmlSerializationFixupCallback Callback { get => throw null; } @@ -603,10 +553,8 @@ namespace System protected XmlSerializationReader() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializationWriteCallback` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public delegate void XmlSerializationWriteCallback(object o); - // Generated from `System.Xml.Serialization.XmlSerializationWriter` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSerializationWriter : System.Xml.Serialization.XmlSerializationGeneratedCode { protected void AddWriteCallback(System.Type type, string typeName, string typeNs, System.Xml.Serialization.XmlSerializationWriteCallback callback) => throw null; @@ -706,7 +654,6 @@ namespace System protected XmlSerializationWriter() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializer` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSerializer { public virtual bool CanDeserialize(System.Xml.XmlReader xmlReader) => throw null; @@ -748,7 +695,6 @@ namespace System public XmlSerializer(System.Xml.Serialization.XmlTypeMapping xmlTypeMapping) => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializerAssemblyAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSerializerAssemblyAttribute : System.Attribute { public string AssemblyName { get => throw null; set => throw null; } @@ -758,7 +704,6 @@ namespace System public XmlSerializerAssemblyAttribute(string assemblyName, string codeBase) => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializerFactory` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSerializerFactory { public System.Xml.Serialization.XmlSerializer CreateSerializer(System.Type type) => throw null; @@ -772,7 +717,6 @@ namespace System public XmlSerializerFactory() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializerImplementation` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public abstract class XmlSerializerImplementation { public virtual bool CanSerialize(System.Type type) => throw null; @@ -785,7 +729,6 @@ namespace System protected XmlSerializerImplementation() => throw null; } - // Generated from `System.Xml.Serialization.XmlSerializerVersionAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlSerializerVersionAttribute : System.Attribute { public string Namespace { get => throw null; set => throw null; } @@ -796,7 +739,6 @@ namespace System public XmlSerializerVersionAttribute(System.Type type) => throw null; } - // Generated from `System.Xml.Serialization.XmlTypeAttribute` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlTypeAttribute : System.Attribute { public bool AnonymousType { get => throw null; set => throw null; } @@ -807,7 +749,6 @@ namespace System public XmlTypeAttribute(string typeName) => throw null; } - // Generated from `System.Xml.Serialization.XmlTypeMapping` in `System.Xml.XmlSerializer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a` public class XmlTypeMapping : System.Xml.Serialization.XmlMapping { public string TypeFullName { get => throw null; } diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp-new.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp-new.rst new file mode 100644 index 00000000000..5c3d81e3f42 --- /dev/null +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp-new.rst @@ -0,0 +1,433 @@ +.. _analyzing-data-flow-in-cpp-new: + +.. pull-quote:: Note + + The data flow library described here is available from CodeQL 2.12.5 onwards. See :ref:`here ` for the library available in earlier versions. + +Analyzing data flow in C and C++ (New) +====================================== + +You can use data flow analysis to track the flow of potentially malicious or insecure data that can cause vulnerabilities in your codebase. + +About data flow +--------------- + +Data flow analysis computes the possible values that a variable can hold at various points in a program, determining how those values propagate through the program, and where they are used. In CodeQL, you can model both local data flow and global data flow. For a more general introduction to modeling data flow, see ":ref:`About data flow analysis `." + +Local data flow +--------------- + +Local data flow is data flow within a single function. Local data flow is usually easier, faster, and more precise than global data flow, and is sufficient for many queries. + +Using local data flow +~~~~~~~~~~~~~~~~~~~~~ + +The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``, ``IndirectExprNode``) and parameter nodes (``ParameterNode``, ``IndirectParameterNode``). The indirect nodes represent expressions or parameters after a fixed number of pointer dereferences. + +It is possible to map between data flow nodes and expressions or parameters using the member predicates ``asExpr``, ``asIndirectExpr``, and ``asParameter``: + +.. code-block:: ql + + class Node { + /** + * Gets the expression corresponding to this node, if any. + */ + Expr asExpr() { ... } + + /** + * Gets the expression corresponding to a node that is obtained after dereferencing + * the expression `index` times, if any. + */ + Expr asIndirectExpr(int index) { ... } + + /** + * Gets the parameter corresponding to this node, if any. + */ + Parameter asParameter() { ... } + + /** + * Gets the parameter corresponding to a node that is obtained after dereferencing + * the parameter `index` times. + */ + Parameter asParameter(int index) { ... } + + ... + } + +The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localFlow``, which is equivalent to ``localFlowStep*``. + +For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows, where ``nodeFrom`` and ``nodeTo`` are of type ``DataFlow::Node``: + +.. code-block:: ql + + nodeFrom.asParameter() = source and + nodeTo.asExpr() = sink and + DataFlow::localFlow(nodeFrom, nodeTo) + +Using local taint tracking +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Local taint tracking extends local data flow by including non-value-preserving flow steps. For example: + +.. code-block:: cpp + + int i = tainted_user_input(); + some_big_struct *array = malloc(i * sizeof(some_big_struct)); + +In this case, the argument to ``malloc`` is tainted. + +The local taint tracking library is in the module ``TaintTracking``. Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or through the predefined recursive predicate ``localTaint``, which is equivalent to ``localTaintStep*``. + +For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows, where ``nodeFrom`` and ``nodeTo`` are of type ``DataFlow::Node``: + +.. code-block:: ql + + nodeFrom.asParameter() = source and + nodeTo.asExpr() = sink and + TaintTracking::localTaint(nodeFrom, nodeTo) + +Examples +~~~~~~~~ + +The following query finds the filename passed to ``fopen``: + +.. code-block:: ql + + import cpp + + from Function fopen, FunctionCall fc + where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen + select fc.getArgument(0) + +However, this will only give the expression in the argument, not the values which could be passed to it. Instead we can use local data flow to find all expressions that flow into the argument, where we use ``asIndirectExpr(1)``. This is because we are interested in the value of the string passed to `fopen`, not the pointer pointing to it: + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + from Function fopen, FunctionCall fc, Expr src, DataFlow::Node source, DataFlow::Node sink + where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen and + source.asIndirectExpr(1) = src and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) + select src + +Then we can vary the source and, for example, use the parameter of a function. The following query finds where a parameter is used when opening a file: + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + from Function fopen, FunctionCall fc, Parameter p, DataFlow::Node source, DataFlow::Node sink + where + fopen.hasGlobalName("fopen") and + fc.getTarget() = fopen and + source.asParameter(1) = p and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) + select p + +The following example finds calls to formatting functions where the format string is not hard-coded. + +.. code-block:: ql + + import semmle.code.cpp.dataflow.new.DataFlow + import semmle.code.cpp.commons.Printf + + from FormattingFunction format, FunctionCall call, Expr formatString, DataFlow::Node sink + where + call.getTarget() = format and + call.getArgument(format.getFormatParameterIndex()) = formatString and + sink.asIndirectExpr(1) = formatString and + not exists(DataFlow::Node source | + DataFlow::localFlow(source, sink) and + source.asIndirectExpr(1) instanceof StringLiteral + ) + select call, "Argument to " + format.getQualifiedName() + " isn't hard-coded." + +Exercises +~~~~~~~~~ + +Exercise 1: Write a query that finds all hard-coded strings used to create a ``host_ent`` via ``gethostbyname``, using local data flow. (`Answer <#exercise-1>`__) + +Global data flow +---------------- + +Global data flow tracks data flow throughout the entire program, and is therefore more powerful than local data flow. However, global data flow is less precise than local data flow, and the analysis typically requires significantly more time and memory to perform. + +.. pull-quote:: Note + + .. include:: ../reusables/path-problem.rst + +Using global data flow +~~~~~~~~~~~~~~~~~~~~~~ + +The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows: + +.. code-block:: ql + + import semmle.code.cpp.dataflow.new.DataFlow + + class MyDataFlowConfiguration extends DataFlow::Configuration { + MyDataFlowConfiguration() { this = "MyDataFlowConfiguration" } + + override predicate isSource(DataFlow::Node source) { + ... + } + + override predicate isSink(DataFlow::Node sink) { + ... + } + } + +The following predicates are defined in the configuration: + +- ``isSource``—defines where data may flow from +- ``isSink``—defines where data may flow to +- ``isBarrier``—optional, restricts the data flow +- ``isBarrierGuard``—optional, restricts the data flow +- ``isAdditionalFlowStep``—optional, adds additional flow steps + +The characteristic predicate ``MyDataFlowConfiguration()`` defines the name of the configuration, so ``"MyDataFlowConfiguration"`` should be replaced by the name of your class. + +The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``: + +.. code-block:: ql + + from MyDataFlowConfiguration dataflow, DataFlow::Node source, DataFlow::Node sink + where dataflow.hasFlow(source, sink) + select source, "Data flow to $@.", sink, sink.toString() + +Using global taint tracking +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Global taint tracking is to global data flow as local taint tracking is to local data flow. That is, global taint tracking extends global data flow with additional non-value-preserving steps. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows: + +.. code-block:: ql + + import semmle.code.cpp.dataflow.new.TaintTracking + + class MyTaintTrackingConfiguration extends TaintTracking::Configuration { + MyTaintTrackingConfiguration() { this = "MyTaintTrackingConfiguration" } + + override predicate isSource(DataFlow::Node source) { + ... + } + + override predicate isSink(DataFlow::Node sink) { + ... + } + } + +The following predicates are defined in the configuration: + +- ``isSource``—defines where taint may flow from +- ``isSink``—defines where taint may flow to +- ``isSanitizer``—optional, restricts the taint flow +- ``isSanitizerGuard``—optional, restricts the taint flow +- ``isAdditionalTaintStep``—optional, adds additional taint steps + +Similar to global data flow, the characteristic predicate ``MyTaintTrackingConfiguration()`` defines the unique name of the configuration, so ``"MyTaintTrackingConfiguration"`` should be replaced by the name of your class. + +The taint tracking analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``. + +Examples +~~~~~~~~ + +The following data flow configuration tracks data flow from environment variables to opening files in a Unix-like environment: + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + class EnvironmentToFileConfiguration extends DataFlow::Configuration { + EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" } + + override predicate isSource(DataFlow::Node source) { + exists(Function getenv | + source.asIndirectExpr(1).(FunctionCall).getTarget() = getenv and + getenv.hasGlobalName("getenv") + ) + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasGlobalName("fopen") + ) + } + } + + from + Expr getenv, Expr fopen, EnvironmentToFileConfiguration config, DataFlow::Node source, + DataFlow::Node sink + where + source.asIndirectExpr(1) = getenv and + sink.asIndirectExpr(1) = fopen and + config.hasFlow(source, sink) + select fopen, "This 'fopen' uses data from $@.", getenv, "call to 'getenv'" + +The following taint-tracking configuration tracks data from a call to ``ntohl`` to an array index operation. It uses the ``Guards`` library to recognize expressions that have been bounds-checked, and defines ``isSanitizer`` to prevent taint from propagating through them. It also uses ``isAdditionalTaintStep`` to add flow from loop bounds to loop indexes. + +.. code-block:: ql + + import cpp + import semmle.code.cpp.controlflow.Guards + import semmle.code.cpp.dataflow.new.TaintTracking + + class NetworkToBufferSizeConfiguration extends TaintTracking::Configuration { + NetworkToBufferSizeConfiguration() { this = "NetworkToBufferSizeConfiguration" } + + override predicate isSource(DataFlow::Node node) { + node.asExpr().(FunctionCall).getTarget().hasGlobalName("ntohl") + } + + override predicate isSink(DataFlow::Node node) { + exists(ArrayExpr ae | node.asExpr() = ae.getArrayOffset()) + } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(Loop loop, LoopCounter lc | + loop = lc.getALoop() and + loop.getControllingExpr().(RelationalOperation).getGreaterOperand() = pred.asExpr() + | + succ.asExpr() = lc.getVariableAccessInLoop(loop) + ) + } + + override predicate isSanitizer(DataFlow::Node node) { + exists(GuardCondition gc, Variable v | + gc.getAChild*() = v.getAnAccess() and + node.asExpr() = v.getAnAccess() and + gc.controls(node.asExpr().getBasicBlock(), _) and + not exists(Loop loop | loop.getControllingExpr() = gc) + ) + } + } + + from DataFlow::Node ntohl, DataFlow::Node offset, NetworkToBufferSizeConfiguration conf + where conf.hasFlow(ntohl, offset) + select offset, "This array offset may be influenced by $@.", ntohl, + "converted data from the network" + +Exercises +~~~~~~~~~ + +Exercise 2: Write a query that finds all hard-coded strings used to create a ``host_ent`` via ``gethostbyname``, using global data flow. (`Answer <#exercise-2>`__) + +Exercise 3: Write a class that represents flow sources from ``getenv``. (`Answer <#exercise-3>`__) + +Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flows from ``getenv`` to ``gethostbyname``. (`Answer <#exercise-4>`__) + +Answers +------- + +Exercise 1 +~~~~~~~~~~ + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + from StringLiteral sl, FunctionCall fc, DataFlow::Node source, DataFlow::Node sink + where + fc.getTarget().hasName("gethostbyname") and + source.asIndirectExpr(1) = sl and + sink.asIndirectExpr(1) = fc.getArgument(0) and + DataFlow::localFlow(source, sink) + select sl, fc + +Exercise 2 +~~~~~~~~~~ + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + class LiteralToGethostbynameConfiguration extends DataFlow::Configuration { + LiteralToGethostbynameConfiguration() { this = "LiteralToGethostbynameConfiguration" } + + override predicate isSource(DataFlow::Node source) { + source.asIndirectExpr(1) instanceof StringLiteral + } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasName("gethostbyname") + ) + } + } + + from + StringLiteral sl, FunctionCall fc, LiteralToGethostbynameConfiguration cfg, DataFlow::Node source, + DataFlow::Node sink + where + source.asIndirectExpr(1) = sl and + sink.asIndirectExpr(1) = fc.getArgument(0) and + cfg.hasFlow(source, sink) + select sl, fc + +Exercise 3 +~~~~~~~~~~ + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + class GetenvSource extends DataFlow::Node { + GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") } + } + +Exercise 4 +~~~~~~~~~~ + +.. code-block:: ql + + import cpp + import semmle.code.cpp.dataflow.new.DataFlow + + class GetenvSource extends DataFlow::Node { + GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") } + } + + class GetenvToGethostbynameConfiguration extends DataFlow::Configuration { + GetenvToGethostbynameConfiguration() { this = "GetenvToGethostbynameConfiguration" } + + override predicate isSource(DataFlow::Node source) { source instanceof GetenvSource } + + override predicate isSink(DataFlow::Node sink) { + exists(FunctionCall fc | + sink.asIndirectExpr(1) = fc.getArgument(0) and + fc.getTarget().hasName("gethostbyname") + ) + } + } + + from + Expr getenv, FunctionCall fc, GetenvToGethostbynameConfiguration cfg, DataFlow::Node source, + DataFlow::Node sink + where + source.asIndirectExpr(1) = getenv and + sink.asIndirectExpr(1) = fc.getArgument(0) and + cfg.hasFlow(source, sink) + select getenv, fc + +Further reading +--------------- + +- ":ref:`Exploring data flow with path queries `" + + +.. include:: ../reusables/cpp-further-reading.rst +.. include:: ../reusables/codeql-ref-tools-further-reading.rst \ No newline at end of file diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst index 815425a425a..7cfe15cb64c 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst @@ -1,5 +1,9 @@ .. _analyzing-data-flow-in-cpp: +.. pull-quote:: Note + + The data flow library described here will be deprecated in the near future. For the replacement library, which is available from CodeQL 2.12.5 onwards, see :ref:`here `. + Analyzing data flow in C and C++ ================================ @@ -84,7 +88,7 @@ The following query finds the filename passed to ``fopen``. import cpp from Function fopen, FunctionCall fc - where fopen.hasQualifiedName("fopen") + where fopen.hasGlobalName("fopen") and fc.getTarget() = fopen select fc.getArgument(0) @@ -96,12 +100,12 @@ Unfortunately, this will only give the expression in the argument, not the value import semmle.code.cpp.dataflow.DataFlow from Function fopen, FunctionCall fc, Expr src - where fopen.hasQualifiedName("fopen") + where fopen.hasGlobalName("fopen") and fc.getTarget() = fopen and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(fc.getArgument(0))) select src -Then we can vary the source, for example an access to a public parameter. The following query finds where a public parameter is used to open a file: +Then we can vary the source and, for example, use the parameter of a function. The following query finds where a parameter is used when opening a file: .. code-block:: ql @@ -109,7 +113,7 @@ Then we can vary the source, for example an access to a public parameter. The fo import semmle.code.cpp.dataflow.DataFlow from Function fopen, FunctionCall fc, Parameter p - where fopen.hasQualifiedName("fopen") + where fopen.hasGlobalName("fopen") and fc.getTarget() = fopen and DataFlow::localFlow(DataFlow::parameterNode(p), DataFlow::exprNode(fc.getArgument(0))) select p @@ -232,14 +236,14 @@ The following data flow configuration tracks data flow from environment variable override predicate isSource(DataFlow::Node source) { exists (Function getenv | source.asExpr().(FunctionCall).getTarget() = getenv and - getenv.hasQualifiedName("getenv") + getenv.hasGlobalName("getenv") ) } override predicate isSink(DataFlow::Node sink) { exists (FunctionCall fc | sink.asExpr() = fc.getArgument(0) and - fc.getTarget().hasQualifiedName("fopen") + fc.getTarget().hasGlobalName("fopen") ) } } @@ -352,7 +356,7 @@ Exercise 3 class GetenvSource extends FunctionCall { GetenvSource() { - this.getTarget().hasQualifiedName("getenv") + this.getTarget().hasGlobalName("getenv") } } @@ -365,7 +369,7 @@ Exercise 4 class GetenvSource extends DataFlow::Node { GetenvSource() { - this.asExpr().(FunctionCall).getTarget().hasQualifiedName("getenv") + this.asExpr().(FunctionCall).getTarget().hasGlobalName("getenv") } } diff --git a/docs/codeql/codeql-language-guides/codeql-for-cpp.rst b/docs/codeql/codeql-language-guides/codeql-for-cpp.rst index 4e5e53d8cb2..ab1afbd325b 100644 --- a/docs/codeql/codeql-language-guides/codeql-for-cpp.rst +++ b/docs/codeql/codeql-language-guides/codeql-for-cpp.rst @@ -14,6 +14,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat expressions-types-and-statements-in-cpp conversions-and-classes-in-cpp analyzing-data-flow-in-cpp + analyzing-data-flow-in-cpp-new refining-a-query-to-account-for-edge-cases detecting-a-potential-buffer-overflow using-the-guards-library-in-cpp diff --git a/docs/codeql/reusables/supported-versions-compilers.rst b/docs/codeql/reusables/supported-versions-compilers.rst index 196bb1a44dd..3ee4ab85ec2 100644 --- a/docs/codeql/reusables/supported-versions-compilers.rst +++ b/docs/codeql/reusables/supported-versions-compilers.rst @@ -24,7 +24,7 @@ JavaScript,ECMAScript 2022 or lower,Not applicable,"``.js``, ``.jsx``, ``.mjs``, ``.es``, ``.es6``, ``.htm``, ``.html``, ``.xhtm``, ``.xhtml``, ``.vue``, ``.hbs``, ``.ejs``, ``.njk``, ``.json``, ``.yaml``, ``.yml``, ``.raml``, ``.xml`` [7]_" Python [8]_,"2.7, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10, 3.11",Not applicable,``.py`` Ruby [9]_,"up to 3.1",Not applicable,"``.rb``, ``.erb``, ``.gemspec``, ``Gemfile``" - TypeScript [10]_,"2.6-4.9",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" + TypeScript [10]_,"2.6-5.0",Standard TypeScript compiler,"``.ts``, ``.tsx``, ``.mts``, ``.cts``" .. container:: footnote-group diff --git a/docs/prepare-db-upgrade.md b/docs/prepare-db-upgrade.md index 42c329dd947..8db7e8fc630 100644 --- a/docs/prepare-db-upgrade.md +++ b/docs/prepare-db-upgrade.md @@ -58,6 +58,15 @@ extended.rel: reorder input.rel (int id, string name, int parent) id name parent // should be placed in the upgrade directory. It should avoid using the default // QLL library, and will run in the context of the *old* dbscheme. relationname.rel: run relationname.qlo + +// Create relationname.rel by running the query predicate 'predicatename' in +// relationname.qlo and writing the query results as a .rel file. This command +// expects the upgrade relation to be a query predicate, which has the advantage +// of allowing multiple upgrade relations to appear in the same .ql file as +// multiple query predicates. The query file should be named relationname.ql and +// should be placed in the upgrade directory. It should avoid using the default +// QLL library, and will run in the context of the *old* dbscheme. +relationname.rel: run relationname.qlo predicatename ``` ### Testing your scripts diff --git a/go/extractor/cli/go-autobuilder/go-autobuilder.go b/go/extractor/cli/go-autobuilder/go-autobuilder.go index c78f7eaa276..eeb82ee54e5 100644 --- a/go/extractor/cli/go-autobuilder/go-autobuilder.go +++ b/go/extractor/cli/go-autobuilder/go-autobuilder.go @@ -16,6 +16,7 @@ import ( "golang.org/x/mod/semver" "github.com/github/codeql-go/extractor/autobuilder" + "github.com/github/codeql-go/extractor/diagnostics" "github.com/github/codeql-go/extractor/util" ) @@ -203,7 +204,7 @@ func (m ModMode) argsForGoVersion(version string) []string { } // addVersionToMod add a go version directive, e.g. `go 1.14` to a `go.mod` file. -func addVersionToMod(goMod []byte, version string) bool { +func addVersionToMod(version string) bool { cmd := exec.Command("go", "mod", "edit", "-go="+version) return util.RunCmd(cmd) } @@ -249,12 +250,29 @@ func main() { depMode := GoGetNoModules modMode := ModUnset needGopath := true + goDirectiveFound := false if _, present := os.LookupEnv("GO111MODULE"); !present { os.Setenv("GO111MODULE", "auto") } if util.FileExists("go.mod") { depMode = GoGetWithModules needGopath = false + versionRe := regexp.MustCompile(`(?m)^go[ \t\r]+([0-9]+\.[0-9]+)$`) + goMod, err := ioutil.ReadFile("go.mod") + if err != nil { + log.Println("Failed to read go.mod to check for missing Go version") + } else { + matches := versionRe.FindSubmatch(goMod) + if matches != nil { + goDirectiveFound = true + if len(matches) > 1 { + goDirectiveVersion := "v" + string(matches[1]) + if semver.Compare(goDirectiveVersion, getEnvGoSemVer()) >= 0 { + diagnostics.EmitNewerGoVersionNeeded() + } + } + } + } log.Println("Found go.mod, enabling go modules") } else if util.FileExists("Gopkg.toml") { depMode = Dep @@ -283,10 +301,7 @@ func main() { // we work around this by adding an explicit go version of 1.13, which is the last version // where this is not an issue if depMode == GoGetWithModules { - goMod, err := ioutil.ReadFile("go.mod") - if err != nil { - log.Println("Failed to read go.mod to check for missing Go version") - } else if versionRe := regexp.MustCompile(`(?m)^go[ \t\r]+[0-9]+\.[0-9]+$`); !versionRe.Match(goMod) { + if !goDirectiveFound { // if the go.mod does not contain a version line modulesTxt, err := ioutil.ReadFile("vendor/modules.txt") if err != nil { @@ -294,7 +309,7 @@ func main() { } else if explicitRe := regexp.MustCompile("(?m)^## explicit$"); !explicitRe.Match(modulesTxt) { // and the modules.txt does not contain an explicit annotation log.Println("Adding a version directive to the go.mod file as the modules.txt does not have explicit annotations") - if !addVersionToMod(goMod, "1.13") { + if !addVersionToMod("1.13") { log.Println("Failed to add a version to the go.mod file to fix explicitly required package bug; not using vendored dependencies") modMode = ModMod } diff --git a/go/extractor/cli/go-extractor/go-extractor.go b/go/extractor/cli/go-extractor/go-extractor.go index 59ab35da4a9..00d3c8e7de1 100644 --- a/go/extractor/cli/go-extractor/go-extractor.go +++ b/go/extractor/cli/go-extractor/go-extractor.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/github/codeql-go/extractor" + "github.com/github/codeql-go/extractor/diagnostics" ) var cpuprofile, memprofile string @@ -115,7 +116,12 @@ func main() { log.Printf("Build flags: '%s'; patterns: '%s'\n", strings.Join(buildFlags, " "), strings.Join(patterns, " ")) err := extractor.ExtractWithFlags(buildFlags, patterns) if err != nil { - log.Fatalf("Error running go tooling: %s\n", err.Error()) + errString := err.Error() + if strings.Contains(errString, "unexpected directory layout:") { + diagnostics.EmitRelativeImportPaths() + } + + log.Fatalf("Error running go tooling: %s\n", errString) } if memprofile != "" { diff --git a/go/extractor/diagnostics/diagnostics.go b/go/extractor/diagnostics/diagnostics.go new file mode 100644 index 00000000000..2078d88d6c5 --- /dev/null +++ b/go/extractor/diagnostics/diagnostics.go @@ -0,0 +1,194 @@ +package diagnostics + +import ( + "encoding/json" + "fmt" + "log" + "os" + "strings" + "time" +) + +type sourceStruct struct { + Id string `json:"id"` + Name string `json:"name"` + ExtractorName string `json:"extractorName"` +} + +type diagnosticSeverity string + +const ( + severityError diagnosticSeverity = "error" + severityWarning diagnosticSeverity = "warning" + severityNote diagnosticSeverity = "note" +) + +type visibilityStruct struct { + StatusPage bool `json:"statusPage"` // True if the message should be displayed on the status page (defaults to false) + CliSummaryTable bool `json:"cliSummaryTable"` // True if the message should be counted in the diagnostics summary table printed by `codeql database analyze` (defaults to false) + Telemetry bool `json:"telemetry"` // True if the message should be sent to telemetry (defaults to false) +} + +var fullVisibility *visibilityStruct = &visibilityStruct{true, true, true} + +type locationStruct struct { + File string `json:"file,omitempty"` + StartLine int `json:"startLine,omitempty"` + StartColumn int `json:"startColumn,omitempty"` + EndLine int `json:"endLine,omitempty"` + EndColumn int `json:"endColumn,omitempty"` +} + +var noLocation *locationStruct = nil + +type diagnostic struct { + Timestamp string `json:"timestamp"` + Source sourceStruct `json:"source"` + MarkdownMessage string `json:"markdownMessage"` + Severity string `json:"severity"` + Visibility *visibilityStruct `json:"visibility,omitempty"` // Use a pointer so that it is omitted if nil + Location *locationStruct `json:"location,omitempty"` // Use a pointer so that it is omitted if nil +} + +var diagnosticsEmitted, diagnosticsLimit uint = 0, 100 +var noDiagnosticDirPrinted bool = false + +func emitDiagnostic(sourceid, sourcename, markdownMessage string, severity diagnosticSeverity, visibility *visibilityStruct, location *locationStruct) { + if diagnosticsEmitted < diagnosticsLimit { + diagnosticsEmitted += 1 + + diagnosticDir := os.Getenv("CODEQL_EXTRACTOR_GO_DIAGNOSTIC_DIR") + if diagnosticDir == "" { + if !noDiagnosticDirPrinted { + log.Println("No diagnostic directory set, so not emitting diagnostic") + noDiagnosticDirPrinted = true + } + return + } + + timestamp := time.Now().UTC().Format("2006-01-02T15:04:05.000") + "Z" + + var d diagnostic + + if diagnosticsEmitted < diagnosticsLimit { + d = diagnostic{ + timestamp, + sourceStruct{sourceid, sourcename, "go"}, + markdownMessage, + string(severity), + visibility, + location, + } + } else { + d = diagnostic{ + timestamp, + sourceStruct{"go/autobuilder/diagnostic-limit-reached", "Diagnostics limit exceeded", "go"}, + fmt.Sprintf("CodeQL has produced more than the maximum number of diagnostics. Only the first %d have been reported.", diagnosticsLimit), + string(severityWarning), + fullVisibility, + noLocation, + } + } + + content, err := json.Marshal(d) + if err != nil { + log.Println(err) + return + } + + targetFile, err := os.CreateTemp(diagnosticDir, "go-extractor.*.json") + if err != nil { + log.Println("Failed to create diagnostic file: ") + log.Println(err) + return + } + defer func() { + if err := targetFile.Close(); err != nil { + log.Println("Failed to close diagnostic file:") + log.Println(err) + } + }() + + _, err = targetFile.Write(content) + if err != nil { + log.Println("Failed to write to diagnostic file: ") + log.Println(err) + } + } +} + +func EmitPackageDifferentOSArchitecture(pkgPath string) { + emitDiagnostic( + "go/autobuilder/package-different-os-architecture", + "An imported package is intended for a different OS or architecture", + "`"+pkgPath+"` could not be imported. Make sure the `GOOS` and `GOARCH` [environment variables are correctly set](https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow). Alternatively, [change your OS and architecture](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#using-a-github-hosted-runner).", + severityWarning, + fullVisibility, + noLocation, + ) +} + +const maxNumPkgPaths = 5 + +func EmitCannotFindPackages(pkgPaths []string) { + numPkgPaths := len(pkgPaths) + + ending := "s" + if numPkgPaths == 1 { + ending = "" + } + + numPrinted := numPkgPaths + truncated := false + if numPrinted > maxNumPkgPaths { + numPrinted = maxNumPkgPaths + truncated = true + } + + secondLine := "`" + strings.Join(pkgPaths[0:numPrinted], "`, `") + "`" + if truncated { + secondLine += fmt.Sprintf(" and %d more", numPkgPaths-maxNumPkgPaths) + } + + emitDiagnostic( + "go/autobuilder/package-not-found", + "Some packages could not be found", + fmt.Sprintf("%d package%s could not be found.\n\n%s.\n\nCheck that the paths are correct and make sure any private packages can be accessed. If any of the packages are present in the repository then you may need a [custom build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", numPkgPaths, ending, secondLine), + severityError, + fullVisibility, + noLocation, + ) +} + +func EmitNewerGoVersionNeeded() { + emitDiagnostic( + "go/autobuilder/newer-go-version-needed", + "Newer Go version needed", + "The detected version of Go is lower than the version specified in `go.mod`. [Install a newer version](https://github.com/actions/setup-go#basic).", + severityError, + fullVisibility, + noLocation, + ) +} + +func EmitGoFilesFoundButNotProcessed() { + emitDiagnostic( + "go/autobuilder/go-files-found-but-not-processed", + "Go files were found but not processed", + "[Specify a custom build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages) that includes one or more `go build` commands to build the `.go` files to be analyzed.", + severityError, + fullVisibility, + noLocation, + ) +} + +func EmitRelativeImportPaths() { + emitDiagnostic( + "go/autobuilder/relative-import-paths", + "Some imports use unsupported relative package paths", + "You should replace relative package paths (that contain `.` or `..`) with absolute paths. Alternatively you can [use a Go module](https://go.dev/blog/using-go-modules).", + severityError, + fullVisibility, + noLocation, + ) +} diff --git a/go/extractor/extractor.go b/go/extractor/extractor.go index 4b087d82947..72aad3d8188 100644 --- a/go/extractor/extractor.go +++ b/go/extractor/extractor.go @@ -22,6 +22,7 @@ import ( "time" "github.com/github/codeql-go/extractor/dbscheme" + "github.com/github/codeql-go/extractor/diagnostics" "github.com/github/codeql-go/extractor/srcarchive" "github.com/github/codeql-go/extractor/trap" "github.com/github/codeql-go/extractor/util" @@ -97,6 +98,13 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error { if len(pkgs) == 0 { log.Println("No packages found.") + + wd, err := os.Getwd() + if err != nil { + log.Printf("Warning: failed to get working directory: %s\n", err.Error()) + } else if util.FindGoFiles(wd) { + diagnostics.EmitGoFilesFoundButNotProcessed() + } } log.Println("Extracting universe scope.") @@ -118,6 +126,8 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error { log.Printf("Done running go list deps: resolved %d packages.", len(pkgInfos)) } + pkgsNotFound := make([]string, 0, len(pkgs)) + // Do a post-order traversal and extract the package scope of each package packages.Visit(pkgs, func(pkg *packages.Package) bool { return true @@ -144,13 +154,27 @@ func ExtractWithFlags(buildFlags []string, patterns []string) error { if len(pkg.Errors) != 0 { log.Printf("Warning: encountered errors extracting package `%s`:", pkg.PkgPath) for i, err := range pkg.Errors { - log.Printf(" %s", err.Error()) + errString := err.Error() + log.Printf(" %s", errString) + + if strings.Contains(errString, "build constraints exclude all Go files in ") { + // `err` is a NoGoError from the package cmd/go/internal/load, which we cannot access as it is internal + diagnostics.EmitPackageDifferentOSArchitecture(pkg.PkgPath) + } else if strings.Contains(errString, "cannot find package") || + strings.Contains(errString, "no required module provides package") { + pkgsNotFound = append(pkgsNotFound, pkg.PkgPath) + } extraction.extractError(tw, err, lbl, i) } } + log.Printf("Done extracting types for package %s.", pkg.PkgPath) }) + if len(pkgsNotFound) > 0 { + diagnostics.EmitCannotFindPackages(pkgsNotFound) + } + for _, pkg := range pkgs { pkgInfo, ok := pkgInfos[pkg.PkgPath] if !ok || pkgInfo.PkgDir == "" { diff --git a/go/extractor/util/util.go b/go/extractor/util/util.go index 37165f56cd7..4417419db6a 100644 --- a/go/extractor/util/util.go +++ b/go/extractor/util/util.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "io" + "io/fs" "log" "os" "os/exec" @@ -281,3 +282,18 @@ func EscapeTrapSpecialChars(s string) string { s = strings.ReplaceAll(s, "#", "#") return s } + +func FindGoFiles(root string) bool { + found := false + filepath.WalkDir(root, func(s string, d fs.DirEntry, e error) error { + if e != nil { + return e + } + if filepath.Ext(d.Name()) == ".go" { + found = true + return filepath.SkipAll + } + return nil + }) + return found +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/diagnostics.expected new file mode 100644 index 00000000000..dc7a5dca282 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "`syscall/js` could not be imported. Make sure the `GOOS` and `GOARCH` [environment variables are correctly set](https://docs.github.com/en/actions/learn-github-actions/variables#defining-environment-variables-for-a-single-workflow). Alternatively, [change your OS and architecture](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners#using-a-github-hosted-runner).", + "severity": "warning", + "source": { + "extractorName": "go", + "id": "go/autobuilder/package-different-os-architecture", + "name": "An imported package is intended for a different OS or architecture" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/test.py new file mode 100644 index 00000000000..9f34f431b93 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/go.mod new file mode 100644 index 00000000000..6d61cf5dc3d --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/go.mod @@ -0,0 +1,3 @@ +go 1.18 + +module test diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/go.sum b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/go.sum new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/test.go b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/test.go new file mode 100644 index 00000000000..dc3846a02e2 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/build-constraints-exclude-all-go-files/work/test.go @@ -0,0 +1,8 @@ +package test + +import "syscall/js" + +func Test() { + var x js.Error + _ = x +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/diagnostics.expected new file mode 100644 index 00000000000..405113fe93a --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "[Specify a custom build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages) that includes one or more `go build` commands to build the `.go` files to be analyzed.", + "severity": "error", + "source": { + "extractorName": "go", + "id": "go/autobuilder/go-files-found-but-not-processed", + "name": "Go files were found but not processed" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/test.py new file mode 100644 index 00000000000..2f43492da41 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None, runFunction=runUnsuccessfully) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/go.mod new file mode 100644 index 00000000000..6d61cf5dc3d --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/go.mod @@ -0,0 +1,3 @@ +go 1.18 + +module test diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/go.sum b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/go.sum new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/go.mod new file mode 100644 index 00000000000..66cb49581d3 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/go.mod @@ -0,0 +1,3 @@ +go 1.18 + +module test/subdir diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/go.sum b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/go.sum new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/test.go b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/test.go new file mode 100644 index 00000000000..3f8cd1e2951 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/go-files-found-not-processed/work/subdir/test.go @@ -0,0 +1,4 @@ +package test/subdir + +func Test() { +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/diagnostics.expected new file mode 100644 index 00000000000..e50dcf5c093 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "The detected version of Go is lower than the version specified in `go.mod`. [Install a newer version](https://github.com/actions/setup-go#basic).", + "severity": "error", + "source": { + "extractorName": "go", + "id": "go/autobuilder/newer-go-version-needed", + "name": "Newer Go version needed" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/test.py new file mode 100644 index 00000000000..9f34f431b93 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/go.mod new file mode 100644 index 00000000000..14415aab0a7 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/go.mod @@ -0,0 +1,3 @@ +go 999.0 + +module test diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/go.sum b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/go.sum new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/test.go b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/test.go new file mode 100644 index 00000000000..d0a32dfa082 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/newer-go-version-needed/work/test.go @@ -0,0 +1,4 @@ +package test + +func Test() { +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/diagnostics.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/test.py new file mode 100644 index 00000000000..2f43492da41 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None, runFunction=runUnsuccessfully) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/work/test.txt b/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/work/test.txt new file mode 100644 index 00000000000..82b6450140b --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/no-go-files-found/work/test.txt @@ -0,0 +1 @@ +// The "Go files were found but not processed" diagnostic should not be emitted because there are no go files \ No newline at end of file diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/diagnostics.expected new file mode 100644 index 00000000000..a24d8121da7 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "110 packages could not be found.\n\n`github.com/nosuchorg/nosuchrepo000`, `github.com/nosuchorg/nosuchrepo001`, `github.com/nosuchorg/nosuchrepo002`, `github.com/nosuchorg/nosuchrepo003`, `github.com/nosuchorg/nosuchrepo004` and 105 more.\n\nCheck that the paths are correct and make sure any private packages can be accessed. If any of the packages are present in the repository then you may need a [custom build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "go", + "id": "go/autobuilder/package-not-found", + "name": "Some packages could not be found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/test.py new file mode 100644 index 00000000000..9f34f431b93 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.mod b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.mod new file mode 100644 index 00000000000..52f47d8d3e2 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.mod @@ -0,0 +1,7 @@ +go 1.19 + +require ( + github.com/linode/linode-docs-theme v0.0.0-20220622135843-166f108e1933 +) + +module test diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.sum b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.sum new file mode 100644 index 00000000000..c4c3e8d972d --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/go.sum @@ -0,0 +1 @@ +github.com/linode/linode-docs-theme v0.0.0-20220622135843-166f108e1933 h1:QchGQS6xESuyjdlNJEjvq2ftGX0sCTAhPhD5hAOJVMI= diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/test.go b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/test.go new file mode 100644 index 00000000000..c353ecd0195 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-with-go-mod/work/test.go @@ -0,0 +1,337 @@ +package test + +import ( + "github.com/nosuchorg/nosuchrepo000" + "github.com/nosuchorg/nosuchrepo001" + "github.com/nosuchorg/nosuchrepo002" + "github.com/nosuchorg/nosuchrepo003" + "github.com/nosuchorg/nosuchrepo004" + "github.com/nosuchorg/nosuchrepo005" + "github.com/nosuchorg/nosuchrepo006" + "github.com/nosuchorg/nosuchrepo007" + "github.com/nosuchorg/nosuchrepo008" + "github.com/nosuchorg/nosuchrepo009" + "github.com/nosuchorg/nosuchrepo010" + "github.com/nosuchorg/nosuchrepo011" + "github.com/nosuchorg/nosuchrepo012" + "github.com/nosuchorg/nosuchrepo013" + "github.com/nosuchorg/nosuchrepo014" + "github.com/nosuchorg/nosuchrepo015" + "github.com/nosuchorg/nosuchrepo016" + "github.com/nosuchorg/nosuchrepo017" + "github.com/nosuchorg/nosuchrepo018" + "github.com/nosuchorg/nosuchrepo019" + "github.com/nosuchorg/nosuchrepo020" + "github.com/nosuchorg/nosuchrepo021" + "github.com/nosuchorg/nosuchrepo022" + "github.com/nosuchorg/nosuchrepo023" + "github.com/nosuchorg/nosuchrepo024" + "github.com/nosuchorg/nosuchrepo025" + "github.com/nosuchorg/nosuchrepo026" + "github.com/nosuchorg/nosuchrepo027" + "github.com/nosuchorg/nosuchrepo028" + "github.com/nosuchorg/nosuchrepo029" + "github.com/nosuchorg/nosuchrepo030" + "github.com/nosuchorg/nosuchrepo031" + "github.com/nosuchorg/nosuchrepo032" + "github.com/nosuchorg/nosuchrepo033" + "github.com/nosuchorg/nosuchrepo034" + "github.com/nosuchorg/nosuchrepo035" + "github.com/nosuchorg/nosuchrepo036" + "github.com/nosuchorg/nosuchrepo037" + "github.com/nosuchorg/nosuchrepo038" + "github.com/nosuchorg/nosuchrepo039" + "github.com/nosuchorg/nosuchrepo040" + "github.com/nosuchorg/nosuchrepo041" + "github.com/nosuchorg/nosuchrepo042" + "github.com/nosuchorg/nosuchrepo043" + "github.com/nosuchorg/nosuchrepo044" + "github.com/nosuchorg/nosuchrepo045" + "github.com/nosuchorg/nosuchrepo046" + "github.com/nosuchorg/nosuchrepo047" + "github.com/nosuchorg/nosuchrepo048" + "github.com/nosuchorg/nosuchrepo049" + "github.com/nosuchorg/nosuchrepo050" + "github.com/nosuchorg/nosuchrepo051" + "github.com/nosuchorg/nosuchrepo052" + "github.com/nosuchorg/nosuchrepo053" + "github.com/nosuchorg/nosuchrepo054" + "github.com/nosuchorg/nosuchrepo055" + "github.com/nosuchorg/nosuchrepo056" + "github.com/nosuchorg/nosuchrepo057" + "github.com/nosuchorg/nosuchrepo058" + "github.com/nosuchorg/nosuchrepo059" + "github.com/nosuchorg/nosuchrepo060" + "github.com/nosuchorg/nosuchrepo061" + "github.com/nosuchorg/nosuchrepo062" + "github.com/nosuchorg/nosuchrepo063" + "github.com/nosuchorg/nosuchrepo064" + "github.com/nosuchorg/nosuchrepo065" + "github.com/nosuchorg/nosuchrepo066" + "github.com/nosuchorg/nosuchrepo067" + "github.com/nosuchorg/nosuchrepo068" + "github.com/nosuchorg/nosuchrepo069" + "github.com/nosuchorg/nosuchrepo070" + "github.com/nosuchorg/nosuchrepo071" + "github.com/nosuchorg/nosuchrepo072" + "github.com/nosuchorg/nosuchrepo073" + "github.com/nosuchorg/nosuchrepo074" + "github.com/nosuchorg/nosuchrepo075" + "github.com/nosuchorg/nosuchrepo076" + "github.com/nosuchorg/nosuchrepo077" + "github.com/nosuchorg/nosuchrepo078" + "github.com/nosuchorg/nosuchrepo079" + "github.com/nosuchorg/nosuchrepo080" + "github.com/nosuchorg/nosuchrepo081" + "github.com/nosuchorg/nosuchrepo082" + "github.com/nosuchorg/nosuchrepo083" + "github.com/nosuchorg/nosuchrepo084" + "github.com/nosuchorg/nosuchrepo085" + "github.com/nosuchorg/nosuchrepo086" + "github.com/nosuchorg/nosuchrepo087" + "github.com/nosuchorg/nosuchrepo088" + "github.com/nosuchorg/nosuchrepo089" + "github.com/nosuchorg/nosuchrepo090" + "github.com/nosuchorg/nosuchrepo091" + "github.com/nosuchorg/nosuchrepo092" + "github.com/nosuchorg/nosuchrepo093" + "github.com/nosuchorg/nosuchrepo094" + "github.com/nosuchorg/nosuchrepo095" + "github.com/nosuchorg/nosuchrepo096" + "github.com/nosuchorg/nosuchrepo097" + "github.com/nosuchorg/nosuchrepo098" + "github.com/nosuchorg/nosuchrepo099" + "github.com/nosuchorg/nosuchrepo100" + "github.com/nosuchorg/nosuchrepo101" + "github.com/nosuchorg/nosuchrepo102" + "github.com/nosuchorg/nosuchrepo103" + "github.com/nosuchorg/nosuchrepo104" + "github.com/nosuchorg/nosuchrepo105" + "github.com/nosuchorg/nosuchrepo106" + "github.com/nosuchorg/nosuchrepo107" + "github.com/nosuchorg/nosuchrepo108" + "github.com/nosuchorg/nosuchrepo109" +) + +func Test() { + theme000 := nosuchrepo000.Theme{} + _ = theme000 + theme001 := nosuchrepo001.Theme{} + _ = theme001 + theme002 := nosuchrepo002.Theme{} + _ = theme002 + theme003 := nosuchrepo003.Theme{} + _ = theme003 + theme004 := nosuchrepo004.Theme{} + _ = theme004 + theme005 := nosuchrepo005.Theme{} + _ = theme005 + theme006 := nosuchrepo006.Theme{} + _ = theme006 + theme007 := nosuchrepo007.Theme{} + _ = theme007 + theme008 := nosuchrepo008.Theme{} + _ = theme008 + theme009 := nosuchrepo009.Theme{} + _ = theme009 + theme010 := nosuchrepo010.Theme{} + _ = theme010 + theme011 := nosuchrepo011.Theme{} + _ = theme011 + theme012 := nosuchrepo012.Theme{} + _ = theme012 + theme013 := nosuchrepo013.Theme{} + _ = theme013 + theme014 := nosuchrepo014.Theme{} + _ = theme014 + theme015 := nosuchrepo015.Theme{} + _ = theme015 + theme016 := nosuchrepo016.Theme{} + _ = theme016 + theme017 := nosuchrepo017.Theme{} + _ = theme017 + theme018 := nosuchrepo018.Theme{} + _ = theme018 + theme019 := nosuchrepo019.Theme{} + _ = theme019 + theme020 := nosuchrepo020.Theme{} + _ = theme020 + theme021 := nosuchrepo021.Theme{} + _ = theme021 + theme022 := nosuchrepo022.Theme{} + _ = theme022 + theme023 := nosuchrepo023.Theme{} + _ = theme023 + theme024 := nosuchrepo024.Theme{} + _ = theme024 + theme025 := nosuchrepo025.Theme{} + _ = theme025 + theme026 := nosuchrepo026.Theme{} + _ = theme026 + theme027 := nosuchrepo027.Theme{} + _ = theme027 + theme028 := nosuchrepo028.Theme{} + _ = theme028 + theme029 := nosuchrepo029.Theme{} + _ = theme029 + theme030 := nosuchrepo030.Theme{} + _ = theme030 + theme031 := nosuchrepo031.Theme{} + _ = theme031 + theme032 := nosuchrepo032.Theme{} + _ = theme032 + theme033 := nosuchrepo033.Theme{} + _ = theme033 + theme034 := nosuchrepo034.Theme{} + _ = theme034 + theme035 := nosuchrepo035.Theme{} + _ = theme035 + theme036 := nosuchrepo036.Theme{} + _ = theme036 + theme037 := nosuchrepo037.Theme{} + _ = theme037 + theme038 := nosuchrepo038.Theme{} + _ = theme038 + theme039 := nosuchrepo039.Theme{} + _ = theme039 + theme040 := nosuchrepo040.Theme{} + _ = theme040 + theme041 := nosuchrepo041.Theme{} + _ = theme041 + theme042 := nosuchrepo042.Theme{} + _ = theme042 + theme043 := nosuchrepo043.Theme{} + _ = theme043 + theme044 := nosuchrepo044.Theme{} + _ = theme044 + theme045 := nosuchrepo045.Theme{} + _ = theme045 + theme046 := nosuchrepo046.Theme{} + _ = theme046 + theme047 := nosuchrepo047.Theme{} + _ = theme047 + theme048 := nosuchrepo048.Theme{} + _ = theme048 + theme049 := nosuchrepo049.Theme{} + _ = theme049 + theme050 := nosuchrepo050.Theme{} + _ = theme050 + theme051 := nosuchrepo051.Theme{} + _ = theme051 + theme052 := nosuchrepo052.Theme{} + _ = theme052 + theme053 := nosuchrepo053.Theme{} + _ = theme053 + theme054 := nosuchrepo054.Theme{} + _ = theme054 + theme055 := nosuchrepo055.Theme{} + _ = theme055 + theme056 := nosuchrepo056.Theme{} + _ = theme056 + theme057 := nosuchrepo057.Theme{} + _ = theme057 + theme058 := nosuchrepo058.Theme{} + _ = theme058 + theme059 := nosuchrepo059.Theme{} + _ = theme059 + theme060 := nosuchrepo060.Theme{} + _ = theme060 + theme061 := nosuchrepo061.Theme{} + _ = theme061 + theme062 := nosuchrepo062.Theme{} + _ = theme062 + theme063 := nosuchrepo063.Theme{} + _ = theme063 + theme064 := nosuchrepo064.Theme{} + _ = theme064 + theme065 := nosuchrepo065.Theme{} + _ = theme065 + theme066 := nosuchrepo066.Theme{} + _ = theme066 + theme067 := nosuchrepo067.Theme{} + _ = theme067 + theme068 := nosuchrepo068.Theme{} + _ = theme068 + theme069 := nosuchrepo069.Theme{} + _ = theme069 + theme070 := nosuchrepo070.Theme{} + _ = theme070 + theme071 := nosuchrepo071.Theme{} + _ = theme071 + theme072 := nosuchrepo072.Theme{} + _ = theme072 + theme073 := nosuchrepo073.Theme{} + _ = theme073 + theme074 := nosuchrepo074.Theme{} + _ = theme074 + theme075 := nosuchrepo075.Theme{} + _ = theme075 + theme076 := nosuchrepo076.Theme{} + _ = theme076 + theme077 := nosuchrepo077.Theme{} + _ = theme077 + theme078 := nosuchrepo078.Theme{} + _ = theme078 + theme079 := nosuchrepo079.Theme{} + _ = theme079 + theme080 := nosuchrepo080.Theme{} + _ = theme080 + theme081 := nosuchrepo081.Theme{} + _ = theme081 + theme082 := nosuchrepo082.Theme{} + _ = theme082 + theme083 := nosuchrepo083.Theme{} + _ = theme083 + theme084 := nosuchrepo084.Theme{} + _ = theme084 + theme085 := nosuchrepo085.Theme{} + _ = theme085 + theme086 := nosuchrepo086.Theme{} + _ = theme086 + theme087 := nosuchrepo087.Theme{} + _ = theme087 + theme088 := nosuchrepo088.Theme{} + _ = theme088 + theme089 := nosuchrepo089.Theme{} + _ = theme089 + theme090 := nosuchrepo090.Theme{} + _ = theme090 + theme091 := nosuchrepo091.Theme{} + _ = theme091 + theme092 := nosuchrepo092.Theme{} + _ = theme092 + theme093 := nosuchrepo093.Theme{} + _ = theme093 + theme094 := nosuchrepo094.Theme{} + _ = theme094 + theme095 := nosuchrepo095.Theme{} + _ = theme095 + theme096 := nosuchrepo096.Theme{} + _ = theme096 + theme097 := nosuchrepo097.Theme{} + _ = theme097 + theme098 := nosuchrepo098.Theme{} + _ = theme098 + theme099 := nosuchrepo099.Theme{} + _ = theme099 + theme100 := nosuchrepo100.Theme{} + _ = theme100 + theme101 := nosuchrepo101.Theme{} + _ = theme101 + theme102 := nosuchrepo102.Theme{} + _ = theme102 + theme103 := nosuchrepo103.Theme{} + _ = theme103 + theme104 := nosuchrepo104.Theme{} + _ = theme104 + theme105 := nosuchrepo105.Theme{} + _ = theme105 + theme106 := nosuchrepo106.Theme{} + _ = theme106 + theme107 := nosuchrepo107.Theme{} + _ = theme107 + theme108 := nosuchrepo108.Theme{} + _ = theme108 + theme109 := nosuchrepo109.Theme{} + _ = theme109 +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/diagnostics.expected new file mode 100644 index 00000000000..d5c515a076b --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "1 package could not be found.\n\n`github.com/linode/linode-docs-theme`.\n\nCheck that the paths are correct and make sure any private packages can be accessed. If any of the packages are present in the repository then you may need a [custom build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages).", + "severity": "error", + "source": { + "extractorName": "go", + "id": "go/autobuilder/package-not-found", + "name": "Some packages could not be found" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/test.py new file mode 100644 index 00000000000..9f34f431b93 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['LGTM_INDEX_IMPORT_PATH'] = "test" +run_codeql_database_create([], lang="go", source="work", db=None) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/work/test.go b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/work/test.go new file mode 100644 index 00000000000..d51c5a926eb --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/package-not-found-without-go-mod/work/test.go @@ -0,0 +1,8 @@ +package test + +import linodedocstheme "github.com/linode/linode-docs-theme" + +func Test() { + theme := linodedocstheme.Theme{} + _ = theme +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/diagnostics.expected b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/diagnostics.expected new file mode 100644 index 00000000000..1a94d1bda1a --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/diagnostics.expected @@ -0,0 +1,14 @@ +{ + "markdownMessage": "You should replace relative package paths (that contain `.` or `..`) with absolute paths. Alternatively you can [use a Go module](https://go.dev/blog/using-go-modules).", + "severity": "error", + "source": { + "extractorName": "go", + "id": "go/autobuilder/relative-import-paths", + "name": "Some imports use unsupported relative package paths" + }, + "visibility": { + "cliSummaryTable": true, + "statusPage": true, + "telemetry": true + } +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/test.py b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/test.py new file mode 100644 index 00000000000..be9ec6f5b7a --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/test.py @@ -0,0 +1,9 @@ +import sys + +from create_database_utils import * +from diagnostics_test_utils import * + +os.environ['GITHUB_REPOSITORY'] = "a/b" +run_codeql_database_create([], lang="go", source="work", db=None, runFunction=runUnsuccessfully) + +check_diagnostics() diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/main.go b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/main.go new file mode 100644 index 00000000000..d64864633b2 --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/main.go @@ -0,0 +1,9 @@ +package main + +import ( + "./subpkg" +) + +func main() { + subpkg.F() +} diff --git a/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/subpkg/subpkg.go b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/subpkg/subpkg.go new file mode 100644 index 00000000000..3fb4f55d98b --- /dev/null +++ b/go/ql/integration-tests/all-platforms/go/diagnostics/unsupported-relative-path/work/main/subpkg/subpkg.go @@ -0,0 +1,8 @@ +package subpkg + +import "fmt" + +func F() { + // It is required that there is an import in this package, which is import by another package using a local path + fmt.Println("subpkg.F") +} diff --git a/go/ql/lib/CHANGELOG.md b/go/ql/lib/CHANGELOG.md index 1a5db51a5ee..3bab3bf2b6a 100644 --- a/go/ql/lib/CHANGELOG.md +++ b/go/ql/lib/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.4 + +No user-facing changes. + ## 0.4.3 ### New Features diff --git a/go/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md b/go/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md new file mode 100644 index 00000000000..89190af399f --- /dev/null +++ b/go/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md @@ -0,0 +1,9 @@ +--- +category: majorAnalysis +--- +* The main data flow and taint tracking APIs have been changed. The old APIs + remain in place for now and translate to the new through a + backwards-compatible wrapper. If multiple configurations are in scope + simultaneously, then this may affect results slightly. The new API is quite + similar to the old, but makes use of a configuration module instead of a + configuration class. diff --git a/go/ql/lib/change-notes/2023-03-13-mergepathgraph.md b/go/ql/lib/change-notes/2023-03-13-mergepathgraph.md new file mode 100644 index 00000000000..63bfade2f10 --- /dev/null +++ b/go/ql/lib/change-notes/2023-03-13-mergepathgraph.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query. diff --git a/go/ql/lib/change-notes/released/0.4.4.md b/go/ql/lib/change-notes/released/0.4.4.md new file mode 100644 index 00000000000..33e1c91255d --- /dev/null +++ b/go/ql/lib/change-notes/released/0.4.4.md @@ -0,0 +1,3 @@ +## 0.4.4 + +No user-facing changes. diff --git a/go/ql/lib/codeql-pack.release.yml b/go/ql/lib/codeql-pack.release.yml index 1ec9c4ea5d9..e9b57993a01 100644 --- a/go/ql/lib/codeql-pack.release.yml +++ b/go/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.3 +lastReleaseVersion: 0.4.4 diff --git a/go/ql/lib/qlpack.yml b/go/ql/lib/qlpack.yml index 6d9f6fb8962..378f7b0e5e4 100644 --- a/go/ql/lib/qlpack.yml +++ b/go/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-all -version: 0.4.4-dev +version: 0.4.5-dev groups: go dbscheme: go.dbscheme extractor: go diff --git a/go/ql/lib/semmle/go/Files.qll b/go/ql/lib/semmle/go/Files.qll index 12f70bb4469..b261b935318 100644 --- a/go/ql/lib/semmle/go/Files.qll +++ b/go/ql/lib/semmle/go/Files.qll @@ -183,7 +183,8 @@ class Folder extends Container, @folder { /** Any file, including files that have not been extracted but are referred to as locations for errors. */ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent, GoModExprParent, - DeclParent, ScopeNode { + DeclParent, ScopeNode +{ override Location getLocation() { has_location(this, result) } override string getAbsolutePath() { files(this, result) } diff --git a/go/ql/lib/semmle/go/StringOps.qll b/go/ql/lib/semmle/go/StringOps.qll index 00fd7d512e9..c3dc8fdb18d 100644 --- a/go/ql/lib/semmle/go/StringOps.qll +++ b/go/ql/lib/semmle/go/StringOps.qll @@ -228,7 +228,8 @@ module StringOps { * the receiver of a call to `strings.Replacer.Replace` or * `strings.Replacer.WriteString`. */ - private class StringsNewReplacerConfiguration extends DataFlowForStringsNewReplacer::Configuration { + private class StringsNewReplacerConfiguration extends DataFlowForStringsNewReplacer::Configuration + { StringsNewReplacerConfiguration() { this = "StringsNewReplacerConfiguration" } override predicate isSource(DataFlow::Node source) { diff --git a/go/ql/lib/semmle/go/dataflow/DataFlow.qll b/go/ql/lib/semmle/go/dataflow/DataFlow.qll index d99ce3bb554..fde408a4450 100644 --- a/go/ql/lib/semmle/go/dataflow/DataFlow.qll +++ b/go/ql/lib/semmle/go/dataflow/DataFlow.qll @@ -22,7 +22,8 @@ import go * data flow analysis. */ module DataFlow { - import semmle.go.dataflow.internal.DataFlowImpl + import semmle.go.dataflow.internal.DataFlow + import semmle.go.dataflow.internal.DataFlowImpl1 import Properties } diff --git a/go/ql/lib/semmle/go/dataflow/TaintTracking.qll b/go/ql/lib/semmle/go/dataflow/TaintTracking.qll index 096116d4bee..2f0bb5ea116 100644 --- a/go/ql/lib/semmle/go/dataflow/TaintTracking.qll +++ b/go/ql/lib/semmle/go/dataflow/TaintTracking.qll @@ -10,5 +10,6 @@ import semmle.go.dataflow.DataFlow * global (inter-procedural) taint-tracking analyses. */ module TaintTracking { + import semmle.go.dataflow.internal.tainttracking1.TaintTracking import semmle.go.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlow.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlow.qll new file mode 100644 index 00000000000..617362ab4f0 --- /dev/null +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlow.qll @@ -0,0 +1,353 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Make` and `MakeWithState` modules. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic +private import DataFlowImpl + +/** An input configuration for data flow. */ +signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** An input configuration for data flow using flow state. */ +signature module StateConfigSig { + bindingset[this] + class FlowState; + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state); + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state); + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ +signature int explorationLimitSig(); + +/** + * The output of a data flow computation. + */ +signature module DataFlowSig { + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode; + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink); + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink); +} + +/** + * Constructs a standard data flow computation. + */ +module Make implements DataFlowSig { + private module C implements FullStateConfigSig { + import DefaultState + import Config + } + + import Impl +} + +/** + * Constructs a data flow computation using flow state. + */ +module MakeWithState implements DataFlowSig { + private module C implements FullStateConfigSig { + import Config + } + + import Impl +} + +signature class PathNodeSig { + /** Gets a textual representation of this element. */ + string toString(); + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); + + /** Gets the underlying `Node`. */ + Node getNode(); +} + +signature module PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + predicate edges(PathNode a, PathNode b); + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + predicate nodes(PathNode n, string key, string val); + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); +} + +/** + * Constructs a `PathGraph` from two `PathGraph`s by disjoint union. + */ +module MergePathGraph< + PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig Graph1, + PathGraphSig Graph2> +{ + private newtype TPathNode = + TPathNode1(PathNode1 p) or + TPathNode2(PathNode2 p) + + /** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */ + class PathNode extends TPathNode { + /** Gets this as a projection on the first given `PathGraph`. */ + PathNode1 asPathNode1() { this = TPathNode1(result) } + + /** Gets this as a projection on the second given `PathGraph`. */ + PathNode2 asPathNode2() { this = TPathNode2(result) } + + /** Gets a textual representation of this element. */ + string toString() { + result = this.asPathNode1().toString() or + result = this.asPathNode2().toString() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + Node getNode() { + result = this.asPathNode1().getNode() or + result = this.asPathNode2().getNode() + } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph implements PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + Graph1::edges(a.asPathNode1(), b.asPathNode1()) or + Graph2::edges(a.asPathNode2(), b.asPathNode2()) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + Graph1::nodes(n.asPathNode1(), key, val) or + Graph2::nodes(n.asPathNode2(), key, val) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or + Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2()) + } + } +} diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll index 1b969756b09..b7cb98deaf9 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl.qll @@ -1,135 +1,75 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * INTERNAL: Do not use. + * + * Provides an implementation of global (interprocedural) data flow. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic +private import DataFlowImplSpecific::Public +private import DataFlowImplCommonPublic +import DataFlow /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + * An input configuration for data flow using flow state. This signature equals + * `StateConfigSig`, but requires explicit implementation of all predicates. */ -abstract class Configuration extends string { +signature module FullStateConfigSig { bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } + class FlowState; /** * Holds if `source` is a relevant data flow source with the given initial * `state`. */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } + predicate isSource(Node source, FlowState state); /** * Holds if `sink` is a relevant data flow sink accepting `state`. */ - predicate isSink(Node sink, FlowState state) { none() } + predicate isSink(Node sink, FlowState state); /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. */ - predicate isBarrier(Node node) { none() } + predicate isBarrier(Node node); /** * Holds if data flow through `node` is prohibited when the flow state is * `state`. */ - predicate isBarrier(Node node, FlowState state) { none() } + predicate isBarrier(Node node, FlowState state); /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } + predicate isBarrierIn(Node node); /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + predicate isBarrierOut(Node node); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + predicate isAdditionalFlowStep(Node node1, Node node2); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); /** * Holds if an arbitrary number of implicit read steps of content `c` may be * taken at `node`. */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } + predicate allowImplicitRead(Node node, ContentSet c); /** * Gets the virtual dispatch branching limit when calculating field flow. * This can be overridden to a smaller value to improve performance (a * value of 0 disables field flow), or a larger value to get more results. */ - int fieldFlowBranchLimit() { result = 2 } + int fieldFlowBranchLimit(); /** * Gets a data flow configuration feature to add restrictions to the set of @@ -144,1720 +84,685 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ - FlowFeature getAFeature() { none() } + FlowFeature getAFeature(); /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } + predicate sourceGrouping(Node source, string sourceGroup); /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } + predicate sinkGrouping(Node sink, string sinkGroup); /** * Holds if hidden nodes should be included in the data flow graph. * * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). + * is not visualized (as it is in a `path-problem` query). */ - predicate includeHiddenNodes() { none() } + predicate includeHiddenNodes(); +} - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } +/** + * Provides default `FlowState` implementations given a `StateConfigSig`. + */ +module DefaultState { + class FlowState = Unit; - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() + predicate isSource(Node source, FlowState state) { Config::isSource(source) and exists(state) } + + predicate isSink(Node sink, FlowState state) { Config::isSink(sink) and exists(state) } + + predicate isBarrier(Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() } } /** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. + * Constructs a data flow computation given a full input configuration. */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } +module Impl { + private class FlowState = Config::FlowState; - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} + private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + Config::allowImplicitRead(n, _) and hasRead = [false, true] + } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false + private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") } - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) } pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) } pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } + } + + private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + } + + private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + } + + private predicate inBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierIn(n) and + Config::isSource(n, _) + ) + } + + private predicate outBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierOut(n) and + Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate fullBarrier(NodeEx node) { + exists(Node n | node.asNode() = n | + Config::isBarrier(n) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + Config::isBarrierIn(n) and + not Config::isSource(n, _) + or + Config::isBarrierOut(n) and + not Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate stateBarrier(NodeEx node, FlowState state) { + exists(Node n | node.asNode() = n | Config::isBarrier(n, state)) + } + + pragma[nomagic] + private predicate sourceNode(NodeEx node, FlowState state) { + Config::isSource(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + pragma[nomagic] + private predicate sinkNode(NodeEx node, FlowState state) { + Config::isSink(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + /** Provides the relevant barriers for a step from `node1` to `node2`. */ + pragma[inline] + private predicate stepFilter(NodeEx node1, NodeEx node2) { + not outBarrier(node1) and + not inBarrier(node2) and + not fullBarrier(node1) and + not fullBarrier(node2) + } + + /** + * Holds if data can flow in one local step from `node1` to `node2`. + */ + private predicate localFlowStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1) + ) + } + + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2) + ) + } + + private predicate additionalLocalStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) + ) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ + private predicate jumpStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ + private predicate additionalJumpStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate additionalJumpStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + pragma[nomagic] + private predicate readSetEx(NodeEx node1, ContentSet c, NodeEx node2) { + readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and + stepFilter(node1, node2) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + Config::allowImplicitRead(n, c) + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate read(NodeEx node1, Content c, NodeEx node2) { + exists(ContentSet cs | + readSetEx(node1, cs, node2) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate clearsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + clearsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate expectsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + expectsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + pragma[nomagic] + private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } + + pragma[nomagic] + private predicate hasReadStep(Content c) { read(_, c, _) } + + pragma[nomagic] + private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { + store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), + contentType) and + hasReadStep(tc.getContent()) and + stepFilter(node1, node2) + } + + pragma[nomagic] + private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) + } + + pragma[nomagic] + private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) + } + + /** + * Holds if field flow should be used for the given configuration. + */ + private predicate useFieldFlow() { Config::fieldFlowBranchLimit() >= 1 } + + private predicate hasSourceCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate sourceCallCtx(CallContext cc) { + if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny + } + + private predicate hasSinkCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if flow from `p` to a return node of kind `kind` is allowed. + * + * We don't expect a parameter to return stored in itself, unless + * explicitly allowed + */ + bindingset[p, kind] + private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { + exists(ParameterPosition pos | p.isParameterOf(_, pos) | + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + allowParameterReturnInSelfCached(p.asNode()) + ) + } + + private module Stage1 implements StageSig { + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } + + private class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + pragma[assume_small_delta] + private predicate fwdFlow(NodeEx node, Cc cc) { + sourceNode(node, _) and + if hasSourceCallCtx() then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc) | + localFlowStepEx(mid, node) or + additionalLocalFlowStep(mid, node) or + additionalLocalStateStep(mid, _, node, _) ) or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + exists(NodeEx mid | fwdFlow(mid, _) and cc = false | + jumpStepEx(mid, node) or + additionalJumpStep(mid, node) or + additionalJumpStateStep(mid, _, node, _) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) + exists(NodeEx mid | + useFieldFlow() and + fwdFlow(mid, cc) and + storeEx(mid, _, node, _) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) + exists(ContentSet c | + fwdFlowReadSet(c, node, cc) and + fwdFlowConsCandSet(c, _) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) + fwdFlowIn(_, _, _, node) and + cc = true or // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) + fwdFlowOut(_, node, false) and + cc = false or // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) + exists(DataFlowCall call | + fwdFlowOutFromArg(call, node) and + fwdFlowIsEntered(call, cc) ) } + // inline to reduce the number of iterations pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and + private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { + // call context cannot help reduce virtual dispatch + fwdFlow(arg, cc) and + viableParamArgEx(call, p, arg) and + not fullBarrier(p) and ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) + cc = false + or + cc = true and + not reducedViableImplInCallContext(call, _, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil + // call context may help reduce virtual dispatch + exists(DataFlowCallable target | + fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and + target = viableImplInSomeFwdFlowCallContextExt(call) and + cc = true ) - or + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc) { fwdFlowIn(call, _, cc, _) } + + pragma[nomagic] + private predicate fwdFlowInReducedViableImplInSomeCallContext( + DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target + ) { + fwdFlow(arg, true) and + viableParamArgEx(call, p, arg) and + reducedViableImplInCallContext(call, _, _) and + target = p.getEnclosingCallable() and + not fullBarrier(p) + } + + /** + * Gets a viable dispatch target of `call` in the context `ctx`. This is + * restricted to those `call`s for which a context might make a difference, + * and to `ctx`s that are reachable in `fwdFlow`. + */ + pragma[nomagic] + private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { + exists(DataFlowCall ctx | + fwdFlowIsEntered(ctx, _) and + result = viableImplInCallContextExt(call, ctx) + ) + } + + private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + + pragma[nomagic] + private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() + fwdFlow(mid, cc) and + readSetEx(mid, c, node) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node) and + useFieldFlow() and + fwdFlow(mid, _) and + storeEx(mid, tc, node, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `cs` may be interpreted in a read as the target of some store + * into `c`, in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCandSet(ContentSet cs, Content c) { + fwdFlowConsCand(c) and + c = cs.getAReadContent() + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc) { + exists(RetNodeEx ret | + fwdFlow(ret, cc) and + ret.getReturnPosition() = pos + ) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out) { + fwdFlowOut(call, out, true) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2) or + additionalJumpStateStep(node1, state1, _, state2) + | + fwdFlow(node1) + ) + } + + private predicate fwdFlowState(FlowState state) { + sourceNode(_, state) + or + exists(FlowState state0 | + fwdFlowState(state0) and + stateStepFwd(state0, state) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + private predicate revFlow(NodeEx node, boolean toReturn) { + revFlow0(node, toReturn) and + fwdFlow(node) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn) { + exists(FlowState state | + fwdFlow(node) and + sinkNode(node, state) and + fwdFlowState(state) and + if hasSinkCallCtx() then toReturn = true else toReturn = false ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, toReturn) | + localFlowStepEx(node, mid) or + additionalLocalFlowStep(node, mid) or + additionalLocalStateStep(node, _, mid, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, _) and toReturn = false | + jumpStepEx(node, mid) or + additionalJumpStep(node, mid) or + additionalJumpStateStep(node, _, mid, _) ) or // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) + exists(Content c | + revFlowStore(c, node, toReturn) and + revFlowConsCand(c) ) or // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) + exists(NodeEx mid, ContentSet c | + readSetEx(node, c, mid) and + fwdFlowConsCandSet(c, _) and + revFlow(mid, toReturn) ) or // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) + revFlowIn(_, node, false) and + toReturn = false or // flow out of a callable exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) + revFlowOut(pos) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + or + // flow through a callable + exists(DataFlowCall call | + revFlowInToReturn(call, node) and + revFlowIsReturned(call, toReturn) ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c } /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. + * Holds if `c` is the target of a read in the flow covered by `revFlow`. */ pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) + private predicate revFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, ContentSet cs | + fwdFlow(node) and + readSetEx(node, cs, mid) and + fwdFlowConsCandSet(cs, c) and + revFlow(pragma[only_bind_into](mid), _) ) } pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn) and + fwdFlowConsCand(c) and + storeEx(node, tc, mid, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + pragma[nomagic] + additional predicate revFlowIsReadAndStored(Content c) { + revFlowConsCand(c) and + revFlowStore(c, _, _) + } + + pragma[nomagic] + additional predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + fwdFlowReturnPosition(pos, _) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos) { + exists(NodeEx out | + revFlow(out, _) and + viableReturnPosOutNodeCandFwd1(_, pos, out) ) } pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) + additional predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + fwdFlowIn(call, arg, _, p) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate revFlowIn(DataFlowCall call, ArgNodeEx arg, boolean toReturn) { + exists(ParamNodeEx p | + revFlow(p, toReturn) and + viableParamArgNodeCandFwd1(call, p, arg) + ) } pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg) { + revFlowIn(call, arg, true) } /** @@ -1866,896 +771,1717 @@ private module MkStage { * reaching an argument of `call`. */ pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn) { + exists(NodeEx out | + revFlow(out, toReturn) and + fwdFlowOutFromArg(call, out) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2) or + additionalJumpStateStep(node1, state1, node2, state2) + | + revFlow(node1, _) and + revFlow(node2, _) and + fwdFlowState(state1) and + fwdFlowState(state2) + ) + } + + pragma[nomagic] + additional predicate revFlowState(FlowState state) { + exists(NodeEx node | + sinkNode(node, state) and + revFlow(node, _) and + fwdFlowState(state) + ) + or + exists(FlowState state0 | + revFlowState(state0) and + stateStepRev(state, state0) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) + exists(Content c | + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, node2, contentType) and + c = tc.getContent() and + exists(ap1) ) } pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() + predicate readStepCand(NodeEx n1, Content c, NodeEx n2) { + revFlowIsReadAndStored(c) and + read(n1, c, n2) and + revFlow(n2) + } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { + revFlow(node) and + exists(ap) + } + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap) { + revFlow(node, _) and + exists(state) and + exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node) { + revFlow(node, true) and + fwdFlow(node, true) and + not inBarrier(node) and + not outBarrier(node) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(DataFlowCallable c, ReturnKindExt kind | + throughFlowNodeCand(p) and + returnFlowCallableNodeCand(c, kind) and + p.getEnclosingCallable() = c and + exists(ap) and + parameterFlowThroughAllowed(p, kind) ) } pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + throughFlowNodeCand(ret) and + kind = ret.getKind() and + exists(argAp) and + exists(ap) } pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn) and + revFlowInToReturn(call, arg) and + revFlowIsReturned(call, toReturn) ) } additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) + nodes = count(NodeEx node | fwdFlow(node)) and + fields = count(Content f0 | fwdFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b)) or fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) + nodes = count(NodeEx node | revFlow(node, _)) and + fields = count(Content f0 | revFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b)) } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } + /* End: Stage 1 logic. */ } - class CcCall extends Cc { - CcCall() { this = true } + pragma[noinline] + private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + localFlowStepEx(node1, node2) } - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + additionalLocalFlowStep(node1, node2) } - Cc ccNone() { result = false } + pragma[nomagic] + private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { + Stage1::revFlow(out) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) + } - CcCall ccSomeCall() { result = true } + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out + ) { + exists(ReturnPosition pos | + viableReturnPosOutNodeCand1(call, pos, out) and + pos = ret.getReturnPosition() and + kind = pos.getKind() and + Stage1::revFlow(ret) and + not outBarrier(ret) and + not inBarrier(out) + ) + } - class LocalCc = Unit; + pragma[nomagic] + private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg) and + Stage1::revFlow(arg) + } - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { + viableParamArgNodeCand1(call, p, arg) and + Stage1::revFlow(p) and + not outBarrier(arg) and + not inBarrier(p) + } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} + /** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int branch(NodeEx n1) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) + } -private module Level1CallContext { - class Cc = CallContext; + /** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int join(NodeEx n2) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) + } - class CcCall = CallContextCall; + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, ret, kind, out) and + exists(int b, int j | + b = branch(ret) and + j = join(out) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, arg, p) and + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - class CcNoCall = CallContextNoCall; + private signature module StageSig { + class Ap; - Cc ccNone() { result instanceof CallContextAny } + predicate revFlow(NodeEx node); - CcCall ccSomeCall() { result instanceof CallContextSomeCall } + predicate revFlowAp(NodeEx node, Ap ap); + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap); + + predicate callMayFlowThroughRev(DataFlowCall call); + + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap); + + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ); + + predicate readStepCand(NodeEx n1, Content c, NodeEx n2); + } + + private module MkStage { + class ApApprox = PrevStage::Ap; + + signature module StageParam { + class Ap; + + class ApNil extends Ap; + + bindingset[result, ap] + ApApprox getApprox(Ap ap); + + ApNil getApNil(NodeEx node); + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail); + + /** + * An approximation of `Content` that corresponds to the precision level of + * `Ap`, such that the mappings from both `Ap` and `Content` to this type + * are functional. + */ + class ApHeadContent; + + ApHeadContent getHeadContent(Ap ap); + + ApHeadContent projectToHeadContent(Content c); + + class ApOption; + + ApOption apNone(); + + ApOption apSome(Ap ap); + + class Cc; + + class CcCall extends Cc; + + // TODO: member predicate on CcCall + predicate matchesCall(CcCall cc, DataFlowCall call); + + class CcNoCall extends Cc; + + Cc ccNone(); + + CcCall ccSomeCall(); + + class LocalCc; + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc); + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ); + + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ); + + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ); + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap); + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType); + } + + module Stage implements StageSig { + import Param + + /* Begin: Stage logic. */ + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + private predicate revFlowApAlias(NodeEx node, ApApprox apa) { + PrevStage::revFlowAp(node, apa) + } + + pragma[nomagic] + private predicate flowIntoCallApa( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa + ) { + flowIntoCall(call, arg, p, allowsFieldFlow) and + PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and + revFlowApAlias(arg, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowOutOfCallApa( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + ApApprox apa + ) { + flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and + PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and + revFlowApAlias(ret, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + ApApprox argApa, ApApprox apa + ) { + exists(ReturnKindExt kind | + flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + ) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `summaryCtx` and `argAp` record the + * corresponding parameter position and access path of that argument, respectively. + */ + pragma[nomagic] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, ap) + } + + pragma[inline] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + ) { + fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + sourceNode(node, state) and + (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + summaryCtx = TParamNodeNone() and + ap = getApNil(node) and + apa = getApprox(ap) + or + exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + localCc = getLocalCc(mid, cc) + | + localStep(mid, state0, node, state, true, _, localCc) and + ap = ap0 and + apa = apa0 + or + localStep(mid, state0, node, state, false, ap, localCc) and + ap0 instanceof ApNil and + apa = getApprox(ap) + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + jumpStepEx(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, _, nil) and + additionalJumpStep(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, _, nil) and + additionalJumpStateStep(mid, state0, node, state) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + ap = apCons(tc, ap0) and + apa = getApprox(ap) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(ap0, c, ap) and + apa = getApprox(ap) + ) + or + // flow into a callable + fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + if PrevStage::parameterMayFlowThrough(node, apa) + then ( + summaryCtx = TParamNodeSome(node.asNode()) and + argAp = apSome(ap) + ) else ( + summaryCtx = TParamNodeNone() and argAp = apNone() + ) + or + // flow out of a callable + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and + inner = ret.getEnclosingCallable() and + cc = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + or + // flow through a callable + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(DataFlowType contentType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, _) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate readStepCand(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + PrevStage::readStepCand(node1, c, node2) and + apc = projectToHeadContent(c) + } + + bindingset[node1, apc] + pragma[inline_late] + private predicate readStepCand0(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + readStepCand(node1, apc, c, node2) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + apc = getHeadContent(ap) and + readStepCand0(node1, apc, c, node2) + ) + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg( + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + ApApprox argApa, Ap ap, ApApprox apa + ) { + exists(ReturnKindExt kind | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + + pragma[inline] + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + } + + pragma[nomagic] + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap + ) { + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa)) and + PrevStage::parameterMayFlowThrough(p, apa) and + PrevStage::callMayFlowThroughRev(call) + ) + } + + pragma[nomagic] + private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + } + + private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(ap1, c, ap2) + } + + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa) + } + + pragma[nomagic] + private predicate returnFlowsThrough( + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + Ap ap + ) { + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap + ) { + exists(ApApprox argApa | + flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), + allowsFieldFlow, argApa) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + if allowsFieldFlow = false then argAp instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowIntoCallAp( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap + ) { + exists(ApApprox apa | + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + fwdFlow(arg, _, _, _, _, ap, apa) + ) + } + + pragma[nomagic] + private predicate flowOutOfCallAp( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, + Ap ap + ) { + exists(ApApprox apa | + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and + fwdFlow(ret, _, _, _, _, ap, apa) and + pos = ret.getReturnPosition() + ) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink. + * + * The parameter `returnCtx` records whether (and how) the node must be returned + * from the enclosing callable in order to reach a sink, and if so, `returnAp` + * records the access path of the returned value. + */ + pragma[nomagic] + additional predicate revFlow( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + revFlow0(node, state, returnCtx, returnAp, ap) and + fwdFlow(node, state, _, _, _, ap) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + fwdFlow(node, state, _, _, _, ap) and + sinkNode(node, state) and + ( + if hasSinkCallCtx() + then returnCtx = TReturnCtxNoFlowThrough() + else returnCtx = TReturnCtxNone() + ) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, nil) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStepEx(node, mid) and + revFlow(mid, state, _, _, ap) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStep(node, mid) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStateStep(node, state, mid, state0) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowConsCand(ap0, c, ap) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, returnCtx, returnAp, ap0) and + readStepFwd(node, ap, _, mid, ap0) + ) + or + // flow into a callable + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, TReturnCtxNone(), returnAp, ap) and + flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and + (if allowsFieldFlow = false then ap instanceof ApNil else any()) and + returnCtx = TReturnCtxNone() + ) + or + // flow through a callable + exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap) and + if returnFlowsThrough(node, pos, state, _, _, _, ap) + then ( + returnCtx = TReturnCtxMaybeFlowThrough(pos) and + returnAp = apSome(ap) + ) else ( + returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() + ) + ) + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + ReturnCtx returnCtx, ApOption returnAp + ) { + revFlow(mid, state, returnCtx, returnAp, ap0) and + storeStepFwd(node, ap, tc, mid, ap0) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, + ApOption returnAp, Ap ap + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, returnCtx, returnAp, ap) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowParamToReturn( + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap + ) { + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap)) + } + + pragma[nomagic] + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp + ) { + revFlowParamToReturn(p, state, pos, innerReturnAp, ap) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + matchesCall(ccc, call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ) { + exists(Ap ap2, Content c | + PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowConsCand(ap2, c, ap1) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and + readStepFwd(node1, ap1, c, node2, ap2) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + ) + } + + additional predicate revFlow(NodeEx node, FlowState state) { revFlow(node, state, _, _, _) } + + predicate revFlow(NodeEx node, FlowState state, Ap ap) { revFlow(node, state, _, _, ap) } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _, _, _, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) { + revFlow(node, state, ap) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + + private predicate validAp(Ap ap) { + revFlow(_, _, _, _, ap) and ap instanceof ApNil + or + exists(TypedContent head, Ap tail | + consCand(head, tail) and + ap = apCons(head, tail) + ) + } + + additional predicate consCand(TypedContent tc, Ap ap) { + revConsCand(tc, ap) and + validAp(ap) + } + + pragma[nomagic] + private predicate parameterFlowsThroughRev( + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp + ) { + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap) and + parameterFlowThroughAllowed(p, pos.getKind()) + } + + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(ReturnPosition pos | + returnFlowsThrough(_, pos, _, _, p, ap, _) and + parameterFlowsThroughRev(p, ap, pos, _) + ) + } + + pragma[nomagic] + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + parameterFlowsThroughRev(p, argAp, pos, ap) and + kind = pos.getKind() + ) + } + + pragma[nomagic] + private predicate revFlowThroughArg( + DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, + Ap ap + ) { + exists(ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(arg, state, returnCtx, returnAp, ap) and + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap) + ) + } + + additional predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and + fields = count(TypedContent f0 | consCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + states = count(FlowState state | revFlow(_, state, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | + revFlow(n, state, returnCtx, retAp, ap) + ) + } + /* End: Stage logic. */ + } + } + + private module BooleanCallContext { + class Cc extends boolean { + Cc() { this in [true, false] } + } + + class CcCall extends Cc { + CcCall() { this = true } + } + + /** Holds if the call context may be `call`. */ + predicate matchesCall(CcCall cc, DataFlowCall call) { any() } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } - module NoLocalCallContext { class LocalCc = Unit; bindingset[node, cc] LocalCc getLocalCc(NodeEx node, Cc cc) { any() } bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + } + + private module Level1CallContext { + class Cc = CallContext; + + class CcCall = CallContextCall; + + pragma[inline] + predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + module NoLocalCallContext { + class LocalCc = Unit; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + module LocalCallContext { + class LocalCc = LocalCallContext; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() } } - module LocalCallContext { - class LocalCc = LocalCallContext; + private module Stage2Param implements MkStage::StageParam { + private module PrevStage = Stage1; - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) + class Ap extends boolean { + Ap() { this in [true, false] } } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + class ApNil extends Ap { + ApNil() { this = false } } + + bindingset[result, ap] + PrevStage::Ap getApprox(Ap ap) { any() } + + ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + class ApHeadContent = Unit; + + pragma[inline] + ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + + ApHeadContent projectToHeadContent(Content c) { any() } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2) + ) and + exists(ap) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + predicate flowIntoCall = flowIntoCallNodeCand1/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::revFlowIsReadAndStored(c) and + expectsContentEx(node, c) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + PrevStage::revFlowState(state) and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + ap = true and + expectsContentCand(node) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + private module Stage2 implements StageSig { + import MkStage::Stage } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) + private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) + pragma[nomagic] + private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) + private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) or + expectsContentCached(this.asNode(), _) + } } - } - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowEntry(NodeEx node, FlowState state) { + Stage2::revFlow(node, state) and + ( + sourceNode(node, state) + or + jumpStepEx(_, node) + or + additionalJumpStep(_, node) + or + additionalJumpStateStep(_, _, node, state) + or + node instanceof ParamNodeEx + or + node.asNode() instanceof OutNodeExt + or + Stage2::storeStepCand(_, _, _, node, _) + or + Stage2::readStepCand(_, _, node) + or + node instanceof FlowCheckNode + or + exists(FlowState s | + additionalLocalStateStep(_, s, node, state) and + s != state + ) + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state) { + exists(NodeEx next | Stage2::revFlow(next, state) | + jumpStepEx(node, next) or + additionalJumpStep(node, next) or + flowIntoCallNodeCand2(_, node, next, _) or + flowOutOfCallNodeCand2(_, node, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _) or + Stage2::readStepCand(node, _, next) + ) or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s) | + additionalJumpStateStep(node, state, next, s) + or + additionalLocalStateStep(node, state, next, s) and s != state ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } + Stage2::revFlow(node, state) and + node instanceof FlowCheckNode + or + sinkNode(node, state) + } - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false) + or + additionalLocalStateStep(node1, state1, node2, state2) and + Stage2::revFlow(node1, state1, false) and + Stage2::revFlowAlias(node2, state2, false) + } - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, + LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + localFlowEntry(node1, pragma[only_bind_into](state)) and + ( + localFlowStepNodeCand1(node1, node2) and + preservesValue = true and + t = node1.getDataFlowType() and // irrelevant dummy value + Stage2::revFlow(node2, pragma[only_bind_into](state)) + or + additionalLocalFlowStepNodeCand2(node1, state, node2, state) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + exists(NodeEx mid | + localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and + localFlowStepNodeCand1(mid, node2) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state)) + ) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state, mid, _, _, cc) and + additionalLocalFlowStepNodeCand2(mid, state, node2, state) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() + ) ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and + localFlowExit(node2, state1) and + state1 = state2 or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and + state1 != state2 and + preservesValue = false and + t = node2.getDataFlowType() and + callContext.relevantFor(node1.getEnclosingCallable()) and + not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | + isUnreachableInCallCached(node1.asNode(), call) or + isUnreachableInCallCached(node2.asNode(), call) ) + } + } + + private import LocalFlowBigStep + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + predicate projectToHeadContent = getContentApprox/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + import BooleanCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApproxAccessPathFrontNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + predicate flowIntoCall = flowIntoCallNodeCand2/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage3 implements StageSig { + import MkStage::Stage + } + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import BooleanCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and + exists(lcc) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + not clear(node, ap) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage4 implements StageSig { + import MkStage::Stage + } + + /** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ + private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { + exists(AccessPathFront apf | + Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) ) } /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() + private predicate expensiveLen2unfolding(TypedContent tc) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage4::consCand(tc, TFrontNil(t)) and + not expensiveLen2unfolding(tc) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage4::consCand(tc1, TFrontHead(tc2)) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc) + } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) + /** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ + abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} + private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; -private module Stage3 implements StageSig { - import MkStage::Stage -} + AccessPathApproxNil() { this = TNil(t) } -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; + override string toString() { result = concat(": " + ppReprType(t)) } - class Ap = AccessPathFront; + override TypedContent getHead() { none() } - class ApNil = AccessPathFrontNil; + override int len() { result = 0 } - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + override DataFlowType getType() { result = t } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + abstract private class AccessPathApproxCons extends AccessPathApprox { } - class ApHeadContent = Content; + private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + AccessPathApproxConsNil() { this = TConsNil(tc, t) } - ApHeadContent projectToHeadContent(Content c) { result = c } + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } - class ApOption = AccessPathFrontOption; + override TypedContent getHead() { result = tc } - ApOption apNone() { result = TAccessPathFrontNone() } + override int len() { result = 1 } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + override DataFlowType getType() { result = tc.getContainerType() } - import BooleanCallContext + override AccessPathFront getFront() { result = TFrontHead(tc) } - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } } - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } + override TypedContent getHead() { result = tc1 } - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } + override int len() { result = len } - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } + override DataFlowType getType() { result = tc1.getContainerType() } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + override AccessPathFront getFront() { result = TFrontHead(tc1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( result = TConsCons(tc2, _, len - 1) or len = 2 and @@ -2763,1561 +2489,581 @@ private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { or result = TCons1(tc2, len - 1) ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) + } + } + + private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage4::consCand(tc, TFrontNil(t)) and + result = TNil(t) + ) ) - ) + } } -} -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + /** Gets the access path obtained by popping `tc` from `ap`, if any. */ + private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto `ap`. */ + private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) + private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } } -} -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; + private module Stage5Param implements MkStage::StageParam { + private module PrevStage = Stage4; - class Ap = AccessPathApprox; + class Ap = AccessPathApprox; - class ApNil = AccessPathApproxNil; + class ApNil = AccessPathApproxNil; + + pragma[nomagic] + PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + import Level1CallContext + import LocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + } + + private module Stage5 = MkStage::Stage; pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc + private predicate nodeMayUseSummary0( + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + exists(AccessPathApprox apa0 | + Stage5::parameterMayFlowThrough(p, _) and + Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + TAccessPathApproxSome(apa), apa0) ) } pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + private predicate nodeMayUseSummary(NodeEx n, FlowState state, AccessPathApprox apa) { + exists(ParamNodeEx p | + Stage5::parameterMayFlowThrough(p, apa) and + nodeMayUseSummary0(n, p, state, apa) ) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + Stage5::parameterMayFlowThrough(p, ap.getApprox()) and + Stage5::revFlow(p, state, _) + } - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} + /** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ + abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); + } -private module Stage5 = MkStage::Stage; + /** A summary context from which no flow summary can be generated. */ + private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } + } -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} + /** A summary context from which a flow summary can be generated. */ + private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ + private int count1to2unfold(AccessPathApproxCons1 apa) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + ) ) } -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and + private int countNodesUsingAccessPath(AccessPathApprox apa) { result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) + strictcount(NodeEx n, FlowState state | + Stage5::revFlow(n, state, apa) or nodeMayUseSummary(n, state, apa) ) - ) -} + } -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else + /** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ + private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa) { exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and + aps = count1to2unfold(apa) and + nodes = countNodesUsingAccessPath(apa) and accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() + apLimit < aps and + tupleLimit < (aps - 1) * nodes ) } -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() + private AccessPathApprox getATail(AccessPathApprox apa) { + exists(TypedContent head | + apa.pop(head) = result and + Stage5::consCand(head, result) ) } -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" + /** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ + private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { + if apa.getHead().forceHighPrecision() + then unfold = true else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa) and + nodes = countNodesUsingAccessPath(apa) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) + /** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ + pragma[assume_small_delta] + private int countAps(AccessPathApprox apa) { + evalUnfold(apa, false) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa)) or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" + evalUnfold(apa, false) and + result = count1to2unfold(apa) and + not expensiveLen1to2unfolding(apa) or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) + evalUnfold(apa, true) and + result = countPotentialAps(apa) } - private string ppCtx() { - this instanceof PathNodeSink and result = "" + /** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ + language[monotonicAggregates] + pragma[assume_small_delta] + private int countPotentialAps(AccessPathApprox apa) { + apa instanceof AccessPathApproxNil and result = 1 or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) + private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false) and + head = apa.getHead() and + tail.getApprox() = getATail(apa) + ) } or - TCallableSrc() or - TCallableSink() + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + not expensiveLen1to2unfolding(apa) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + expensiveLen1to2unfolding(apa) and + apa.len() = len and + head = apa.getHead() + ) + } - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + private newtype TPathNode = + pragma[assume_small_delta] + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + // A PathNode is introduced by a source ... + Stage5::revFlow(node, state) and + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + pathStep(_, node, state, cc, sc, ap) and + Stage5::revFlow(node, state, ap.getApprox()) + } or + TPathNodeSink(NodeEx node, FlowState state) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() + ) + } or + TPathNodeSourceGroup(string sourceGroup) { + exists(PathNodeImpl source | sourceGroup = source.getSourceGroup()) + } or + TPathNodeSinkGroup(string sinkGroup) { + exists(PathNodeSink sink | sinkGroup = sink.getSinkGroup()) + } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the * tracked object. The final type indicates the type of the tracked object. */ - private class PartialAccessPath extends TPartialAccessPath { + private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() } - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } } - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } } - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + pragma[assume_small_delta] + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + pragma[assume_small_delta] + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } - } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) } } - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) + private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage5::consCand(head1, result.getApprox()) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = + "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } } - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) + private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } + AccessPathCons1() { this = TAccessPathCons1(head, len) } - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + override TypedContent getHead() { result = head } - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) + override AccessPath getTail() { + Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + } - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + override AccessPathFrontHead getFront() { result = TFrontHead(head) } - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } + } + + abstract private class PathNodeImpl extends TPathNode { + /** Gets the `FlowState` of this node. */ + abstract FlowState getState(); + + /** Holds if this node is a source. */ + abstract predicate isSource(); + + abstract PathNodeImpl getASuccessorImpl(); + + private PathNodeImpl getASuccessorIfHidden() { + this.isHidden() and + result = this.getASuccessorImpl() + } + + pragma[nomagic] + private PathNodeImpl getANonHiddenSuccessor0() { + result = this.getASuccessorIfHidden*() and + not result.isHidden() + } + + final PathNodeImpl getANonHiddenSuccessor() { + result = this.getASuccessorImpl().getANonHiddenSuccessor0() and + not this.isHidden() + } + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + not Config::includeHiddenNodes() and ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + ) } - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } + string getSourceGroup() { + this.isSource() and + Config::sourceGrouping(this.getNodeEx().asNode(), result) + } + + predicate isFlowSource() { + this.isSource() and not exists(this.getSourceGroup()) + or + this instanceof PathNodeSourceGroup + } + + predicate isFlowSink() { + this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or + this instanceof PathNodeSinkGroup + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { /** Gets a textual representation of this element. */ string toString() { result = this.getNodeEx().toString() + this.ppAp() } @@ -4341,305 +3087,335 @@ private module FlowExploration { ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + } + + /** Holds if `n` can reach a sink. */ + private predicate directReach(PathNodeImpl n) { + n instanceof PathNodeSink or + n instanceof PathNodeSinkGroup or + directReach(n.getANonHiddenSuccessor()) + } + + /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ + private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } + + /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ + private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { + n1.getANonHiddenSuccessor() = n2 and directReach(n2) + } + + private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } + final Node getNode() { super.getNodeEx().projectToNode() = result } - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) } - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group) } } /** * Provides the query predicates needed to include a graph in a path-problem query. */ - module PartialPathGraph { + module PathGraph implements PathGraphSig { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) + } } - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + /** + * An intermediate flow graph node. This is a tuple consisting of a `Node`, + * a `FlowState`, a `CallContext`, a `SummaryCtx`, and an `AccessPath`. + */ + private class PathNodeMid extends PathNodeImpl, TPathNodeMid { NodeEx node; FlowState state; CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; + SummaryCtx sc; + AccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } CallContext getCallContext() { result = cc } - TSummaryCtx1 getSummaryCtx1() { result = sc1 } + SummaryCtx getSummaryCtx() { result = sc } - TSummaryCtx2 getSummaryCtx2() { result = sc2 } + AccessPath getAp() { result = ap } - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) } - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + } + + predicate isAtSink() { + sinkNode(node, state) and + ap instanceof AccessPathNil and + if hasSinkCallCtx() + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state } } - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + /** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ + private class PathNodeSink extends PathNodeImpl, TPathNodeSink { NodeEx node; FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + PathNodeSink() { this = TPathNodeSink(node, state) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) } - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + override predicate isSource() { sourceNode(node, state) } - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) } + } - RevPartialAccessPath getAp() { result = ap } + private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { + string sourceGroup; - override Configuration getConfiguration() { result = config } + PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup) } - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } + override NodeEx getNodeEx() { none() } - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup } + + override predicate isSource() { none() } + + override string toString() { result = sourceGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 } } - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { + string sinkGroup; + + PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup) } + + override NodeEx getNodeEx() { none() } + + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { none() } + + override predicate isSource() { none() } + + override string toString() { result = sinkGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 + } + } + + private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + LocalCallContext localCC ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and + midnode = mid.getNodeEx() and state = mid.getState() and cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() } - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + /** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) + or + exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + state = mid.getState() and + cc = mid.getCallContext() } pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config + private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + state = mid.getState() and + cc = mid.getCallContext() } - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() + apa = mid.getAp().getApprox() } pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + pathOutOfCallable0(mid, pos, state, innercc, apa) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4648,53 +3424,86 @@ private module FlowExploration { ) } - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) + pragma[noinline] + private NodeEx getAnOutNodeFlow(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa) { + result.asNode() = kind.getAnOutNode(call) and + Stage5::revFlow(result, _, apa) + } + + /** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ + pragma[noinline] + private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa | + pathOutOfCallable1(mid, call, kind, state, cc, apa) and + out = getAnOutNodeFlow(kind, call, apa) ) } + /** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and parameterMatch(ppos, apos) ) } pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) + exists(ParamNodeEx p | + Stage5::revFlow(p, _, apa) and + p.isParameterOf(callable, pos) + ) } - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config + pragma[nomagic] + private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) + ) + } + + /** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ + pragma[nomagic] + private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call + ) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4702,252 +3511,1108 @@ private module FlowExploration { ) } + /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and + exists(RetNodeEx ret | + pathNode(_, ret, state, cc, sc, ap, _) and kind = ret.getKind() and + apa = ap.getApprox() and + parameterFlowThroughAllowed(sc.getParamNode(), kind) + ) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa + ) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa) + ) + } + + /** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ + pragma[noinline] + private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + out = getAnOutNodeFlow(kind, call, apa) + ) + } + + private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _) and + not arg.isHidden() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, + AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _) or + storeEx(n1, _, n2, _) or + readSetEx(n1, _, n2) + ) + } + + pragma[nomagic] + private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { + succ = pred.getANonHiddenSuccessor() and + succNode = succ.getNodeEx() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + hasSuccessor(pragma[only_bind_into](arg), par, p) and + not ret.isHidden() and + pathNode(out0, o, sout, _, _, apout, _) + | + out = out0 or out = out0.projectToSink() + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNodeImpl n) { + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNodeImpl mid | + retReach(mid) and + n.getANonHiddenSuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } + } + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { + exists(PathNodeImpl flowsource, PathNodeImpl flowsink | + source = flowsource and sink = flowsink + | + flowsource.isFlowSource() and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.isFlowSink() + ) + } + + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { + flowsource.isSource() and + flowsource.getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink + } + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + + private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNodeImpl pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = + count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn) + } + + /** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ + predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples + ) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "5 Fwd" and + n = 50 and + Stage5::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and + n = 55 and + Stage5::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) + } + + module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { + exists(NodeEx node1, NodeEx node2 | + jumpStepEx(node1, node2) + or + additionalJumpStep(node1, node2) + or + additionalJumpStateStep(node1, _, node2, _) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c) { + exists(Node n | Config::isSource(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) + } + + private predicate interestingCallableSink(DataFlowCallable c) { + exists(Node n | Config::isSink(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c) { + interestingCallableSrc(c) or + interestingCallableSink(c) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2 | + callableStep(c1, c2) and + ce1 = TCallable(c1) and + ce2 = TCallable(c2) + ) + or + exists(Node n | + ce1 = TCallableSrc() and + Config::isSource(n, _) and + ce2 = TCallable(getNodeEnclosingCallable(n)) + ) + or + exists(Node n | + ce2 = TCallableSink() and + Config::isSink(n, _) and + ce1 = TCallable(getNodeEnclosingCallable(n)) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } + + private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state) or + sinkNode(_, state) or + additionalLocalStateStep(_, state, _, _) or + additionalLocalStateStep(_, _, _, state) or + additionalJumpStateStep(_, state, _, _) or + additionalJumpStateStep(_, _, _, state) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + distSrc(node.getEnclosingCallable()) <= explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap + ) { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(explorationLimit()) + or + revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and + not clearsContentEx(node, ap.getHead()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead()) + ) and + not fullBarrier(node) and + not stateBarrier(node, state) and + distSink(node.getEnclosingCallable()) <= explorationLimit() + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + not fullBarrier(node) and + not stateBarrier(node, state) and + not clearsContentEx(node, ap.getHead().getContent()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead().getContent()) + ) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { result = distSrc(this.getNodeEx().getEnclosingCallable()) } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { result = distSink(this.getNodeEx().getEnclosingCallable()) } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + } + + predicate isSource() { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp()) + } + + predicate isSink() { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + or + additionalLocalFlowStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + partialPathStoreStep(mid, _, _, node, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and + sc3 = mid.getSummaryCtx3() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + or + partialPathOutOfCallable(mid, node, state, cc, ap) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + storeEx(midNode, tc, node, contentType) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { + partialPathStoreStep(_, ap1, tc, _, ap2) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node) and + ap.getHead() = tc and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and ap = mid.getAp() - ) - } + } - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + | + out.asNode() = kind.getAnOutNode(call) + ) + } - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[nomagic] + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + ) { + localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and + ap = mid.getAp() + or + additionalLocalFlowStep(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + jumpStepEx(node, mid.getNodeEx()) and + state = mid.getState() and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and + ap = mid.getAp() + or + additionalJumpStep(node, mid.getNodeEx()) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } + sc3 = mid.getSummaryCtx3() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) + pragma[nomagic] + private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + revPartialPathReadStep(_, ap1, c, _, ap2) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + storeEx(node, tc, midNode, _) and + ap.getHead() = c and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } + + private predicate partialFlow(PartialPathNode source, PartialPathNode node) { + source.isFwdSource() and + node = source.getASuccessor+() + } + + private predicate revPartialFlow(PartialPathNode node, PartialPathNode sink) { + sink.isRevSink() and + node.getASuccessor+() = sink + } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink) and + dist = node.getSinkDistance() + } } } - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll new file mode 100644 index 00000000000..e6bdc74cceb --- /dev/null +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll @@ -0,0 +1,396 @@ +/** + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +private import DataFlowImpl +import DataFlowImplCommonPublic +import FlowStateString + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited. + */ + deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited when + * the flow state is `state` + */ + deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * DEPRECATED: Use `FlowExploration` instead. + * + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + deprecated int explorationLimit() { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (for example in a `path-problem` query). + */ + predicate includeHiddenNodes() { none() } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +/** A bridge class to access the deprecated `isBarrierGuard`. */ +private class BarrierGuardGuardedNodeBridge extends Unit { + abstract predicate guardedNode(Node n, Configuration config); + + abstract predicate guardedNode(Node n, FlowState state, Configuration config); +} + +private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { + deprecated override predicate guardedNode(Node n, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + } + + deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g, state) and + n = g.getAGuardedNode() + ) + } +} + +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) + or + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) + or + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) + or + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 + } + + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) + } + + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } + + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } + + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) + } + + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) + } + + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } +} + +private import Impl as I +import I + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof I::PathNode { + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { result = super.getNode() } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = getState(super.getState()) } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = getConfig(super.getState()) } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getASuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } + + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } + + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } +} + +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink + ) +} + +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config +} + +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } + +predicate flowsTo = hasFlow/3; diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll index 1b969756b09..e6bdc74cceb 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll index 5d3becc8078..d09fdcfca3e 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplCommon.qll @@ -3,15 +3,18 @@ private import DataFlowImplSpecific::Public import Cached module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; + /** Provides `FlowState = string`. */ + module FlowStateString { + /** A state value to track during data flow. */ + class FlowState = string; - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } + /** + * The default state, which is used when the state is unspecified for a source + * or a sink. + */ + class FlowStateEmpty extends FlowState { + FlowStateEmpty() { this = "" } + } } private newtype TFlowFeature = @@ -179,6 +182,7 @@ private module LambdaFlow { boolean toJump, DataFlowCallOption lastCall ) { revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and + not expectsContent(node, _) and if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode then compatibleTypes(t, getNodeDataFlowType(node)) else any() diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll index 1b969756b09..e6bdc74cceb 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index b65fb3d7d5d..f6cb63c1c75 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -390,3 +390,12 @@ class ContentApprox = Unit; /** Gets an approximated value for content `c`. */ pragma[inline] ContentApprox getContentApprox(Content c) { any() } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index e742493b5ca..40ec012cc27 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -2,8 +2,8 @@ * Provides Go-specific definitions for use in the data flow library. */ -import go -import semmle.go.dataflow.FunctionInputsAndOutputs +private import go +private import semmle.go.dataflow.FunctionInputsAndOutputs private import semmle.go.dataflow.ExternalFlow private import DataFlowPrivate private import FlowSummaryImpl as FlowSummaryImpl diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll index 468ed73e81a..e485a5be522 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImpl.qll @@ -301,8 +301,8 @@ module Private { TWithoutContentSummaryComponent(ContentSet c) or TWithContentSummaryComponent(ContentSet c) - private TParameterSummaryComponent thisParam() { - result = TParameterSummaryComponent(instanceParameterPosition()) + private TParameterSummaryComponent callbackSelfParam() { + result = TParameterSummaryComponent(callbackSelfParameterPosition()) } newtype TSummaryComponentStack = @@ -311,7 +311,7 @@ module Private { any(RequiredSummaryComponentStack x).required(head, tail) or any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and - head = thisParam() + head = callbackSelfParam() or derivedFluentFlowPush(_, _, _, head, tail, _) } @@ -336,7 +336,7 @@ module Private { callbackRef = s.drop(_) and (isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and input = callbackRef.tail() and - output = TConsSummaryComponentStack(thisParam(), input) and + output = TConsSummaryComponentStack(callbackSelfParam(), input) and preservesValue = true ) or @@ -439,6 +439,9 @@ module Private { out.head() = TParameterSummaryComponent(_) and s = out.tail() ) + or + // Add the post-update node corresponding to the requested argument node + outputState(c, s) and isCallbackParameter(s) } private newtype TSummaryNodeState = @@ -1012,7 +1015,7 @@ module Private { private predicate relevantSummaryElementGenerated( AccessPath inSpec, AccessPath outSpec, string kind ) { - summaryElement(this, inSpec, outSpec, kind, "generated") and + summaryElement(this, inSpec, outSpec, kind, ["generated", "ai-generated"]) and not summaryElement(this, _, _, _, "manual") } diff --git a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll index b71e1ae713d..7eedf1f911e 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/FlowSummaryImplSpecific.qll @@ -20,7 +20,7 @@ class SummarizedCallableBase = Callable; DataFlowCallable inject(SummarizedCallable c) { result.asCallable() = c } /** Gets the parameter position of the instance parameter. */ -ArgumentPosition instanceParameterPosition() { result = -1 } +ArgumentPosition callbackSelfParameterPosition() { result = -1 } /** Gets the textual representation of a parameter position in the format used for flow summaries. */ string getParameterPosition(ParameterPosition pos) { result = pos.toString() } diff --git a/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll new file mode 100644 index 00000000000..7f96fe5e6fb --- /dev/null +++ b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTracking.qll @@ -0,0 +1,64 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ + +import TaintTrackingParameter::Public +private import TaintTrackingParameter::Private + +private module AddTaintDefaults implements + DataFlowInternal::FullStateConfigSig +{ + import Config + + predicate isBarrier(DataFlow::Node node) { + Config::isBarrier(node) or defaultTaintSanitizer(node) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + Config::isAdditionalFlowStep(node1, node2) or + defaultAdditionalTaintStep(node1, node2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + Config::allowImplicitRead(node, c) + or + ( + Config::isSink(node, _) or + Config::isAdditionalFlowStep(node, _) or + Config::isAdditionalFlowStep(node, _, _, _) + ) and + defaultImplicitTaintRead(node, c) + } +} + +/** + * Constructs a standard taint tracking computation. + */ +module Make implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import DataFlowInternal::DefaultState + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} + +/** + * Constructs a taint tracking computation using flow state. + */ +module MakeWithState implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} diff --git a/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTrackingParameter.qll index b38482194ec..a5a45514a06 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/tainttracking1/TaintTrackingParameter.qll @@ -2,4 +2,5 @@ import semmle.go.dataflow.internal.TaintTrackingUtil as Public module Private { import semmle.go.dataflow.DataFlow::DataFlow as DataFlow + import semmle.go.dataflow.internal.DataFlowImpl as DataFlowInternal } diff --git a/go/ql/lib/semmle/go/frameworks/Chi.qll b/go/ql/lib/semmle/go/frameworks/Chi.qll index 89f1a41d350..d2dfee90ab0 100644 --- a/go/ql/lib/semmle/go/frameworks/Chi.qll +++ b/go/ql/lib/semmle/go/frameworks/Chi.qll @@ -21,7 +21,8 @@ private module Chi { * Methods that extract URL parameters, considered as a source of untrusted flow. */ private class UserControlledRequestMethod extends UntrustedFlowSource::Range, - DataFlow::MethodCallNode { + DataFlow::MethodCallNode + { UserControlledRequestMethod() { this.getTarget().hasQualifiedName(packagePath(), "Context", "URLParam") } diff --git a/go/ql/lib/semmle/go/frameworks/Encoding.qll b/go/ql/lib/semmle/go/frameworks/Encoding.qll index 34af4ce6ed7..0bb0152db83 100644 --- a/go/ql/lib/semmle/go/frameworks/Encoding.qll +++ b/go/ql/lib/semmle/go/frameworks/Encoding.qll @@ -9,7 +9,8 @@ private string packagePath() { result = package("github.com/json-iterator/go", " /** A model of json-iterator's `Unmarshal` function, propagating taint from the JSON input to the decoded object. */ private class JsonIteratorUnmarshalFunction extends TaintTracking::FunctionModel, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range +{ JsonIteratorUnmarshalFunction() { this.hasQualifiedName(packagePath(), ["Unmarshal", "UnmarshalFromString"]) or diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll index 9918274f166..ee860e762a2 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll @@ -28,7 +28,8 @@ module K8sIoApiCoreV1 { } private class SecretMarshal extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { SecretMarshal() { this.hasQualifiedName(packagePath(), ["Secret", "SecretList"], "Marshal") } override DataFlow::FunctionInput getAnInput() { result.isReceiver() } @@ -43,7 +44,8 @@ module K8sIoApiCoreV1 { } private class SecretUnmarshal extends TaintTracking::FunctionModel, Method, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range + { SecretUnmarshal() { this.hasQualifiedName(packagePath(), ["Secret", "SecretList"], "Unmarshal") } diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll index 35ebb507f5e..081beebe9e9 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApimachineryPkgRuntime.qll @@ -85,7 +85,8 @@ module K8sIoApimachineryPkgRuntime { } private class CacheableObjectCacheEncode extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { CacheableObjectCacheEncode() { this.implements(packagePath(), "CacheableObject", "CacheEncode") } @@ -113,7 +114,8 @@ module K8sIoApimachineryPkgRuntime { } private class DecoderDecode extends TaintTracking::FunctionModel, Method, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range + { DecoderDecode() { this.implements(packagePath(), "Decoder", "Decode") or this.hasQualifiedName(packagePath(), "WithoutVersionDecoder", "Decode") @@ -134,7 +136,8 @@ module K8sIoApimachineryPkgRuntime { } private class EncoderEncode extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { EncoderEncode() { this.implements(packagePath(), "Encoder", "Encode") or this.hasQualifiedName(packagePath(), "WithVersionEncoder", "Encode") @@ -240,7 +243,8 @@ module K8sIoApimachineryPkgRuntime { } private class ParameterCodecDecodeParameters extends TaintTracking::FunctionModel, Method, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range + { ParameterCodecDecodeParameters() { this.implements(packagePath(), "ParameterCodec", "DecodeParameters") } @@ -260,7 +264,8 @@ module K8sIoApimachineryPkgRuntime { } private class ParameterCodecEncodeParameters extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { ParameterCodecEncodeParameters() { this.implements(packagePath(), "ParameterCodec", "EncodeParameters") } @@ -280,7 +285,8 @@ module K8sIoApimachineryPkgRuntime { } private class ProtobufMarshallerMarshalTo extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { ProtobufMarshallerMarshalTo() { this.implements(packagePath(), "ProtobufMarshaller", "MarshalTo") or this.implements(packagePath(), "ProtobufReverseMarshaller", "MarshalToSizedBuffer") @@ -316,7 +322,8 @@ module K8sIoApimachineryPkgRuntime { } private class RawExtensionMarshal extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { RawExtensionMarshal() { this.hasQualifiedName(packagePath(), "RawExtension", "Marshal") } override DataFlow::FunctionInput getAnInput() { result.isReceiver() } @@ -331,7 +338,8 @@ module K8sIoApimachineryPkgRuntime { } private class RawExtensionUnmarshal extends TaintTracking::FunctionModel, Method, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range + { RawExtensionUnmarshal() { this.hasQualifiedName(packagePath(), "RawExtension", "Unmarshal") } override DataFlow::FunctionInput getAnInput() { result.isReceiver() } @@ -364,7 +372,8 @@ module K8sIoApimachineryPkgRuntime { } private class UnknownMarshal extends TaintTracking::FunctionModel, Method, - MarshalingFunction::Range { + MarshalingFunction::Range + { string methodName; UnknownMarshal() { @@ -388,7 +397,8 @@ module K8sIoApimachineryPkgRuntime { } private class UnknownUnmarshal extends TaintTracking::FunctionModel, Method, - UnmarshalingFunction::Range { + UnmarshalingFunction::Range + { UnknownUnmarshal() { this.hasQualifiedName(packagePath(), "Unknown", "Unmarshal") } override DataFlow::FunctionInput getAnInput() { result.isReceiver() } diff --git a/go/ql/lib/semmle/go/frameworks/Revel.qll b/go/ql/lib/semmle/go/frameworks/Revel.qll index fbbe329564e..e5090a50caa 100644 --- a/go/ql/lib/semmle/go/frameworks/Revel.qll +++ b/go/ql/lib/semmle/go/frameworks/Revel.qll @@ -20,7 +20,8 @@ module Revel { } private class ParamsFixedSanitizer extends TaintTracking::DefaultTaintSanitizer, - DataFlow::FieldReadNode { + DataFlow::FieldReadNode + { ParamsFixedSanitizer() { exists(Field f | this.readsField(_, f) and @@ -48,7 +49,8 @@ module Revel { /** An access to an HTTP request field whose value may be controlled by an untrusted user. */ private class UserControlledRequestField extends UntrustedFlowSource::Range, - DataFlow::FieldReadNode { + DataFlow::FieldReadNode + { UserControlledRequestField() { exists(string fieldName | this.getField().hasQualifiedName(packagePath(), "Request", fieldName) @@ -61,7 +63,8 @@ module Revel { } private class UserControlledRequestMethod extends UntrustedFlowSource::Range, - DataFlow::MethodCallNode { + DataFlow::MethodCallNode + { UserControlledRequestMethod() { this.getTarget() .hasQualifiedName(packagePath(), "Request", diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll index 12eee7079f7..965fbeca4fb 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll @@ -8,7 +8,8 @@ import go module NetHttp { /** An access to an HTTP request field whose value may be controlled by an untrusted user. */ private class UserControlledRequestField extends UntrustedFlowSource::Range, - DataFlow::FieldReadNode { + DataFlow::FieldReadNode + { UserControlledRequestField() { exists(string fieldName | this.getField().hasQualifiedName("net/http", "Request", fieldName) | fieldName = diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll b/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll index 3e297bdcc25..dbb6dd195cb 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/TextTemplate.qll @@ -25,7 +25,8 @@ module TextTemplate { } private class TextTemplateInstantiation extends TemplateInstantiation::Range, - DataFlow::MethodCallNode { + DataFlow::MethodCallNode + { int dataArg; TextTemplateInstantiation() { diff --git a/go/ql/lib/semmle/go/security/CleartextLoggingCustomizations.qll b/go/ql/lib/semmle/go/security/CleartextLoggingCustomizations.qll index d9e9039f5b3..17a7345b23e 100644 --- a/go/ql/lib/semmle/go/security/CleartextLoggingCustomizations.qll +++ b/go/ql/lib/semmle/go/security/CleartextLoggingCustomizations.qll @@ -183,7 +183,8 @@ module CleartextLogging { override string describe() { result = "HTTP request headers" } } - private class KubernetesSecretInterfaceSource extends Source, K8sIoClientGo::SecretInterfaceSource { + private class KubernetesSecretInterfaceSource extends Source, K8sIoClientGo::SecretInterfaceSource + { override string describe() { result = "Kubernetes Secret" } } diff --git a/go/ql/lib/semmle/go/security/ExternalAPIs.qll b/go/ql/lib/semmle/go/security/ExternalAPIs.qll index 211576ab602..f2e588ab5de 100644 --- a/go/ql/lib/semmle/go/security/ExternalAPIs.qll +++ b/go/ql/lib/semmle/go/security/ExternalAPIs.qll @@ -19,6 +19,16 @@ abstract class SafeExternalApiFunction extends Function { } /** DEPRECATED: Alias for SafeExternalApiFunction */ deprecated class SafeExternalAPIFunction = SafeExternalApiFunction; +/** + * A `Function` with one or more arguments that are considered "safe" from a security perspective. + */ +abstract class SafeExternalApiArgument extends Function { + /** + * Holds if `i` is a safe argument to this function. + */ + abstract predicate isSafeArgument(int i); +} + private predicate isDefaultSafePackage(Package package) { package.getPath() in ["time", "unicode/utf8", package("gopkg.in/go-playground/validator", "")] } @@ -44,6 +54,16 @@ private class DefaultSafeExternalApiFunction extends SafeExternalApiFunction { } } +private class DefaultSafeExternalApiFunctionArgument extends SafeExternalApiArgument { + int index; + + DefaultSafeExternalApiFunctionArgument() { + this.(Method).hasQualifiedName("net/http", "Header", ["Set", "Del"]) and index = -1 + } + + override predicate isSafeArgument(int i) { i = index } +} + /** Holds if `callNode` is a local function pointer. */ private predicate isProbableLocalFunctionPointer(DataFlow::CallNode callNode) { // Not a method call @@ -77,7 +97,9 @@ class ExternalApiDataNode extends DataFlow::Node { // Not already modeled as a taint step not TaintTracking::localTaintStep(this, _) and // Not a call to a known safe external API - not call.getTarget() instanceof SafeExternalApiFunction + not call.getTarget() instanceof SafeExternalApiFunction and + // Not a known safe argument to an external API + not any(SafeExternalApiArgument seaa).isSafeArgument(i) } /** Gets the called API `Function`. */ diff --git a/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll b/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll index 1c0b647e91f..298dd7c8513 100644 --- a/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll +++ b/go/ql/lib/semmle/go/security/IncorrectIntegerConversionLib.qll @@ -123,7 +123,13 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { this.isSinkWithBitSize(sink, sinkBitSize) } + override predicate isSink(DataFlow::Node sink) { + // We use the argument of the type conversion as the configuration sink so that we + // can sanitize the result of the conversion to prevent flow on to further sinks + // without needing to use `isSanitizerOut`, which doesn't work with flow states + // (and therefore the legacy `TaintTracking::Configuration` class). + this.isSinkWithBitSize(sink.getASuccessor(), sinkBitSize) + } override predicate isSanitizer(DataFlow::Node node) { // To catch flows that only happen on 32-bit architectures we @@ -134,10 +140,9 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration { node = DataFlow::BarrierGuard::getABarrierNodeForGuard(g) and g.isBoundFor(bitSize, sinkIsSigned) ) - } - - override predicate isSanitizerOut(DataFlow::Node node) { - exists(int bitSize | isIncorrectIntegerConversion(sourceBitSize, bitSize) | + or + exists(int bitSize | + isIncorrectIntegerConversion(sourceBitSize, bitSize) and this.isSinkWithBitSize(node, bitSize) ) } diff --git a/go/ql/src/CHANGELOG.md b/go/ql/src/CHANGELOG.md index d7c6b659d23..89ee497c17f 100644 --- a/go/ql/src/CHANGELOG.md +++ b/go/ql/src/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.4.4 + +### Minor Analysis Improvements + +* The query `go/incorrect-integer-conversion` now correctly recognizes guards of the form `if val <= x` to protect a conversion `uintX(val)` when `x` is in the range `(math.MaxIntX, math.MaxUintX]`. + ## 0.4.3 ### New Queries diff --git a/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql b/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql index c710d135a65..8513c673189 100644 --- a/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql +++ b/go/ql/src/Security/CWE-681/IncorrectIntegerConversionQuery.ql @@ -19,10 +19,13 @@ import semmle.go.security.IncorrectIntegerConversionLib from DataFlow::PathNode source, DataFlow::PathNode sink, ConversionWithoutBoundsCheckConfig cfg, - DataFlow::CallNode call -where cfg.hasFlowPath(source, sink) and call.getResult(0) = source.getNode() -select sink.getNode(), source, sink, + DataFlow::CallNode call, DataFlow::Node sinkConverted +where + cfg.hasFlowPath(source, sink) and + call.getResult(0) = source.getNode() and + sinkConverted = sink.getNode().getASuccessor() +select sinkConverted, source, sink, "Incorrect conversion of " + describeBitSize(cfg.getSourceBitSize(), getIntTypeBitSize(source.getNode().getFile())) + - " from $@ to a lower bit size type " + sink.getNode().getType().getUnderlyingType().getName() + + " from $@ to a lower bit size type " + sinkConverted.getType().getUnderlyingType().getName() + " without an upper bound check.", source, call.getTarget().getQualifiedName() diff --git a/go/ql/src/change-notes/2023-03-16-untrusted-data-write-only-args.md b/go/ql/src/change-notes/2023-03-16-untrusted-data-write-only-args.md new file mode 100644 index 00000000000..52ef46ae70e --- /dev/null +++ b/go/ql/src/change-notes/2023-03-16-untrusted-data-write-only-args.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The receiver arguments of `net/http.Header.Set` and `.Del` are no longer flagged by query `go/untrusted-data-to-external-api`. diff --git a/go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md b/go/ql/src/change-notes/released/0.4.4.md similarity index 55% rename from go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md rename to go/ql/src/change-notes/released/0.4.4.md index 9fb36271a32..c721dd4bc33 100644 --- a/go/ql/src/change-notes/2023-02-17-integer-conversion-fix.md +++ b/go/ql/src/change-notes/released/0.4.4.md @@ -1,4 +1,5 @@ ---- -category: minorAnalysis ---- -* The query `go/incorrect-integer-conversion` now correctly recognises guards of the form `if val <= x` to protect a conversion `uintX(val)` when `x` is in the range `(math.MaxIntX, math.MaxUintX]`. +## 0.4.4 + +### Minor Analysis Improvements + +* The query `go/incorrect-integer-conversion` now correctly recognizes guards of the form `if val <= x` to protect a conversion `uintX(val)` when `x` is in the range `(math.MaxIntX, math.MaxUintX]`. diff --git a/go/ql/src/codeql-pack.release.yml b/go/ql/src/codeql-pack.release.yml index 1ec9c4ea5d9..e9b57993a01 100644 --- a/go/ql/src/codeql-pack.release.yml +++ b/go/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.4.3 +lastReleaseVersion: 0.4.4 diff --git a/go/ql/src/qlpack.yml b/go/ql/src/qlpack.yml index a5a4c5de846..02c9d788969 100644 --- a/go/ql/src/qlpack.yml +++ b/go/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/go-queries -version: 0.4.4-dev +version: 0.4.5-dev groups: - go - queries diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql index 176396da6f7..87e9b301148 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/VarArgsWithFunctionModels/Flows.ql @@ -41,8 +41,6 @@ class DataConfiguration extends DataFlow::Configuration { override predicate isSink(DataFlow::Node sink) { sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) } - - override int explorationLimit() { result = 10 } // this is different! } class DataFlowTest extends InlineExpectationsTest { @@ -71,8 +69,6 @@ class TaintConfiguration extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink = any(DataFlow::CallNode c | c.getCalleeName() = "sink").getArgument(0) } - - override int explorationLimit() { result = 10 } // this is different! } class TaintFlowTest extends InlineExpectationsTest { diff --git a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.ql b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.ql index 90bb7f94e73..e4eb088abd8 100644 --- a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.ql +++ b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.ql @@ -1,11 +1,23 @@ import go -import TestUtilities.InlineFlowTest +import TestUtilities.InlineExpectationsTest import semmle.go.security.IncorrectIntegerConversionLib -class IncorrectIntegerConversionTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { - result = any(ConversionWithoutBoundsCheckConfig config) - } +class TestIncorrectIntegerConversion extends InlineExpectationsTest { + TestIncorrectIntegerConversion() { this = "TestIncorrectIntegerConversion" } - override DataFlow::Configuration getTaintFlowConfig() { none() } + override string getARelevantTag() { result = "hasValueFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node sink, DataFlow::Node sinkConverted | + any(ConversionWithoutBoundsCheckConfig config).hasFlowTo(sink) and + sinkConverted = sink.getASuccessor() + | + sinkConverted + .hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), + location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and + element = sinkConverted.toString() and + value = "\"" + sinkConverted.toString() + "\"" + ) + } } diff --git a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected index d6bb8bbf7af..74ec75c02f3 100644 --- a/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected +++ b/go/ql/test/query-tests/Security/CWE-918/RequestForgery.expected @@ -6,13 +6,7 @@ edges | tst.go:10:13:10:35 | call to FormValue | tst.go:24:66:24:72 | tainted | | tst.go:10:13:10:35 | call to FormValue | tst.go:27:11:27:29 | ...+... | | tst.go:10:13:10:35 | call to FormValue | tst.go:29:11:29:40 | ...+... | -| tst.go:10:13:10:35 | call to FormValue | tst.go:36:2:36:2 | implicit dereference | | tst.go:10:13:10:35 | call to FormValue | tst.go:37:11:37:20 | call to String | -| tst.go:35:2:35:2 | definition of u [pointer] | tst.go:36:2:36:2 | u [pointer] | -| tst.go:36:2:36:2 | implicit dereference | tst.go:35:2:35:2 | definition of u [pointer] | -| tst.go:36:2:36:2 | implicit dereference | tst.go:36:2:36:2 | implicit dereference | -| tst.go:36:2:36:2 | implicit dereference | tst.go:37:11:37:20 | call to String | -| tst.go:36:2:36:2 | u [pointer] | tst.go:36:2:36:2 | implicit dereference | | websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | | websocket.go:74:21:74:31 | call to Referer | websocket.go:78:36:78:49 | untrustedInput | | websocket.go:88:21:88:31 | call to Referer | websocket.go:91:31:91:44 | untrustedInput | @@ -32,9 +26,6 @@ nodes | tst.go:24:66:24:72 | tainted | semmle.label | tainted | | tst.go:27:11:27:29 | ...+... | semmle.label | ...+... | | tst.go:29:11:29:40 | ...+... | semmle.label | ...+... | -| tst.go:35:2:35:2 | definition of u [pointer] | semmle.label | definition of u [pointer] | -| tst.go:36:2:36:2 | implicit dereference | semmle.label | implicit dereference | -| tst.go:36:2:36:2 | u [pointer] | semmle.label | u [pointer] | | tst.go:37:11:37:20 | call to String | semmle.label | call to String | | websocket.go:60:21:60:31 | call to Referer | semmle.label | call to Referer | | websocket.go:65:27:65:40 | untrustedInput | semmle.label | untrustedInput | diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv index 211ecabe415..fa61d8d78ea 100644 --- a/java/documentation/library-coverage/coverage.csv +++ b/java/documentation/library-coverage/coverage.csv @@ -25,6 +25,7 @@ com.hubspot.jinjava,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, com.mitchellbosecke.pebble,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,, com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,,,3,,,,,,,,,,,,,,,,,,,,,,,,, com.rabbitmq.client,,21,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,21,7, +com.thoughtworks.xstream,1,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,, com.unboundid.ldap.sdk,17,,,,,,,,,,,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,,, com.zaxxer.hikari,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1 @@ -32,18 +33,21 @@ freemarker.cache,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,, freemarker.template,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,, groovy.lang,26,,,,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, groovy.util,5,,,,,,5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +hudson.remoting,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, +io.netty.resolver,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 jakarta.ws.rs.client,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, -java.io,37,,42,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,22,,,,,,,,41,1 -java.lang,14,,76,,,,,,,,,,,,8,,,,,1,,4,,,1,,,,,,,,,,,,,,,,53,23 -java.net,10,3,9,,,,,,,,,,,,,,,10,,,,,,,,,,,,,,,,,,,,,,3,9, -java.nio,16,,16,,13,,,,,,,,,,,,,,,1,,,,,,,,,,,,,2,,,,,,,,16, -java.sql,11,,2,,,,,,,,4,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,1,1 +java.io,42,,40,,17,,,,,,,,,,,,,,,3,,,,,,,,,,,,,22,,,,,,,,39,1 +java.lang,16,,76,,,,,,,,,,,,8,,,,,3,,4,,,1,,,,,,,,,,,,,,,,53,23 +java.net,12,3,16,,,,,,,,,,,,,,,12,,,,,,,,,,,,,,,,,,,,,,3,16, +java.nio,20,,15,,15,,,,,,,,,,,,,,,3,,,,,,,,,,,,,2,,,,,,,,15, +java.sql,13,,2,,,,,,,,4,,,,,,,,,,,,,,,,,,9,,,,,,,,,,,,1,1 java.util,44,,465,,,,,,,,,,,,34,,,,,,,,5,2,,1,2,,,,,,,,,,,,,,38,427 +javafx.scene.web,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,7,, javax.jms,,9,57,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,57, javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,100,23 @@ -56,7 +60,7 @@ javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,, javax.ws.rs.client,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,9,, javax.ws.rs.core,3,,149,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,94,55 -javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,6, +javax.xml.transform,2,,6,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,6, javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3,,,,,,,, jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,10 kotlin,12,,1835,,10,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,1828,7 @@ -66,7 +70,9 @@ okhttp3,2,,47,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,22,25 org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6, org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,17,783 -org.apache.commons.io,106,,560,,91,,,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,546,14 +org.apache.commons.compress.archivers.tar,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4, +org.apache.commons.io,107,,560,,91,,,,,,,,,,,,,15,,1,,,,,,,,,,,,,,,,,,,,,546,14 +org.apache.commons.jelly,6,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,, org.apache.commons.jexl2,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.apache.commons.jexl3,15,,,,,,,,,,,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.apache.commons.lang3,6,,424,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,293,131 @@ -80,14 +86,17 @@ org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,2,39, org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2, org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,18,6 org.apache.hive.hcatalog.templeton,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,, -org.apache.http,27,3,70,,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,,,,2,,,,3,62,8 +org.apache.http,27,3,77,,,,,,,,,,,,,,,25,,,,,,,,,,,,,,,,,,2,,,,3,69,8 org.apache.ibatis.jdbc,6,,57,,,,,,,,,,,,,,,,,,,,,,,,,,6,,,,,,,,,,,,57, org.apache.log4j,11,,,,,,,,,,,,,,11,,,,,,,,,,,,,,,,,,,,,,,,,,, org.apache.logging.log4j,359,,8,,,,,,,,,,,,359,,,,,,,,,,,,,,,,,,,,,,,,,,4,4 org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, org.apache.shiro.jndi,1,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +org.apache.tools.ant,11,,,,3,,,,,,,,,,,,,,,8,,,,,,,,,,,,,,,,,,,,,, +org.apache.tools.zip,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1, org.apache.velocity.app,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, org.apache.velocity.runtime,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,, +org.codehaus.cargo.container.installer,3,,,,2,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,, org.codehaus.groovy.control,1,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,20,,,,,,,, org.hibernate,7,,,,,,,,,,,,,,,,,,,,,,,,,,,,7,,,,,,,,,,,,, @@ -95,7 +104,9 @@ org.jboss.logging,324,,,,,,,,,,,,,,324,,,,,,,,,,,,,,,,,,,,,,,,,,, org.jdbi.v3.core,6,,,,,,,,,,6,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.jooq,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,, org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,198,38 +org.kohsuke.stapler,3,,1,,,,,,,,,,,,,,,1,,1,,,,,,,,,,,,1,,,,,,,,,1, org.mvel2,16,,,,,,,,,,,,,,,16,,,,,,,,,,,,,,,,,,,,,,,,,, +org.openjdk.jmh.runner.options,1,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, org.scijava.log,13,,,,,,,,,,,,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,, org.slf4j,55,,6,,,,,,,,,,,,55,,,,,,,,,,,,,,,,,,,,,,,,,,2,4 org.springframework.beans,,,30,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30 diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst index 2e90702b3b8..b0b240d9acc 100644 --- a/java/documentation/library-coverage/coverage.rst +++ b/java/documentation/library-coverage/coverage.rst @@ -10,18 +10,18 @@ Java framework & library support Android,``android.*``,52,479,138,,,3,67,,, Android extensions,``androidx.*``,5,183,19,,,,,,, `Apache Commons Collections `_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,, - `Apache Commons IO `_,``org.apache.commons.io``,,560,106,91,,,,,,15 + `Apache Commons IO `_,``org.apache.commons.io``,,560,107,91,,,,,,15 `Apache Commons Lang `_,``org.apache.commons.lang3``,,424,6,,,,,,, `Apache Commons Text `_,``org.apache.commons.text``,,272,,,,,,,, - `Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25 + `Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,143,28,,,3,,,,25 `Apache Log4j 2 `_,``org.apache.logging.log4j``,,8,359,,,,,,, `Google Guava `_,``com.google.common.*``,,728,39,,6,,,,, JBoss Logging,``org.jboss.logging``,,,324,,,,,,, `JSON-java `_,``org.json``,,236,,,,,,,, - Java Standard Library,``java.*``,3,611,132,28,,,7,,,10 - Java extensions,"``javax.*``, ``jakarta.*``",63,609,32,,,4,,1,1,2 + Java Standard Library,``java.*``,3,615,147,32,,,9,,,12 + Java extensions,"``javax.*``, ``jakarta.*``",63,609,33,1,,4,,1,1,2 Kotlin Standard Library,``kotlin*``,,1835,12,10,,,,,,2 `Spring `_,``org.springframework.*``,29,477,101,,,,19,14,,29 - Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",60,300,273,,,,18,18,,3 - Totals,,217,8458,1569,129,6,10,111,33,1,86 + Others,"``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.hubspot.jinjava``, ``com.mitchellbosecke.pebble``, ``com.opensymphony.xwork2.ognl``, ``com.rabbitmq.client``, ``com.thoughtworks.xstream``, ``com.unboundid.ldap.sdk``, ``com.zaxxer.hikari``, ``flexjson``, ``freemarker.cache``, ``freemarker.template``, ``groovy.lang``, ``groovy.util``, ``hudson.remoting``, ``io.netty.resolver``, ``javafx.scene.web``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``okhttp3``, ``org.apache.commons.codec``, ``org.apache.commons.compress.archivers.tar``, ``org.apache.commons.jelly``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.hadoop.hive.metastore``, ``org.apache.hive.hcatalog.templeton``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.apache.tools.ant``, ``org.apache.tools.zip``, ``org.apache.velocity.app``, ``org.apache.velocity.runtime``, ``org.codehaus.cargo.container.installer``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jdbi.v3.core``, ``org.jooq``, ``org.kohsuke.stapler``, ``org.mvel2``, ``org.openjdk.jmh.runner.options``, ``org.scijava.log``, ``org.slf4j``, ``org.thymeleaf``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``, ``retrofit2``",60,308,299,6,,,18,18,,12 + Totals,,217,8477,1612,140,6,10,113,33,1,97 diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/diagnostics.expected index 5446916799d..34d7835bf5e 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/android-gradle-incompatibility/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle).\n\nSuspicious output line: ` > Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in /gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`", + "markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle).\n\nRelevant output line: ` > Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in /gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`", "severity": "error", "source": { "extractorName": "java", @@ -13,7 +13,7 @@ } } { - "markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle).\n\nSuspicious output line: `Caused by: java.lang.RuntimeException: Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in /gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`", + "markdownMessage": "An Android build may have failed. Ensure the Code Scanning workflow installs required dependencies, and that the [Gradle and Android SDK versions are compatible](https://developer.android.com/studio/releases/gradle-plugin#updating-gradle).\n\nRelevant output line: `Caused by: java.lang.RuntimeException: Minimum supported Gradle version is 7.4. Current version is 7.3. If using the gradle wrapper, try editing the distributionUrl in /gradle/wrapper/gradle-wrapper.properties to gradle-7.4-all.zip`", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/diagnostics.expected index 34a7884823d..3d087084db0 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/compilation-error/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nSuspicious output line: `[ERROR] COMPILATION ERROR : `", + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nRelevant output line: `[ERROR] COMPILATION ERROR : `", "severity": "error", "source": { "extractorName": "java", @@ -13,7 +13,7 @@ } } { - "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nSuspicious output line: `[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`", + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nRelevant output line: `[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`", "severity": "error", "source": { "extractorName": "java", @@ -27,7 +27,7 @@ } } { - "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nSuspicious output line: `org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`", + "markdownMessage": "A compilation error was observed while autobuilding your code. Check that your Code Scanning workflow installs the needed compiler version and dependencies.\n\nRelevant output line: `org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project maven-sample: Compilation failure`", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/diagnostics.expected index fbb583581f2..d97eb904658 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/dependency-error/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "A dependency failed to download. Check that all dependencies are available, and [supply credentials for any private dependencies](https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md#set-up-secrets-in-github-action-workflows).\n\nSuspicious output line: `Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact junit:junit-nonesuch:jar:4.11 in central (https://repo.maven.apache.org/maven2)`", + "markdownMessage": "A dependency failed to download. Check that all dependencies are available, and [supply credentials for any private dependencies](https://github.com/Azure/actions-workflow-samples/blob/master/assets/create-secrets-for-GitHub-workflows.md#set-up-secrets-in-github-action-workflows).\n\nRelevant output line: `Caused by: org.eclipse.aether.transfer.ArtifactNotFoundException: Could not find artifact junit:junit-nonesuch:jar:4.11 in central (https://repo.maven.apache.org/maven2)`", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/diagnostics.expected index 396198d057a..c002fd22788 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/java-version-too-old/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "Your project may need a different JDK version. Ensure your Code Scanning workflow file has [an appropriate `setup-java` step](https://github.com/actions/setup-java#eclipse-temurin).\n\nSuspicious output line: `> Could not target platform: 'Java SE 11' using tool chain: 'JDK 8 (1.8)'.`", + "markdownMessage": "Your project may need a different JDK version. Ensure your Code Scanning workflow file has [an appropriate `setup-java` step](https://github.com/actions/setup-java#eclipse-temurin).\n\nRelevant output line: `> Could not target platform: 'Java SE 11' using tool chain: 'JDK 8 (1.8)'.`", "severity": "error", "source": { "extractorName": "java", @@ -13,7 +13,7 @@ } } { - "markdownMessage": "Your project may need a different JDK version. Ensure your Code Scanning workflow file has [an appropriate `setup-java` step](https://github.com/actions/setup-java#eclipse-temurin).\n\nSuspicious output line: `Caused by: java.lang.IllegalArgumentException: Could not target platform: 'Java SE 11' using tool chain: 'JDK 8 (1.8)'.`", + "markdownMessage": "Your project may need a different JDK version. Ensure your Code Scanning workflow file has [an appropriate `setup-java` step](https://github.com/actions/setup-java#eclipse-temurin).\n\nRelevant output line: `Caused by: java.lang.IllegalArgumentException: Could not target platform: 'Java SE 11' using tool chain: 'JDK 8 (1.8)'.`", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/diagnostics.expected index 301efee2929..5e7d5956858 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/maven-http-repository/diagnostics.expected @@ -1,10 +1,10 @@ { - "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nSuspicious output line: `Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", + "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nRelevant output line: `Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", "severity": "error", "source": { "extractorName": "java", "id": "java/autobuilder/non-https-repository", - "name": "A non-https Maven repository access failed" + "name": "A non-HTTPS Maven repository access failed" }, "visibility": { "cliSummaryTable": false, @@ -13,12 +13,12 @@ } } { - "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nSuspicious output line: `Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", + "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nRelevant output line: `Caused by: org.eclipse.aether.transfer.ArtifactTransferException: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", "severity": "error", "source": { "extractorName": "java", "id": "java/autobuilder/non-https-repository", - "name": "A non-https Maven repository access failed" + "name": "A non-HTTPS Maven repository access failed" }, "visibility": { "cliSummaryTable": false, @@ -27,12 +27,12 @@ } } { - "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nSuspicious output line: `Caused by: org.eclipse.aether.transfer.NoRepositoryConnectorException: Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", + "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nRelevant output line: `Caused by: org.eclipse.aether.transfer.NoRepositoryConnectorException: Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)]`", "severity": "error", "source": { "extractorName": "java", "id": "java/autobuilder/non-https-repository", - "name": "A non-https Maven repository access failed" + "name": "A non-HTTPS Maven repository access failed" }, "visibility": { "cliSummaryTable": false, @@ -41,12 +41,12 @@ } } { - "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nSuspicious output line: `[ERROR] Failed to execute goal on project maven-sample: Could not resolve dependencies for project com.example:maven-sample:jar:1.0-SNAPSHOT: Failed to collect dependencies at junit-nonesuch:junit-nonesuch:jar:4.11: Failed to read artifact descriptor for junit-nonesuch:junit-nonesuch:jar:4.11: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)] -> [Help 1]`", + "markdownMessage": "Building your code triggered an access to an insecure HTTP Maven repository. Allow access to insecure repositories, or [update your build to use HTTPS](https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked).\n\nRelevant output line: `[ERROR] Failed to execute goal on project maven-sample: Could not resolve dependencies for project com.example:maven-sample:jar:1.0-SNAPSHOT: Failed to collect dependencies at junit-nonesuch:junit-nonesuch:jar:4.11: Failed to read artifact descriptor for junit-nonesuch:junit-nonesuch:jar:4.11: Could not transfer artifact junit-nonesuch:junit-nonesuch:pom:4.11 from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [insecure (http://repo.maven.apache.org/maven2/, default, releases+snapshots)] -> [Help 1]`", "severity": "error", "source": { "extractorName": "java", "id": "java/autobuilder/non-https-repository", - "name": "A non-https Maven repository access failed" + "name": "A non-HTTPS Maven repository access failed" }, "visibility": { "cliSummaryTable": true, diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/diagnostics.expected index 9e7a9ceec33..c55a814c684 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/multiple-candidate-builds/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "Building using Maven was skipped because there were multiple sibling build directories containing build files: [./maven-project-1,./maven-project-2]. If you want to use one of these, please [manually supply a build command](https://docs.github.com/en/github-ae@latest/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", + "markdownMessage": "Building using Maven was skipped because there were multiple sibling build directories containing build files: [./maven-project-1,./maven-project-2]. If you want to use one of these, please [manually supply a build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", "severity": "warning", "source": { "extractorName": "java", @@ -13,7 +13,7 @@ } } { - "markdownMessage": "If you want to use one of the candidate build systems and directories (see previous warnings), please [supply a manual a build command](https://docs.github.com/en/github-ae@latest/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", + "markdownMessage": "Could not identify a unique top-level project to build. [Supply a manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/diagnostics.expected index f465cd5df84..a4568fcd233 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-build-system/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "Could not find a Gradle, Maven or Ant top-level project to build. Please [supply a manual build command](https://docs.github.com/en/github-ae@latest/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", + "markdownMessage": "Could not find a Gradle, Maven or Ant top-level project to build. [Supply a manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language).", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/diagnostics.expected index a6c5e2eb877..30e328253da 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-test-classes/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "Built a Gradle project without the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). This may use an incompatible version of Gradle", + "markdownMessage": "Built a Gradle project without the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). This may use an incompatible version of Gradle.", "severity": "warning", "source": { "extractorName": "java", @@ -13,7 +13,7 @@ } } { - "markdownMessage": "Gradle project does not define a `testClasses` goal. [Supply a manual build command](https://docs.github.com/en/github-ae@latest/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language) that builds the code that should be analyzed.\n\nSuspicious output line: `org.gradle.execution.TaskSelectionException: Task 'testClasses' not found in root project 'no-gradle-test-classes'.`", + "markdownMessage": "Gradle project does not define a `testClasses` goal. [Supply a manual build command](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages#adding-build-steps-for-a-compiled-language) that builds the code that should be analyzed.\n\nRelevant output line: `org.gradle.execution.TaskSelectionException: Task 'testClasses' not found in root project 'no-gradle-test-classes'.`", "severity": "error", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/diagnostics.expected b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/diagnostics.expected index ad5c5bdb7c6..feef1ed590d 100644 --- a/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/diagnostics.expected +++ b/java/ql/integration-tests/all-platforms/java/diagnostics/no-gradle-wrapper/diagnostics.expected @@ -1,5 +1,5 @@ { - "markdownMessage": "Built a Gradle project without the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). This may use an incompatible version of Gradle", + "markdownMessage": "Built a Gradle project without the [Gradle wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html). This may use an incompatible version of Gradle.", "severity": "warning", "source": { "extractorName": "java", diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/build.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/build.py new file mode 100644 index 00000000000..45ab2315b54 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/build.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python3 + +import glob +import os +import re +from create_database_utils import * + +def say(s): + print(s) + sys.stdout.flush() + +say('Doing normal compilation') +# This is a normal intercepted compilation +runSuccessfully([get_cmd('kotlinc'), 'normal.kt']) + +say('Identifying extractor jar') +# Find the extractor jar that is being used +trapDir = os.environ['CODEQL_EXTRACTOR_JAVA_TRAP_DIR'] +invocationTrapDir = os.path.join(trapDir, 'invocations') +invocationTraps = os.listdir(invocationTrapDir) +if len(invocationTraps) != 1: + raise Exception('Expected to find 1 invocation TRAP, but found ' + str(invocationTraps)) +invocationTrap = os.path.join(invocationTrapDir, invocationTraps[0]) +with open(invocationTrap, 'r') as f: + content = f.read() + m = re.search('^// Using extractor: (.*)$', content, flags = re.MULTILINE) + extractorJar = m.group(1) + +def getManualFlags(invocationTrapName): + return ['-Xplugin=' + extractorJar, '-P', 'plugin:kotlin-extractor:invocationTrapFile=' + os.path.join(trapDir, 'invocations', invocationTrapName + '.trap')] + +# This is both normally intercepted, and it has the extractor flags manually added +say('Doing double-interception compilation') +runSuccessfully([get_cmd('kotlinc'), 'doubleIntercepted.kt'] + getManualFlags('doubleIntercepted')) +os.environ['CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN'] = 'true' +# We don't see this compilation at all +say('Doing unseen compilation') +runSuccessfully([get_cmd('kotlinc'), 'notSeen.kt']) +# This is extracted as it has the extractor flags manually added +say('Doing manual compilation') +runSuccessfully([get_cmd('kotlinc'), 'manual.kt'] + getManualFlags('manual')) diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/doubleIntercepted.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/doubleIntercepted.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/manual.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/manual.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/manuallyIntercepted.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/manuallyIntercepted.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/normal.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/normal.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/notSeen.kt b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/code/notSeen.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.expected b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.expected new file mode 100644 index 00000000000..bc69208b7e8 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.expected @@ -0,0 +1,3 @@ +| code/doubleIntercepted.kt:0:0:0:0 | doubleIntercepted | +| code/manual.kt:0:0:0:0 | manual | +| code/normal.kt:0:0:0:0 | normal | diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.ql b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.ql new file mode 100644 index 00000000000..c6d9064f1e9 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/files.ql @@ -0,0 +1,4 @@ +import java + +from File f +select f diff --git a/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/test.py b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/test.py new file mode 100644 index 00000000000..9abcb43e304 --- /dev/null +++ b/java/ql/integration-tests/posix-only/kotlin/kotlin_double_interception/test.py @@ -0,0 +1,7 @@ +import sys + +from create_database_utils import * + +run_codeql_database_create( + ['"%s" build.py' % sys.executable], + source="code", lang="java") diff --git a/java/ql/lib/CHANGELOG.md b/java/ql/lib/CHANGELOG.md index a7710c105fd..d7428d81c27 100644 --- a/java/ql/lib/CHANGELOG.md +++ b/java/ql/lib/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.5.4 + +### Minor Analysis Improvements + +* Added new sinks for `java/hardcoded-credential-api-call` to identify the use of hardcoded secrets in the creation and verification of JWT tokens using `com.auth0.jwt`. These sinks are from [an experimental query submitted by @luchua](https://github.com/github/codeql/pull/9036). +* The Java extractor now supports builds against JDK 20. +* The query `java/hardcoded-credential-api-call` now recognizes methods that accept user and password from the SQLServerDataSource class of the Microsoft JDBC Driver for SQL Server. + ## 0.5.3 ### New Features diff --git a/java/ql/lib/change-notes/2023-02-15-mssql-jdbc-hardcoded-credential-api.md b/java/ql/lib/change-notes/2023-02-15-mssql-jdbc-hardcoded-credential-api.md deleted file mode 100644 index 63fbb5647c1..00000000000 --- a/java/ql/lib/change-notes/2023-02-15-mssql-jdbc-hardcoded-credential-api.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The query `java/hardcoded-credential-api-call` now recognizes methods that accept user and password from the SQLServerDataSource class of the Microsoft JDBC Driver for SQL Server. \ No newline at end of file diff --git a/java/ql/lib/change-notes/2023-02-17-add-hardcoded-secret-for-jwt-tokens.md b/java/ql/lib/change-notes/2023-02-17-add-hardcoded-secret-for-jwt-tokens.md deleted file mode 100644 index 408bb13755b..00000000000 --- a/java/ql/lib/change-notes/2023-02-17-add-hardcoded-secret-for-jwt-tokens.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* Added new sinks for `java/hardcoded-credential-api-call` to identify the use of hardcoded secrets in the creation and verification of JWT tokens using `com.auth0.jwt`. These sinks are from [an experimental query submitted by @luchua](https://github.com/github/codeql/pull/9036). diff --git a/java/ql/lib/change-notes/2023-02-17-jdk20.md b/java/ql/lib/change-notes/2023-02-17-jdk20.md deleted file mode 100644 index a2f674cc275..00000000000 --- a/java/ql/lib/change-notes/2023-02-17-jdk20.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -category: minorAnalysis ---- -* The Java extractor now supports builds against JDK 20. \ No newline at end of file diff --git a/java/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md b/java/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md new file mode 100644 index 00000000000..89190af399f --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-02-dataflow-conf-module.md @@ -0,0 +1,9 @@ +--- +category: majorAnalysis +--- +* The main data flow and taint tracking APIs have been changed. The old APIs + remain in place for now and translate to the new through a + backwards-compatible wrapper. If multiple configurations are in scope + simultaneously, then this may affect results slightly. The new API is quite + similar to the old, but makes use of a configuration module instead of a + configuration class. diff --git a/java/ql/lib/change-notes/2023-03-03-delete-deps.md b/java/ql/lib/change-notes/2023-03-03-delete-deps.md new file mode 100644 index 00000000000..bdc84d43d26 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-03-delete-deps.md @@ -0,0 +1,7 @@ +--- +category: minorAnalysis +--- +* Deleted the deprecated `getPath` and `getFolder` predicates from the `XmlFile` class. +* Deleted the deprecated `getRepresentedString` predicate from the `StringLiteral` class. +* Deleted the deprecated `ServletWriterSource` class. +* Deleted the deprecated `getGroupID`, `getArtefactID`, and `artefactMatches` predicates from the `MavenRepoJar` class. \ No newline at end of file diff --git a/java/ql/lib/change-notes/2023-03-09-more-models.md b/java/ql/lib/change-notes/2023-03-09-more-models.md new file mode 100644 index 00000000000..2d763c0d22b --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-09-more-models.md @@ -0,0 +1,11 @@ +--- +category: majorAnalysis +--- +* Added more sink and summary dataflow models for the following packages: + * `java.io` + * `java.lang` + * `java.sql` + * `javafx.scene.web` + * `org.apache.commons.compress.archivers.tar` + * `org.apache.http.client.utils` + * `org.codehaus.cargo.container.installer` diff --git a/java/ql/lib/change-notes/2023-03-13-mergepathgraph.md b/java/ql/lib/change-notes/2023-03-13-mergepathgraph.md new file mode 100644 index 00000000000..63bfade2f10 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-13-mergepathgraph.md @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Added support for merging two `PathGraph`s via disjoint union to allow results from multiple data flow computations in a single `path-problem` query. diff --git a/java/ql/lib/change-notes/2023-03-14-neutral-dispatch.md b/java/ql/lib/change-notes/2023-03-14-neutral-dispatch.md new file mode 100644 index 00000000000..f01e8700757 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-14-neutral-dispatch.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* Removed low-confidence call edges to known neutral call targets from the call graph used in data flow analysis. This includes, for example, custom `List.contains` implementations when the best inferrable type at the call site is simply `List`. diff --git a/java/ql/lib/change-notes/released/0.5.4.md b/java/ql/lib/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..2a7d66f7cfe --- /dev/null +++ b/java/ql/lib/change-notes/released/0.5.4.md @@ -0,0 +1,7 @@ +## 0.5.4 + +### Minor Analysis Improvements + +* Added new sinks for `java/hardcoded-credential-api-call` to identify the use of hardcoded secrets in the creation and verification of JWT tokens using `com.auth0.jwt`. These sinks are from [an experimental query submitted by @luchua](https://github.com/github/codeql/pull/9036). +* The Java extractor now supports builds against JDK 20. +* The query `java/hardcoded-credential-api-call` now recognizes methods that accept user and password from the SQLServerDataSource class of the Microsoft JDBC Driver for SQL Server. diff --git a/java/ql/lib/codeql-pack.release.yml b/java/ql/lib/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/java/ql/lib/codeql-pack.release.yml +++ b/java/ql/lib/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/java/ql/lib/ext/com.thoughtworks.xstream.model.yml b/java/ql/lib/ext/com.thoughtworks.xstream.model.yml new file mode 100644 index 00000000000..a129f9f2580 --- /dev/null +++ b/java/ql/lib/ext/com.thoughtworks.xstream.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["com.thoughtworks.xstream", "XStream", True, "fromXML", "(File)", "", "Argument[0]", "read-file", "ai-generated"] diff --git a/java/ql/lib/ext/hudson.remoting.model.yml b/java/ql/lib/ext/hudson.remoting.model.yml new file mode 100644 index 00000000000..6125f10c827 --- /dev/null +++ b/java/ql/lib/ext/hudson.remoting.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["hudson.remoting", "URLDeserializationHelper", True, "wrapIfRequired", "(URL)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/io.netty.resolver.model.yml b/java/ql/lib/ext/io.netty.resolver.model.yml new file mode 100644 index 00000000000..64444c387eb --- /dev/null +++ b/java/ql/lib/ext/io.netty.resolver.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["io.netty.resolver", "SimpleNameResolver", False, "resolve", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/java.io.model.yml b/java/ql/lib/ext/java.io.model.yml index a0e7777c3b5..2e6e8897ca1 100644 --- a/java/ql/lib/ext/java.io.model.yml +++ b/java/ql/lib/ext/java.io.model.yml @@ -3,8 +3,13 @@ extensions: pack: codeql/java-all extensible: sinkModel data: + - ["java.io", "File", True, "createTempFile", "(String,String,File)", "", "Argument[2]", "create-file", "ai-generated"] + - ["java.io", "File", True, "renameTo", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["java.io", "FileInputStream", True, "FileInputStream", "(File)", "", "Argument[0]", "read-file", "ai-generated"] - ["java.io", "FileOutputStream", False, "FileOutputStream", "", "", "Argument[0]", "create-file", "manual"] - ["java.io", "FileOutputStream", False, "write", "", "", "Argument[0]", "write-file", "manual"] + - ["java.io", "FileReader", True, "FileReader", "(File)", "", "Argument[0]", "read-file", "ai-generated"] + - ["java.io", "FileReader", True, "FileReader", "(String)", "", "Argument[0]", "read-file", "ai-generated"] - ["java.io", "FileWriter", False, "FileWriter", "", "", "Argument[0]", "create-file", "manual"] - ["java.io", "PrintStream", False, "PrintStream", "(File)", "", "Argument[0]", "create-file", "manual"] - ["java.io", "PrintStream", False, "PrintStream", "(File,Charset)", "", "Argument[0]", "create-file", "manual"] @@ -82,11 +87,8 @@ extensions: - ["java.io", "OutputStream", True, "write", "(byte[],int,int)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.io", "OutputStream", True, "write", "(int)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.io", "Reader", True, "read", "", "", "Argument[-1]", "Argument[0]", "taint", "manual"] - - ["java.io", "Reader", True, "read", "()", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.io", "StringReader", False, "StringReader", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - - ["java.io", "Writer", True, "toString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.io", "Writer", True, "write", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - - addsTo: pack: codeql/java-all extensible: neutralModel diff --git a/java/ql/lib/ext/java.lang.model.yml b/java/ql/lib/ext/java.lang.model.yml index 55a7f7f8990..94fe112301c 100644 --- a/java/ql/lib/ext/java.lang.model.yml +++ b/java/ql/lib/ext/java.lang.model.yml @@ -3,13 +3,25 @@ extensions: pack: codeql/java-all extensible: sinkModel data: + - ["java.lang", "Class", False, "getResource", "(String)", "", "Argument[0]", "read-file", "ai-generated"] + - ["java.lang", "ClassLoader", True, "getSystemResourceAsStream", "(String)", "", "Argument[0]", "read-file", "ai-generated"] - ["java.lang", "Module", True, "getResourceAsStream", "(String)", "", "Argument[0]", "read-file", "ai-generated"] -# suggested label is not supported: - ["java.lang", "ProcessBuilder", True, "ProcessBuilder", "(String[])", "", "Argument[0]", "command-injection", "ai-generated"] + # These are modeled in plain CodeQL. TODO: migrate them. + # - ["java.lang", "ProcessBuilder", False, "directory", "(File)", "", "Argument[0]", "command-injection", "ai-generated"] + # - ["java.lang", "ProcessBuilder", True, "ProcessBuilder", "(String[])", "", "Argument[0]", "command-injection", "ai-generated"] + # - ["java.lang", "Runtime", True, "exec", "(String,String[],File)", "", "Argument[2]", "command-injection", "ai-generated"] + # - ["java.lang", "Runtime", True, "exec", "(String)", "", "Argument[0]", "command-injection", "ai-generated"] + # - ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[0]", "command-injection", "ai-generated"] + # - ["java.lang", "Runtime", True, "exec", "(String[],String[],File)", "", "Argument[2]", "command-injection", "ai-generated"] + # - ["java.lang", "Runtime", True, "exec", "(String[])", "", "Argument[0]", "command-injection", "ai-generated"] - ["java.lang", "String", False, "matches", "(String)", "", "Argument[0]", "regex-use[f-1]", "manual"] - ["java.lang", "String", False, "replaceAll", "(String,String)", "", "Argument[0]", "regex-use[-1]", "manual"] - ["java.lang", "String", False, "replaceFirst", "(String,String)", "", "Argument[0]", "regex-use[-1]", "manual"] - ["java.lang", "String", False, "split", "(String)", "", "Argument[0]", "regex-use[-1]", "manual"] - ["java.lang", "String", False, "split", "(String,int)", "", "Argument[0]", "regex-use[-1]", "manual"] + # These are modeled in plain CodeQL. TODO: migrate them. + # - ["java.lang", "System", False, "load", "(String)", "", "Argument[0]", "command-injection", "ai-generated"] # This is actually injecting a library. + # - ["java.lang", "System", False, "loadLibrary", "(String)", "", "Argument[0]", "command-injection", "ai-generated"] # This is actually injecting a library. - ["java.lang", "System$Logger", True, "log", "(Level,Object)", "", "Argument[1]", "logging", "manual"] - ["java.lang", "System$Logger", True, "log", "(Level,ResourceBundle,String,Object[])", "", "Argument[2..3]", "logging", "manual"] - ["java.lang", "System$Logger", True, "log", "(Level,ResourceBundle,String,Throwable)", "", "Argument[2]", "logging", "manual"] @@ -98,7 +110,6 @@ extensions: - ["java.lang", "Throwable", False, "Throwable", "(Throwable)", "", "Argument[0]", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "value", "manual"] - ["java.lang", "Throwable", True, "getCause", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.cause]", "ReturnValue", "value", "manual"] - ["java.lang", "Throwable", True, "getMessage", "()", "", "Argument[-1].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"] - - addsTo: pack: codeql/java-all extensible: neutralModel @@ -131,7 +142,6 @@ extensions: - ["java.lang", "System", "nanoTime", "()", "manual"] - ["java.lang", "Thread", "currentThread", "()", "manual"] - ["java.lang", "Thread", "sleep", "(long)", "manual"] - # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - ["java.lang", "Integer", "intValue", "()", "manual"] # taint-numeric diff --git a/java/ql/lib/ext/java.net.model.yml b/java/ql/lib/ext/java.net.model.yml index 1ee1c96347f..9554dd2295f 100644 --- a/java/ql/lib/ext/java.net.model.yml +++ b/java/ql/lib/ext/java.net.model.yml @@ -9,7 +9,9 @@ extensions: pack: codeql/java-all extensible: sinkModel data: + - ["java.net", "DatagramSocket", True, "connect", "(SocketAddress)", "", "Argument[0]", "open-url", "ai-generated"] - ["java.net", "URL", False, "openConnection", "", "", "Argument[-1]", "open-url", "manual"] + - ["java.net", "URL", False, "openConnection", "(Proxy)", "", "Argument[0]", "open-url", "ai-generated"] - ["java.net", "URL", False, "openStream", "", "", "Argument[-1]", "open-url", "manual"] - ["java.net", "URLClassLoader", False, "URLClassLoader", "(String,URL[],ClassLoader)", "", "Argument[1]", "open-url", "manual"] - ["java.net", "URLClassLoader", False, "URLClassLoader", "(String,URL[],ClassLoader,URLStreamHandlerFactory)", "", "Argument[1]", "open-url", "manual"] @@ -21,6 +23,11 @@ extensions: pack: codeql/java-all extensible: summaryModel data: + - ["java.net", "InetAddress", True, "getByName", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["java.net", "InetSocketAddress", True, "createUnresolved", "(String,int)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["java.net", "InetSocketAddress", True, "InetSocketAddress", "(String,int)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["java.net", "URI", False, "resolve", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["java.net", "URI", False, "resolve", "(URI)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] - ["java.net", "URI", False, "URI", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.net", "URI", False, "create", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.net", "URI", False, "toASCIIString", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] @@ -29,4 +36,6 @@ extensions: - ["java.net", "URL", False, "URL", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["java.net", "URL", False, "toURI", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.net", "URL", False, "toExternalForm", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] + - ["java.net", "URL", False, "URL", "(URL,String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["java.net", "URL", False, "URL", "(URL,String)", "", "Argument[1]", "Argument[-1]", "taint", "ai-generated"] # @atorralba: review for consistency - ["java.net", "URLDecoder", False, "decode", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.nio.file.model.yml b/java/ql/lib/ext/java.nio.file.model.yml index db51d2f6686..ec2056c9a8f 100644 --- a/java/ql/lib/ext/java.nio.file.model.yml +++ b/java/ql/lib/ext/java.nio.file.model.yml @@ -12,7 +12,11 @@ extensions: - ["java.nio.file", "Files", False, "createSymbolicLink", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createTempDirectory", "(Path,String,FileAttribute[])", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "createTempFile", "(Path,String,String,FileAttribute[])", "", "Argument[0]", "create-file", "manual"] + - ["java.nio.file", "Files", False, "delete", "(Path)", "", "Argument[0]", "create-file", "ai-generated"] # should be delete-file + - ["java.nio.file", "Files", False, "deleteIfExists", "(Path)", "", "Argument[0]", "create-file", "ai-generated"] # should be delete-file + - ["java.nio.file", "Files", False, "lines", "(Path,Charset)", "", "Argument[0]", "read-file", "ai-generated"] - ["java.nio.file", "Files", False, "move", "", "", "Argument[1]", "create-file", "manual"] + - ["java.nio.file", "Files", False, "newBufferedReader", "(Path,Charset)", "", "Argument[0]", "read-file", "ai-generated"] - ["java.nio.file", "Files", False, "newBufferedWriter", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "newOutputStream", "", "", "Argument[0]", "create-file", "manual"] - ["java.nio.file", "Files", False, "write", "", "", "Argument[0]", "create-file", "manual"] @@ -24,7 +28,6 @@ extensions: extensible: summaryModel data: - ["java.nio.file", "FileSystem", True, "getPath", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - - ["java.nio.file", "FileSystem", True, "getRootDirectories", "", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "getParent", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "normalize", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - ["java.nio.file", "Path", True, "resolve", "", "", "Argument[-1..0]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/lib/ext/java.sql.model.yml b/java/ql/lib/ext/java.sql.model.yml index bf544fdb8e7..0bc57cb2f75 100644 --- a/java/ql/lib/ext/java.sql.model.yml +++ b/java/ql/lib/ext/java.sql.model.yml @@ -5,6 +5,8 @@ extensions: data: - ["java.sql", "Connection", True, "prepareCall", "", "", "Argument[0]", "sql", "manual"] - ["java.sql", "Connection", True, "prepareStatement", "", "", "Argument[0]", "sql", "manual"] + - ["java.sql", "DatabaseMetaData", True, "getColumns", "(String,String,String,String)", "", "Argument[2]", "sql", "ai-generated"] + - ["java.sql", "DatabaseMetaData", True, "getPrimaryKeys", "(String,String,String)", "", "Argument[2]", "sql", "ai-generated"] - ["java.sql", "Driver", False, "connect", "(String,Properties)", "", "Argument[0]", "jdbc-url", "manual"] - ["java.sql", "DriverManager", False, "getConnection", "(String)", "", "Argument[0]", "jdbc-url", "manual"] - ["java.sql", "DriverManager", False, "getConnection", "(String,Properties)", "", "Argument[0]", "jdbc-url", "manual"] @@ -14,20 +16,17 @@ extensions: - ["java.sql", "Statement", True, "executeLargeUpdate", "", "", "Argument[0]", "sql", "manual"] - ["java.sql", "Statement", True, "executeQuery", "", "", "Argument[0]", "sql", "manual"] - ["java.sql", "Statement", True, "executeUpdate", "", "", "Argument[0]", "sql", "manual"] - - addsTo: pack: codeql/java-all extensible: summaryModel data: - ["java.sql", "PreparedStatement", True, "setString", "(int,String)", "", "Argument[1]", "Argument[-1]", "value", "manual"] - ["java.sql", "ResultSet", True, "getString", "(String)", "", "Argument[-1]", "ReturnValue", "taint", "manual"] - - addsTo: pack: codeql/java-all extensible: neutralModel data: - ["java.sql", "ResultSet", "next", "()", "manual"] - # The below APIs have numeric flow and are currently being stored as neutral models. # These may be changed to summary models with kinds "value-numeric" and "taint-numeric" (or similar) in the future. - ["java.sql", "PreparedStatement", "setInt", "(int,int)", "manual"] # value-numeric diff --git a/java/ql/lib/ext/javafx.scene.web.model.yml b/java/ql/lib/ext/javafx.scene.web.model.yml new file mode 100644 index 00000000000..c31725e1d03 --- /dev/null +++ b/java/ql/lib/ext/javafx.scene.web.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["javafx.scene.web", "WebEngine", False, "load", "(String)", "", "Argument[0]", "open-url", "ai-generated"] diff --git a/java/ql/lib/ext/javax.xml.transform.stream.model.yml b/java/ql/lib/ext/javax.xml.transform.stream.model.yml index 5098f9badfc..6c97f60e2d9 100644 --- a/java/ql/lib/ext/javax.xml.transform.stream.model.yml +++ b/java/ql/lib/ext/javax.xml.transform.stream.model.yml @@ -5,3 +5,8 @@ extensions: data: - ["javax.xml.transform.stream", "StreamSource", False, "StreamSource", "", "", "Argument[0]", "Argument[-1]", "taint", "manual"] - ["javax.xml.transform.stream", "StreamSource", False, "getInputStream", "", "", "Argument[-1]", "ReturnValue", "taint", "manual"] + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["javax.xml.transform.stream", "StreamResult", True, "StreamResult", "(File)", "", "Argument[0]", "create-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.commons.compress.archivers.tar.model.yml b/java/ql/lib/ext/org.apache.commons.compress.archivers.tar.model.yml new file mode 100644 index 00000000000..bf565008fa0 --- /dev/null +++ b/java/ql/lib/ext/org.apache.commons.compress.archivers.tar.model.yml @@ -0,0 +1,9 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.apache.commons.compress.archivers.tar", "TarArchiveEntry", True, "TarArchiveEntry", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.commons.compress.archivers.tar", "TarArchiveEntry", True, "TarArchiveEntry", "(String,boolean)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.commons.compress.archivers.tar", "TarArchiveEntry", True, "TarArchiveEntry", "(String,byte)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.commons.compress.archivers.tar", "TarArchiveEntry", True, "setLinkName", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.commons.io.model.yml b/java/ql/lib/ext/org.apache.commons.io.model.yml index d00be2099de..7a3176c1e7d 100644 --- a/java/ql/lib/ext/org.apache.commons.io.model.yml +++ b/java/ql/lib/ext/org.apache.commons.io.model.yml @@ -12,3 +12,8 @@ extensions: - ["org.apache.commons.io", "IOUtils", True, "toByteArray", "(Reader,String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] - ["org.apache.commons.io", "IOUtils", True, "writeLines", "(Collection,String,Writer)", "", "Argument[0].Element", "Argument[2]", "taint", "manual"] - ["org.apache.commons.io", "IOUtils", True, "writeLines", "(Collection,String,Writer)", "", "Argument[1]", "Argument[2]", "taint", "manual"] + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.commons.io", "FileUtils", True, "openInputStream", "(File)", "", "Argument[0]", "read-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.commons.jelly.model.yml b/java/ql/lib/ext/org.apache.commons.jelly.model.yml new file mode 100644 index 00000000000..84efafba4e4 --- /dev/null +++ b/java/ql/lib/ext/org.apache.commons.jelly.model.yml @@ -0,0 +1,11 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(JellyContext,URL,URL)", "", "Argument[1]", "open-url", "ai-generated"] + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(JellyContext,URL,URL)", "", "Argument[2]", "open-url", "ai-generated"] + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(JellyContext,URL)", "", "Argument[1]", "open-url", "ai-generated"] + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(URL,URL)", "", "Argument[0]", "open-url", "ai-generated"] + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(URL,URL)", "", "Argument[1]", "open-url", "ai-generated"] + - ["org.apache.commons.jelly", "JellyContext", True, "JellyContext", "(URL)", "", "Argument[0]", "open-url", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.http.client.utils.model.yml b/java/ql/lib/ext/org.apache.http.client.utils.model.yml new file mode 100644 index 00000000000..e184ff0cdc8 --- /dev/null +++ b/java/ql/lib/ext/org.apache.http.client.utils.model.yml @@ -0,0 +1,12 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.apache.http.client.utils", "URIBuilder", True, "setHost", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URIBuilder", True, "setHost", "(String)", "", "Argument[0]", "ReturnValue", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URIBuilder", True, "setPath", "(String)", "", "Argument[0]", "Argument[-1].SyntheticField[org.apache.http.client.utils.URIBuilder.path]", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URIBuilder", True, "setPathSegments", "(List)", "", "Argument[0]", "Argument[-1].SyntheticField[org.apache.http.client.utils.URIBuilder.path]", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URIBuilder", True, "URIBuilder", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URIBuilder", True, "URIBuilder", "(URI)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] + - ["org.apache.http.client.utils", "URLEncodedUtils", True, "parse", "(URI,String)", "", "Argument[0]", "ReturnValue.Element", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.tools.ant.model.yml b/java/ql/lib/ext/org.apache.tools.ant.model.yml new file mode 100644 index 00000000000..2f3870c8ee7 --- /dev/null +++ b/java/ql/lib/ext/org.apache.tools.ant.model.yml @@ -0,0 +1,10 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.tools.ant", "AntClassLoader", True, "addPathComponent", "(File)", "", "Argument[0]", "read-file", "ai-generated"] + - ["org.apache.tools.ant", "AntClassLoader", True, "AntClassLoader", "(ClassLoader,Project,Path,boolean)", "", "Argument[2]", "read-file", "ai-generated"] + - ["org.apache.tools.ant", "AntClassLoader", True, "AntClassLoader", "(Project,Path,boolean)", "", "Argument[1]", "read-file", "ai-generated"] + - ["org.apache.tools.ant", "AntClassLoader", True, "AntClassLoader", "(Project,Path)", "", "Argument[1]", "read-file", "ai-generated"] + - ["org.apache.tools.ant", "DirectoryScanner", True, "setBasedir", "(File)", "", "Argument[0]", "read-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.tools.ant.taskdefs.model.yml b/java/ql/lib/ext/org.apache.tools.ant.taskdefs.model.yml new file mode 100644 index 00000000000..892f8c15876 --- /dev/null +++ b/java/ql/lib/ext/org.apache.tools.ant.taskdefs.model.yml @@ -0,0 +1,11 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.tools.ant.taskdefs", "Copy", True, "addFileset", "(FileSet)", "", "Argument[0]", "read-file", "ai-generated"] + - ["org.apache.tools.ant.taskdefs", "Copy", True, "setFile", "(File)", "", "Argument[0]", "read-file", "ai-generated"] + - ["org.apache.tools.ant.taskdefs", "Copy", True, "setTodir", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["org.apache.tools.ant.taskdefs", "Copy", True, "setTofile", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["org.apache.tools.ant.taskdefs", "Expand", True, "setDest", "(File)", "", "Argument[0]", "create-file", "ai-generated"] + - ["org.apache.tools.ant.taskdefs", "Expand", True, "setSrc", "(File)", "", "Argument[0]", "read-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.apache.tools.zip.model.yml b/java/ql/lib/ext/org.apache.tools.zip.model.yml new file mode 100644 index 00000000000..e70c0fa6ed5 --- /dev/null +++ b/java/ql/lib/ext/org.apache.tools.zip.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.apache.tools.zip", "ZipEntry", True, "ZipEntry", "(String)", "", "Argument[0]", "Argument[-1]", "taint", "ai-generated"] diff --git a/java/ql/lib/ext/org.codehaus.cargo.container.installer.model.yml b/java/ql/lib/ext/org.codehaus.cargo.container.installer.model.yml new file mode 100644 index 00000000000..9c0c9db9172 --- /dev/null +++ b/java/ql/lib/ext/org.codehaus.cargo.container.installer.model.yml @@ -0,0 +1,8 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.codehaus.cargo.container.installer", "ZipURLInstaller", True, "ZipURLInstaller", "(URL,String,String)", "", "Argument[0]", "open-url", "ai-generated"] + - ["org.codehaus.cargo.container.installer", "ZipURLInstaller", True, "ZipURLInstaller", "(URL,String,String)", "", "Argument[1]", "create-file", "ai-generated"] + - ["org.codehaus.cargo.container.installer", "ZipURLInstaller", True, "ZipURLInstaller", "(URL,String,String)", "", "Argument[2]", "create-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.kohsuke.stapler.framework.adjunct.model.yml b/java/ql/lib/ext/org.kohsuke.stapler.framework.adjunct.model.yml new file mode 100644 index 00000000000..2d855a9aa42 --- /dev/null +++ b/java/ql/lib/ext/org.kohsuke.stapler.framework.adjunct.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.kohsuke.stapler.framework.adjunct", "AdjunctManager", True, "AdjunctManager", "(ServletContext,ClassLoader,String,long)", "", "Argument[2]", "Argument[-1].Field[org.kohsuke.stapler.framework.adjunct.AdjunctManager.rootURL]", "taint", "ai-generated"] # the class never accesses the URL, but the field is public diff --git a/java/ql/lib/ext/org.kohsuke.stapler.framework.io.model.yml b/java/ql/lib/ext/org.kohsuke.stapler.framework.io.model.yml new file mode 100644 index 00000000000..86cdbc2b740 --- /dev/null +++ b/java/ql/lib/ext/org.kohsuke.stapler.framework.io.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.kohsuke.stapler.framework.io", "LargeText", True, "LargeText", "(File,Charset,boolean,boolean)", "", "Argument[0]", "read-file", "ai-generated"] diff --git a/java/ql/lib/ext/org.kohsuke.stapler.model.yml b/java/ql/lib/ext/org.kohsuke.stapler.model.yml new file mode 100644 index 00000000000..5b399f64ccd --- /dev/null +++ b/java/ql/lib/ext/org.kohsuke.stapler.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.kohsuke.stapler", "HttpResponses", True, "redirectTo", "(String)", "", "Argument[0]", "url-redirect", "ai-generated"] + - ["org.kohsuke.stapler", "HttpResponses", True, "staticResource", "(URL)", "", "Argument[0]", "open-url", "ai-generated"] diff --git a/java/ql/lib/ext/org.openjdk.jmh.runner.options.model.yml b/java/ql/lib/ext/org.openjdk.jmh.runner.options.model.yml new file mode 100644 index 00000000000..fd37cd1796d --- /dev/null +++ b/java/ql/lib/ext/org.openjdk.jmh.runner.options.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.openjdk.jmh.runner.options", "ChainedOptionsBuilder", True, "result", "(String)", "", "Argument[0]", "create-file", "ai-generated"] diff --git a/java/ql/lib/qlpack.yml b/java/ql/lib/qlpack.yml index fb4ea6dca37..90fcc57cebf 100644 --- a/java/ql/lib/qlpack.yml +++ b/java/ql/lib/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-all -version: 0.5.4-dev +version: 0.5.5-dev groups: java dbscheme: config/semmlecode.dbscheme extractor: java diff --git a/java/ql/lib/semmle/code/java/Expr.qll b/java/ql/lib/semmle/code/java/Expr.qll index 42b8313e063..b4fbfc55818 100644 --- a/java/ql/lib/semmle/code/java/Expr.qll +++ b/java/ql/lib/semmle/code/java/Expr.qll @@ -701,14 +701,6 @@ class StringLiteral extends Literal, @stringliteral { */ override string getValue() { result = super.getValue() } - /** - * DEPRECATED: This predicate will be removed in a future version because - * it is just an alias for `getValue()`; that predicate should be used instead. - * - * Gets the literal string without the quotes. - */ - deprecated string getRepresentedString() { result = this.getValue() } - /** Holds if this string literal is a text block (`""" ... """`). */ predicate isTextBlock() { this.getLiteral().matches("\"\"\"%") } diff --git a/java/ql/lib/semmle/code/java/PrintAst.qll b/java/ql/lib/semmle/code/java/PrintAst.qll index 0e52be33149..44e5f9fa22e 100644 --- a/java/ql/lib/semmle/code/java/PrintAst.qll +++ b/java/ql/lib/semmle/code/java/PrintAst.qll @@ -132,9 +132,9 @@ private newtype TPrintAstNode = TGenericTypeNode(GenericType ty) { shouldPrint(ty, _) } or TGenericCallableNode(GenericCallable c) { shouldPrint(c, _) } or TDocumentableNode(Documentable d) { shouldPrint(d, _) and exists(d.getJavadoc()) } or - TJavadocNode(Javadoc jd) { exists(Documentable d | d.getJavadoc() = jd | shouldPrint(d, _)) } or - TJavadocElementNode(JavadocElement jd) { - exists(Documentable d | d.getJavadoc() = jd.getParent*() | shouldPrint(d, _)) + TJavadocNode(Javadoc jd, Documentable d) { d.getJavadoc() = jd and shouldPrint(d, _) } or + TJavadocElementNode(JavadocElement jd, Documentable d) { + d.getJavadoc() = jd.getParent*() and shouldPrint(d, _) } or TImportsNode(CompilationUnit cu) { shouldPrint(cu, _) and exists(Import i | i.getCompilationUnit() = cu) @@ -537,17 +537,13 @@ final class ClassInterfaceNode extends ElementNode { or childIndex >= 0 and result.(ElementNode).getElement() = - rank[childIndex](Element e, string file, int line, int column, string childStr, int argCount | + rank[childIndex](Element e, string file, int line, int column, string childStr, string sig | e = this.getADeclaration() and locationSortKeys(e, file, line, column) and childStr = e.toString() and - ( - if e instanceof Callable - then argCount = e.(Callable).getNumberOfParameters() - else argCount = 0 - ) + (if e instanceof Callable then sig = e.(Callable).getStringSignature() else sig = "") | - e order by file, line, column, childStr, argCount + e order by file, line, column, childStr, sig ) } } @@ -794,6 +790,7 @@ final class DocumentableNode extends PrintAstNode, TDocumentableNode { override Location getLocation() { none() } override JavadocNode getChild(int childIndex) { + result.getDocumentable() = d and result.getJavadoc() = rank[childIndex](Javadoc jd, string file, int line, int column | jd.getCommentedElement() = d and jd.getLocation().hasLocationInfo(file, line, column, _, _) @@ -814,14 +811,16 @@ final class DocumentableNode extends PrintAstNode, TDocumentableNode { */ final class JavadocNode extends PrintAstNode, TJavadocNode { Javadoc jd; + Documentable d; - JavadocNode() { this = TJavadocNode(jd) } + JavadocNode() { this = TJavadocNode(jd, d) and not duplicateMetadata(d) } override string toString() { result = getQlClass(jd) + jd.toString() } override Location getLocation() { result = jd.getLocation() } override JavadocElementNode getChild(int childIndex) { + result.getDocumentable() = d and result.getJavadocElement() = jd.getChild(childIndex) } @@ -829,6 +828,11 @@ final class JavadocNode extends PrintAstNode, TJavadocNode { * Gets the `Javadoc` represented by this node. */ Javadoc getJavadoc() { result = jd } + + /** + * Gets the `Documentable` whose `Javadoc` is represented by this node. + */ + Documentable getDocumentable() { result = d } } /** @@ -837,14 +841,16 @@ final class JavadocNode extends PrintAstNode, TJavadocNode { */ final class JavadocElementNode extends PrintAstNode, TJavadocElementNode { JavadocElement jd; + Documentable d; - JavadocElementNode() { this = TJavadocElementNode(jd) } + JavadocElementNode() { this = TJavadocElementNode(jd, d) and not duplicateMetadata(d) } override string toString() { result = getQlClass(jd) + jd.toString() } override Location getLocation() { result = jd.getLocation() } override JavadocElementNode getChild(int childIndex) { + result.getDocumentable() = d and result.getJavadocElement() = jd.(JavadocParent).getChild(childIndex) } @@ -852,6 +858,11 @@ final class JavadocElementNode extends PrintAstNode, TJavadocElementNode { * Gets the `JavadocElement` represented by this node. */ JavadocElement getJavadocElement() { result = jd } + + /** + * Gets the `Documentable` whose `JavadocElement` is represented by this node. + */ + Documentable getDocumentable() { result = d } } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/DataFlow.qll b/java/ql/lib/semmle/code/java/dataflow/DataFlow.qll index 1b4409234e6..3676423ccbf 100644 --- a/java/ql/lib/semmle/code/java/dataflow/DataFlow.qll +++ b/java/ql/lib/semmle/code/java/dataflow/DataFlow.qll @@ -6,5 +6,6 @@ import java module DataFlow { - import semmle.code.java.dataflow.internal.DataFlowImpl + import semmle.code.java.dataflow.internal.DataFlow + import semmle.code.java.dataflow.internal.DataFlowImpl1 } diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll index 09a5f05914f..6d6af4f82b4 100644 --- a/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll +++ b/java/ql/lib/semmle/code/java/dataflow/FlowSummary.qll @@ -171,6 +171,8 @@ class SummarizedCallableBase extends TSummarizedCallableBase { class SummarizedCallable = Impl::Public::SummarizedCallable; +class NeutralCallable = Impl::Public::NeutralCallable; + /** * An adapter class to add the flow summaries specified on `SyntheticCallable` * to `SummarizedCallable`. diff --git a/java/ql/lib/semmle/code/java/dataflow/TaintTracking.qll b/java/ql/lib/semmle/code/java/dataflow/TaintTracking.qll index 853b8c5d63c..37a26bf38bf 100644 --- a/java/ql/lib/semmle/code/java/dataflow/TaintTracking.qll +++ b/java/ql/lib/semmle/code/java/dataflow/TaintTracking.qll @@ -8,5 +8,6 @@ import semmle.code.java.dataflow.DataFlow2 import semmle.code.java.dataflow.internal.TaintTrackingUtil::StringBuilderVarModule module TaintTracking { + import semmle.code.java.dataflow.internal.tainttracking1.TaintTracking import semmle.code.java.dataflow.internal.tainttracking1.TaintTrackingImpl } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll new file mode 100644 index 00000000000..617362ab4f0 --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlow.qll @@ -0,0 +1,353 @@ +/** + * Provides an implementation of global (interprocedural) data flow. This file + * re-exports the local (intraprocedural) data flow analysis from + * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed + * through the `Make` and `MakeWithState` modules. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +import DataFlowImplCommonPublic +private import DataFlowImpl + +/** An input configuration for data flow. */ +signature module ConfigSig { + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source); + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** An input configuration for data flow using flow state. */ +signature module StateConfigSig { + bindingset[this] + class FlowState; + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state); + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state); + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + default predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state); + + /** Holds if data flow into `node` is prohibited. */ + default predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + default predicate isBarrierOut(Node node) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + default predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + default predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + default int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + default FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + default predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + default predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (as it is in a `path-problem` query). + */ + default predicate includeHiddenNodes() { none() } +} + +/** + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ +signature int explorationLimitSig(); + +/** + * The output of a data flow computation. + */ +signature module DataFlowSig { + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode; + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink); + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink); + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink); +} + +/** + * Constructs a standard data flow computation. + */ +module Make implements DataFlowSig { + private module C implements FullStateConfigSig { + import DefaultState + import Config + } + + import Impl +} + +/** + * Constructs a data flow computation using flow state. + */ +module MakeWithState implements DataFlowSig { + private module C implements FullStateConfigSig { + import Config + } + + import Impl +} + +signature class PathNodeSig { + /** Gets a textual representation of this element. */ + string toString(); + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ); + + /** Gets the underlying `Node`. */ + Node getNode(); +} + +signature module PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + predicate edges(PathNode a, PathNode b); + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + predicate nodes(PathNode n, string key, string val); + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out); +} + +/** + * Constructs a `PathGraph` from two `PathGraph`s by disjoint union. + */ +module MergePathGraph< + PathNodeSig PathNode1, PathNodeSig PathNode2, PathGraphSig Graph1, + PathGraphSig Graph2> +{ + private newtype TPathNode = + TPathNode1(PathNode1 p) or + TPathNode2(PathNode2 p) + + /** A node in a graph of path explanations that is formed by disjoint union of the two given graphs. */ + class PathNode extends TPathNode { + /** Gets this as a projection on the first given `PathGraph`. */ + PathNode1 asPathNode1() { this = TPathNode1(result) } + + /** Gets this as a projection on the second given `PathGraph`. */ + PathNode2 asPathNode2() { this = TPathNode2(result) } + + /** Gets a textual representation of this element. */ + string toString() { + result = this.asPathNode1().toString() or + result = this.asPathNode2().toString() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.asPathNode1().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) or + this.asPathNode2().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + Node getNode() { + result = this.asPathNode1().getNode() or + result = this.asPathNode2().getNode() + } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PathGraph implements PathGraphSig { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PathNode a, PathNode b) { + Graph1::edges(a.asPathNode1(), b.asPathNode1()) or + Graph2::edges(a.asPathNode2(), b.asPathNode2()) + } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + Graph1::nodes(n.asPathNode1(), key, val) or + Graph2::nodes(n.asPathNode2(), key, val) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Graph1::subpaths(arg.asPathNode1(), par.asPathNode1(), ret.asPathNode1(), out.asPathNode1()) or + Graph2::subpaths(arg.asPathNode2(), par.asPathNode2(), ret.asPathNode2(), out.asPathNode2()) + } + } +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll index 22e79a2240d..875fbd43921 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowDispatch.qll @@ -11,6 +11,8 @@ private module DispatchImpl { private predicate hasHighConfidenceTarget(Call c) { exists(SummarizedCallable sc | sc.getACall() = c and not sc.isAutoGenerated()) or + exists(NeutralCallable nc | nc.getACall() = c and nc.isManual()) + or exists(Callable srcTgt | srcTgt = VirtualDispatch::viableCallable(c) and not VirtualDispatch::lowConfidenceDispatchTarget(c, srcTgt) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll deleted file mode 100644 index b66c1aa3c2f..00000000000 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses (for internal use only). - * - * This copy of the library is exclusively for use by `OnActivityResultSource.qll` and - * related libraries. Configurations computed using this instance of the library - * are in scope whenever `java.qll` is imported, and are used to compute among - * other things `RemoteFlowSource`s. - */ - -import java - -/** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses (for internal use only). - */ -module DataFlowForOnActivityResult { - import semmle.code.java.dataflow.internal.DataFlowImplForOnActivityResult -} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForSerializability.qll deleted file mode 100644 index 87c55fc8f31..00000000000 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForSerializability.qll +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses (for internal use only). - * - * This copy of the library is exclusively for use by `Serializability.qll` and - * related libraries. Configurations computed using this instance of the library - * are in scope whenever `java.qll` is imported, and are used to compute among - * other things `AdditionalTaintStep`. - */ - -import java - -/** - * Provides classes for performing local (intra-procedural) and - * global (inter-procedural) data flow analyses (for internal use only). - */ -module DataFlowForSerializability { - import semmle.code.java.dataflow.internal.DataFlowImplForSerializability -} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 1b969756b09..b7cb98deaf9 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1,135 +1,75 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * INTERNAL: Do not use. + * + * Provides an implementation of global (interprocedural) data flow. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic +private import DataFlowImplSpecific::Public +private import DataFlowImplCommonPublic +import DataFlow /** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + * An input configuration for data flow using flow state. This signature equals + * `StateConfigSig`, but requires explicit implementation of all predicates. */ -abstract class Configuration extends string { +signature module FullStateConfigSig { bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } + class FlowState; /** * Holds if `source` is a relevant data flow source with the given initial * `state`. */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } + predicate isSource(Node source, FlowState state); /** * Holds if `sink` is a relevant data flow sink accepting `state`. */ - predicate isSink(Node sink, FlowState state) { none() } + predicate isSink(Node sink, FlowState state); /** * Holds if data flow through `node` is prohibited. This completely removes * `node` from the data flow graph. */ - predicate isBarrier(Node node) { none() } + predicate isBarrier(Node node); /** * Holds if data flow through `node` is prohibited when the flow state is * `state`. */ - predicate isBarrier(Node node, FlowState state) { none() } + predicate isBarrier(Node node, FlowState state); /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } + predicate isBarrierIn(Node node); /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + predicate isBarrierOut(Node node); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + predicate isAdditionalFlowStep(Node node1, Node node2); /** * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. * This step is only applicable in `state1` and updates the flow state to `state2`. */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2); /** * Holds if an arbitrary number of implicit read steps of content `c` may be * taken at `node`. */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } + predicate allowImplicitRead(Node node, ContentSet c); /** * Gets the virtual dispatch branching limit when calculating field flow. * This can be overridden to a smaller value to improve performance (a * value of 0 disables field flow), or a larger value to get more results. */ - int fieldFlowBranchLimit() { result = 2 } + int fieldFlowBranchLimit(); /** * Gets a data flow configuration feature to add restrictions to the set of @@ -144,1720 +84,685 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ - FlowFeature getAFeature() { none() } + FlowFeature getAFeature(); /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } + predicate sourceGrouping(Node source, string sourceGroup); /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } + predicate sinkGrouping(Node sink, string sinkGroup); /** * Holds if hidden nodes should be included in the data flow graph. * * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). + * is not visualized (as it is in a `path-problem` query). */ - predicate includeHiddenNodes() { none() } + predicate includeHiddenNodes(); +} - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } +/** + * Provides default `FlowState` implementations given a `StateConfigSig`. + */ +module DefaultState { + class FlowState = Unit; - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() + predicate isSource(Node source, FlowState state) { Config::isSource(source) and exists(state) } + + predicate isSink(Node sink, FlowState state) { Config::isSink(sink) and exists(state) } + + predicate isBarrier(Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() } } /** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. + * Constructs a data flow computation given a full input configuration. */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } +module Impl { + private class FlowState = Config::FlowState; - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} + private newtype TNodeEx = + TNodeNormal(Node n) or + TNodeImplicitRead(Node n, boolean hasRead) { + Config::allowImplicitRead(n, _) and hasRead = [false, true] + } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false + private class NodeEx extends TNodeEx { + string toString() { + result = this.asNode().toString() or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) + exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") } - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } + Node asNode() { this = TNodeNormal(result) } + + predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } + + Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) + private DataFlowCallable getEnclosingCallable0() { + nodeEnclosingCallable(this.projectToNode(), result) } pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) + DataFlowCallable getEnclosingCallable() { + pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) } pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config + private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } + + pragma[inline] + DataFlowType getDataFlowType() { + pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) + } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) + this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + private class ArgNodeEx extends NodeEx { + ArgNodeEx() { this.asNode() instanceof ArgNode } + } + + private class ParamNodeEx extends NodeEx { + ParamNodeEx() { this.asNode() instanceof ParamNode } + + predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { + this.asNode().(ParamNode).isParameterOf(c, pos) + } + + ParameterPosition getPosition() { this.isParameterOf(_, result) } + } + + private class RetNodeEx extends NodeEx { + RetNodeEx() { this.asNode() instanceof ReturnNodeExt } + + ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } + + ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } + } + + private predicate inBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierIn(n) and + Config::isSource(n, _) + ) + } + + private predicate outBarrier(NodeEx node) { + exists(Node n | + node.asNode() = n and + Config::isBarrierOut(n) and + Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate fullBarrier(NodeEx node) { + exists(Node n | node.asNode() = n | + Config::isBarrier(n) or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) + Config::isBarrierIn(n) and + not Config::isSource(n, _) + or + Config::isBarrierOut(n) and + not Config::isSink(n, _) + ) + } + + pragma[nomagic] + private predicate stateBarrier(NodeEx node, FlowState state) { + exists(Node n | node.asNode() = n | Config::isBarrier(n, state)) + } + + pragma[nomagic] + private predicate sourceNode(NodeEx node, FlowState state) { + Config::isSource(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + pragma[nomagic] + private predicate sinkNode(NodeEx node, FlowState state) { + Config::isSink(node.asNode(), state) and + not fullBarrier(node) and + not stateBarrier(node, state) + } + + /** Provides the relevant barriers for a step from `node1` to `node2`. */ + pragma[inline] + private predicate stepFilter(NodeEx node1, NodeEx node2) { + not outBarrier(node1) and + not inBarrier(node2) and + not fullBarrier(node1) and + not fullBarrier(node2) + } + + /** + * Holds if data can flow in one local step from `node1` to `node2`. + */ + private predicate localFlowStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.asNode() = n and + node2.isImplicitReadNode(n, false) and + not fullBarrier(node1) + ) + } + + /** + * Holds if the additional step from `node1` to `node2` does not jump between callables. + */ + private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) + ) + or + exists(Node n | + Config::allowImplicitRead(n, _) and + node1.isImplicitReadNode(n, true) and + node2.asNode() = n and + not fullBarrier(node2) + ) + } + + private predicate additionalLocalStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) + ) + } + + /** + * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. + */ + private predicate jumpStepEx(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if the additional step from `node1` to `node2` jumps between callables. + */ + private predicate additionalJumpStep(NodeEx node1, NodeEx node2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate additionalJumpStateStep(NodeEx node1, FlowState s1, NodeEx node2, FlowState s2) { + exists(Node n1, Node n2 | + node1.asNode() = n1 and + node2.asNode() = n2 and + Config::isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and + getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and + stepFilter(node1, node2) and + not stateBarrier(node1, s1) and + not stateBarrier(node2, s2) and + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) + } + + pragma[nomagic] + private predicate readSetEx(NodeEx node1, ContentSet c, NodeEx node2) { + readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and + stepFilter(node1, node2) + or + exists(Node n | + node2.isImplicitReadNode(n, true) and + node1.isImplicitReadNode(n, _) and + Config::allowImplicitRead(n, c) + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate read(NodeEx node1, Content c, NodeEx node2) { + exists(ContentSet cs | + readSetEx(node1, cs, node2) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate clearsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + clearsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + // inline to reduce fan-out via `getAReadContent` + bindingset[c] + private predicate expectsContentEx(NodeEx n, Content c) { + exists(ContentSet cs | + expectsContentCached(n.asNode(), cs) and + pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() + ) + } + + pragma[nomagic] + private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } + + pragma[nomagic] + private predicate hasReadStep(Content c) { read(_, c, _) } + + pragma[nomagic] + private predicate storeEx(NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType) { + store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), + contentType) and + hasReadStep(tc.getContent()) and + stepFilter(node1, node2) + } + + pragma[nomagic] + private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { + viableReturnPosOut(call, pos, out.asNode()) + } + + pragma[nomagic] + private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + viableParamArg(call, p.asNode(), arg.asNode()) + } + + /** + * Holds if field flow should be used for the given configuration. + */ + private predicate useFieldFlow() { Config::fieldFlowBranchLimit() >= 1 } + + private predicate hasSourceCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSourceCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + private predicate sourceCallCtx(CallContext cc) { + if hasSourceCallCtx() then cc instanceof CallContextSomeCall else cc instanceof CallContextAny + } + + private predicate hasSinkCallCtx() { + exists(FlowFeature feature | feature = Config::getAFeature() | + feature instanceof FeatureHasSinkCallContext or + feature instanceof FeatureEqualSourceSinkCallContext + ) + } + + /** + * Holds if flow from `p` to a return node of kind `kind` is allowed. + * + * We don't expect a parameter to return stored in itself, unless + * explicitly allowed + */ + bindingset[p, kind] + private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { + exists(ParameterPosition pos | p.isParameterOf(_, pos) | + not kind.(ParamUpdateReturnKind).getPosition() = pos + or + allowParameterReturnInSelfCached(p.asNode()) + ) + } + + private module Stage1 implements StageSig { + class Ap extends int { + // workaround for bad functionality-induced joins (happens when using `Unit`) + pragma[nomagic] + Ap() { this in [0 .. 1] and this < 1 } + } + + private class Cc = boolean; + + /* Begin: Stage 1 logic. */ + /** + * Holds if `node` is reachable from a source. + * + * The Boolean `cc` records whether the node is reached through an + * argument in a call. + */ + pragma[assume_small_delta] + private predicate fwdFlow(NodeEx node, Cc cc) { + sourceNode(node, _) and + if hasSourceCallCtx() then cc = true else cc = false + or + exists(NodeEx mid | fwdFlow(mid, cc) | + localFlowStepEx(mid, node) or + additionalLocalFlowStep(mid, node) or + additionalLocalStateStep(mid, _, node, _) ) or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) + exists(NodeEx mid | fwdFlow(mid, _) and cc = false | + jumpStepEx(mid, node) or + additionalJumpStep(mid, node) or + additionalJumpStateStep(mid, _, node, _) ) or // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) + exists(NodeEx mid | + useFieldFlow() and + fwdFlow(mid, cc) and + storeEx(mid, _, node, _) ) or // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) + exists(ContentSet c | + fwdFlowReadSet(c, node, cc) and + fwdFlowConsCandSet(c, _) ) or // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) + fwdFlowIn(_, _, _, node) and + cc = true or // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) + fwdFlowOut(_, node, false) and + cc = false or // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) + exists(DataFlowCall call | + fwdFlowOutFromArg(call, node) and + fwdFlowIsEntered(call, cc) ) } + // inline to reduce the number of iterations pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and + private predicate fwdFlowIn(DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p) { + // call context cannot help reduce virtual dispatch + fwdFlow(arg, cc) and + viableParamArgEx(call, p, arg) and + not fullBarrier(p) and ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) + cc = false + or + cc = true and + not reducedViableImplInCallContext(call, _, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil + // call context may help reduce virtual dispatch + exists(DataFlowCallable target | + fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target) and + target = viableImplInSomeFwdFlowCallContextExt(call) and + cc = true ) - or + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc) { fwdFlowIn(call, _, cc, _) } + + pragma[nomagic] + private predicate fwdFlowInReducedViableImplInSomeCallContext( + DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target + ) { + fwdFlow(arg, true) and + viableParamArgEx(call, p, arg) and + reducedViableImplInCallContext(call, _, _) and + target = p.getEnclosingCallable() and + not fullBarrier(p) + } + + /** + * Gets a viable dispatch target of `call` in the context `ctx`. This is + * restricted to those `call`s for which a context might make a difference, + * and to `ctx`s that are reachable in `fwdFlow`. + */ + pragma[nomagic] + private DataFlowCallable viableImplInSomeFwdFlowCallContextExt(DataFlowCall call) { + exists(DataFlowCall ctx | + fwdFlowIsEntered(ctx, _) and + result = viableImplInCallContextExt(call, ctx) + ) + } + + private predicate fwdFlow(NodeEx node) { fwdFlow(node, _) } + + pragma[nomagic] + private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc) { exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() + fwdFlow(mid, cc) and + readSetEx(mid, c, node) + ) + } + + /** + * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, TypedContent tc | + not fullBarrier(node) and + useFieldFlow() and + fwdFlow(mid, _) and + storeEx(mid, tc, node, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `cs` may be interpreted in a read as the target of some store + * into `c`, in the flow covered by `fwdFlow`. + */ + pragma[nomagic] + private predicate fwdFlowConsCandSet(ContentSet cs, Content c) { + fwdFlowConsCand(c) and + c = cs.getAReadContent() + } + + pragma[nomagic] + private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc) { + exists(RetNodeEx ret | + fwdFlow(ret, cc) and + ret.getReturnPosition() = pos + ) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc) { + exists(ReturnPosition pos | + fwdFlowReturnPosition(pos, cc) and + viableReturnPosOutEx(call, pos, out) and + not fullBarrier(out) + ) + } + + pragma[nomagic] + private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out) { + fwdFlowOut(call, out, true) + } + + private predicate stateStepFwd(FlowState state1, FlowState state2) { + exists(NodeEx node1 | + additionalLocalStateStep(node1, state1, _, state2) or + additionalJumpStateStep(node1, state1, _, state2) + | + fwdFlow(node1) + ) + } + + private predicate fwdFlowState(FlowState state) { + sourceNode(_, state) + or + exists(FlowState state0 | + fwdFlowState(state0) and + stateStepFwd(state0, state) + ) + } + + /** + * Holds if `node` is part of a path from a source to a sink. + * + * The Boolean `toReturn` records whether the node must be returned from + * the enclosing callable in order to reach a sink. + */ + pragma[nomagic] + private predicate revFlow(NodeEx node, boolean toReturn) { + revFlow0(node, toReturn) and + fwdFlow(node) + } + + pragma[nomagic] + private predicate revFlow0(NodeEx node, boolean toReturn) { + exists(FlowState state | + fwdFlow(node) and + sinkNode(node, state) and + fwdFlowState(state) and + if hasSinkCallCtx() then toReturn = true else toReturn = false ) or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, toReturn) | + localFlowStepEx(node, mid) or + additionalLocalFlowStep(node, mid) or + additionalLocalStateStep(node, _, mid, _) ) or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil + exists(NodeEx mid | revFlow(mid, _) and toReturn = false | + jumpStepEx(node, mid) or + additionalJumpStep(node, mid) or + additionalJumpStateStep(node, _, mid, _) ) or // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) + exists(Content c | + revFlowStore(c, node, toReturn) and + revFlowConsCand(c) ) or // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) + exists(NodeEx mid, ContentSet c | + readSetEx(node, c, mid) and + fwdFlowConsCandSet(c, _) and + revFlow(mid, toReturn) ) or // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) + revFlowIn(_, node, false) and + toReturn = false or // flow out of a callable exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) + revFlowOut(pos) and + node.(RetNodeEx).getReturnPosition() = pos and + toReturn = true + ) + or + // flow through a callable + exists(DataFlowCall call | + revFlowInToReturn(call, node) and + revFlowIsReturned(call, toReturn) ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c } /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. + * Holds if `c` is the target of a read in the flow covered by `revFlow`. */ pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) + private predicate revFlowConsCand(Content c) { + exists(NodeEx mid, NodeEx node, ContentSet cs | + fwdFlow(node) and + readSetEx(node, cs, mid) and + fwdFlowConsCandSet(cs, c) and + revFlow(pragma[only_bind_into](mid), _) ) } pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config + private predicate revFlowStore(Content c, NodeEx node, boolean toReturn) { + exists(NodeEx mid, TypedContent tc | + revFlow(mid, toReturn) and + fwdFlowConsCand(c) and + storeEx(node, tc, mid, _) and + c = tc.getContent() + ) + } + + /** + * Holds if `c` is the target of both a read and a store in the flow covered + * by `revFlow`. + */ + pragma[nomagic] + additional predicate revFlowIsReadAndStored(Content c) { + revFlowConsCand(c) and + revFlowStore(c, _, _) + } + + pragma[nomagic] + additional predicate viableReturnPosOutNodeCandFwd1( + DataFlowCall call, ReturnPosition pos, NodeEx out ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() + fwdFlowReturnPosition(pos, _) and + viableReturnPosOutEx(call, pos, out) + } + + pragma[nomagic] + private predicate revFlowOut(ReturnPosition pos) { + exists(NodeEx out | + revFlow(out, _) and + viableReturnPosOutNodeCandFwd1(_, pos, out) ) } pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) + additional predicate viableParamArgNodeCandFwd1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + fwdFlowIn(call, arg, _, p) + } + + // inline to reduce the number of iterations + pragma[inline] + private predicate revFlowIn(DataFlowCall call, ArgNodeEx arg, boolean toReturn) { + exists(ParamNodeEx p | + revFlow(p, toReturn) and + viableParamArgNodeCandFwd1(call, p, arg) + ) } pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) + private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg) { + revFlowIn(call, arg, true) } /** @@ -1866,896 +771,1717 @@ private module MkStage { * reaching an argument of `call`. */ pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) + private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn) { + exists(NodeEx out | + revFlow(out, toReturn) and + fwdFlowOutFromArg(call, out) + ) + } + + private predicate stateStepRev(FlowState state1, FlowState state2) { + exists(NodeEx node1, NodeEx node2 | + additionalLocalStateStep(node1, state1, node2, state2) or + additionalJumpStateStep(node1, state1, node2, state2) + | + revFlow(node1, _) and + revFlow(node2, _) and + fwdFlowState(state1) and + fwdFlowState(state2) + ) + } + + pragma[nomagic] + additional predicate revFlowState(FlowState state) { + exists(NodeEx node | + sinkNode(node, state) and + revFlow(node, _) and + fwdFlowState(state) + ) + or + exists(FlowState state0 | + revFlowState(state0) and + stateStepRev(state, state0) ) } pragma[nomagic] predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) + exists(Content c | + revFlowIsReadAndStored(c) and + revFlow(node2) and + storeEx(node1, tc, node2, contentType) and + c = tc.getContent() and + exists(ap1) ) } pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() + predicate readStepCand(NodeEx n1, Content c, NodeEx n2) { + revFlowIsReadAndStored(c) and + read(n1, c, n2) and + revFlow(n2) + } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { + revFlow(node) and + exists(ap) + } + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap) { + revFlow(node, _) and + exists(state) and + exists(ap) + } + + private predicate throughFlowNodeCand(NodeEx node) { + revFlow(node, true) and + fwdFlow(node, true) and + not inBarrier(node) and + not outBarrier(node) + } + + /** Holds if flow may return from `callable`. */ + pragma[nomagic] + private predicate returnFlowCallableNodeCand(DataFlowCallable callable, ReturnKindExt kind) { + exists(RetNodeEx ret | + throughFlowNodeCand(ret) and + callable = ret.getEnclosingCallable() and + kind = ret.getKind() + ) + } + + /** + * Holds if flow may enter through `p` and reach a return node making `p` a + * candidate for the origin of a summary. + */ + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(DataFlowCallable c, ReturnKindExt kind | + throughFlowNodeCand(p) and + returnFlowCallableNodeCand(c, kind) and + p.getEnclosingCallable() = c and + exists(ap) and + parameterFlowThroughAllowed(p, kind) ) } pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + throughFlowNodeCand(ret) and + kind = ret.getKind() and + exists(argAp) and + exists(ap) } pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, boolean toReturn | + revFlow(arg, toReturn) and + revFlowInToReturn(call, arg) and + revFlowIsReturned(call, toReturn) ) } additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config + boolean fwd, int nodes, int fields, int conscand, int states, int tuples ) { fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) + nodes = count(NodeEx node | fwdFlow(node)) and + fields = count(Content f0 | fwdFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | fwdFlowState(state)) and + tuples = count(NodeEx n, boolean b | fwdFlow(n, b)) or fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) + nodes = count(NodeEx node | revFlow(node, _)) and + fields = count(Content f0 | revFlowConsCand(f0)) and + conscand = -1 and + states = count(FlowState state | revFlowState(state)) and + tuples = count(NodeEx n, boolean b | revFlow(n, b)) } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } + /* End: Stage 1 logic. */ } - class CcCall extends Cc { - CcCall() { this = true } + pragma[noinline] + private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + localFlowStepEx(node1, node2) } - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2) { + Stage1::revFlow(node2) and + additionalLocalFlowStep(node1, node2) } - Cc ccNone() { result = false } + pragma[nomagic] + private predicate viableReturnPosOutNodeCand1(DataFlowCall call, ReturnPosition pos, NodeEx out) { + Stage1::revFlow(out) and + Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out) + } - CcCall ccSomeCall() { result = true } + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out + ) { + exists(ReturnPosition pos | + viableReturnPosOutNodeCand1(call, pos, out) and + pos = ret.getReturnPosition() and + kind = pos.getKind() and + Stage1::revFlow(ret) and + not outBarrier(ret) and + not inBarrier(out) + ) + } - class LocalCc = Unit; + pragma[nomagic] + private predicate viableParamArgNodeCand1(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { + Stage1::viableParamArgNodeCandFwd1(call, p, arg) and + Stage1::revFlow(arg) + } - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1(DataFlowCall call, ArgNodeEx arg, ParamNodeEx p) { + viableParamArgNodeCand1(call, p, arg) and + Stage1::revFlow(p) and + not outBarrier(arg) and + not inBarrier(p) + } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + /** + * Gets an additional term that is added to `branch` and `join` when deciding whether + * the amount of forward or backward branching is within the limit specified by the + * configuration. + */ + pragma[nomagic] + private int getLanguageSpecificFlowIntoCallNodeCand1(ArgNodeEx arg, ParamNodeEx p) { + flowIntoCallNodeCand1(_, arg, p) and + result = getAdditionalFlowIntoCallNodeTerm(arg.projectToNode(), p.projectToNode()) + } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} + /** + * Gets the amount of forward branching on the origin of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int branch(NodeEx n1) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n1, _, n) or flowIntoCallNodeCand1(_, n1, n)) + + sum(ParamNodeEx p1 | | getLanguageSpecificFlowIntoCallNodeCand1(n1, p1)) + } -private module Level1CallContext { - class Cc = CallContext; + /** + * Gets the amount of backward branching on the target of a cross-call path + * edge in the graph of paths between sources and sinks that ignores call + * contexts. + */ + pragma[nomagic] + private int join(NodeEx n2) { + result = + strictcount(NodeEx n | flowOutOfCallNodeCand1(_, n, _, n2) or flowIntoCallNodeCand1(_, n, n2)) + + sum(ArgNodeEx arg2 | | getLanguageSpecificFlowIntoCallNodeCand1(arg2, n2)) + } - class CcCall = CallContextCall; + /** + * Holds if data can flow out of `call` from `ret` to `out`, either + * through a `ReturnNode` or through an argument that has been mutated, and + * that this step is part of a path from a source to a sink. The + * `allowsFieldFlow` flag indicates whether the branching is within the limit + * specified by the configuration. + */ + pragma[nomagic] + private predicate flowOutOfCallNodeCand1( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, ret, kind, out) and + exists(int b, int j | + b = branch(ret) and + j = join(out) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + /** + * Holds if data can flow into `call` and that this step is part of a + * path from a source to a sink. The `allowsFieldFlow` flag indicates whether + * the branching is within the limit specified by the configuration. + */ + pragma[nomagic] + private predicate flowIntoCallNodeCand1( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, arg, p) and + exists(int b, int j | + b = branch(arg) and + j = join(p) and + if b.minimum(j) <= Config::fieldFlowBranchLimit() + then allowsFieldFlow = true + else allowsFieldFlow = false + ) + } - class CcNoCall = CallContextNoCall; + private signature module StageSig { + class Ap; - Cc ccNone() { result instanceof CallContextAny } + predicate revFlow(NodeEx node); - CcCall ccSomeCall() { result instanceof CallContextSomeCall } + predicate revFlowAp(NodeEx node, Ap ap); + + bindingset[node, state] + predicate revFlow(NodeEx node, FlowState state, Ap ap); + + predicate callMayFlowThroughRev(DataFlowCall call); + + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap); + + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind); + + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ); + + predicate readStepCand(NodeEx n1, Content c, NodeEx n2); + } + + private module MkStage { + class ApApprox = PrevStage::Ap; + + signature module StageParam { + class Ap; + + class ApNil extends Ap; + + bindingset[result, ap] + ApApprox getApprox(Ap ap); + + ApNil getApNil(NodeEx node); + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail); + + /** + * An approximation of `Content` that corresponds to the precision level of + * `Ap`, such that the mappings from both `Ap` and `Content` to this type + * are functional. + */ + class ApHeadContent; + + ApHeadContent getHeadContent(Ap ap); + + ApHeadContent projectToHeadContent(Content c); + + class ApOption; + + ApOption apNone(); + + ApOption apSome(Ap ap); + + class Cc; + + class CcCall extends Cc; + + // TODO: member predicate on CcCall + predicate matchesCall(CcCall cc, DataFlowCall call); + + class CcNoCall extends Cc; + + Cc ccNone(); + + CcCall ccSomeCall(); + + class LocalCc; + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc); + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ); + + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow + ); + + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow + ); + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap); + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType); + } + + module Stage implements StageSig { + import Param + + /* Begin: Stage logic. */ + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + private predicate revFlowApAlias(NodeEx node, ApApprox apa) { + PrevStage::revFlowAp(node, apa) + } + + pragma[nomagic] + private predicate flowIntoCallApa( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa + ) { + flowIntoCall(call, arg, p, allowsFieldFlow) and + PrevStage::revFlowAp(p, pragma[only_bind_into](apa)) and + revFlowApAlias(arg, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowOutOfCallApa( + DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, + ApApprox apa + ) { + flowOutOfCall(call, ret, kind, out, allowsFieldFlow) and + PrevStage::revFlowAp(out, pragma[only_bind_into](apa)) and + revFlowApAlias(ret, pragma[only_bind_into](apa)) + } + + pragma[nomagic] + private predicate flowThroughOutOfCall( + DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, + ApApprox argApa, ApApprox apa + ) { + exists(ReturnKindExt kind | + flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa) and + PrevStage::callMayFlowThroughRev(call) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) and + matchesCall(ccc, call) + ) + } + + /** + * Holds if `node` is reachable with access path `ap` from a source. + * + * The call context `cc` records whether the node is reached through an + * argument in a call, and if so, `summaryCtx` and `argAp` record the + * corresponding parameter position and access path of that argument, respectively. + */ + pragma[nomagic] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa) and + PrevStage::revFlow(node, state, apa) and + filter(node, state, ap) + } + + pragma[inline] + additional predicate fwdFlow( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap + ) { + fwdFlow(node, state, cc, summaryCtx, argAp, ap, _) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate fwdFlow0( + NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, + ApApprox apa + ) { + sourceNode(node, state) and + (if hasSourceCallCtx() then cc = ccSomeCall() else cc = ccNone()) and + argAp = apNone() and + summaryCtx = TParamNodeNone() and + ap = getApNil(node) and + apa = getApprox(ap) + or + exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | + fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0) and + localCc = getLocalCc(mid, cc) + | + localStep(mid, state0, node, state, true, _, localCc) and + ap = ap0 and + apa = apa0 + or + localStep(mid, state0, node, state, false, ap, localCc) and + ap0 instanceof ApNil and + apa = getApprox(ap) + ) + or + exists(NodeEx mid | + fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa) and + jumpStepEx(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(mid, state, _, _, _, nil) and + additionalJumpStep(mid, node) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(mid, state0, _, _, _, nil) and + additionalJumpStateStep(mid, state0, node, state) and + cc = ccNone() and + summaryCtx = TParamNodeNone() and + argAp = apNone() and + ap = getApNil(node) and + apa = getApprox(ap) + ) + or + // store + exists(TypedContent tc, Ap ap0 | + fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp) and + ap = apCons(tc, ap0) and + apa = getApprox(ap) + ) + or + // read + exists(Ap ap0, Content c | + fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp) and + fwdFlowConsCand(ap0, c, ap) and + apa = getApprox(ap) + ) + or + // flow into a callable + fwdFlowIn(_, node, state, _, cc, _, _, ap, apa) and + if PrevStage::parameterMayFlowThrough(node, apa) + then ( + summaryCtx = TParamNodeSome(node.asNode()) and + argAp = apSome(ap) + ) else ( + summaryCtx = TParamNodeNone() and argAp = apNone() + ) + or + // flow out of a callable + exists( + DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, + DataFlowCallable inner + | + fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa) and + flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa) and + inner = ret.getEnclosingCallable() and + cc = getCallContextReturn(inner, call, innercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + or + // flow through a callable + exists( + DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, + ApApprox innerArgApa + | + fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowStore( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(DataFlowType contentType, ApApprox apa1 | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1) and + PrevStage::storeStepCand(node1, apa1, tc, node2, contentType) and + typecheckStore(ap1, contentType) + ) + } + + /** + * Holds if forward flow with access path `tail` reaches a store of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail) { + exists(TypedContent tc | + fwdFlowStore(_, tail, tc, _, _, _, _, _) and + tc.getContent() = c and + cons = apCons(tc, tail) + ) + } + + pragma[nomagic] + private predicate readStepCand(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + PrevStage::readStepCand(node1, c, node2) and + apc = projectToHeadContent(c) + } + + bindingset[node1, apc] + pragma[inline_late] + private predicate readStepCand0(NodeEx node1, ApHeadContent apc, Content c, NodeEx node2) { + readStepCand(node1, apc, c, node2) + } + + pragma[nomagic] + private predicate fwdFlowRead( + Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, + ParamNodeOption summaryCtx, ApOption argAp + ) { + exists(ApHeadContent apc | + fwdFlow(node1, state, cc, summaryCtx, argAp, ap) and + apc = getHeadContent(ap) and + readStepCand0(node1, apc, c, node2) + ) + } + + pragma[nomagic] + private predicate fwdFlowIn( + DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, + ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa + ) { + exists(ArgNodeEx arg, boolean allowsFieldFlow | + fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa) and + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate fwdFlowRetFromArg( + RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, + ApApprox argApa, Ap ap, ApApprox apa + ) { + exists(ReturnKindExt kind | + fwdFlow(pragma[only_bind_into](ret), state, ccc, + TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), + pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa)) and + kind = ret.getKind() and + parameterFlowThroughAllowed(summaryCtx, kind) and + argApa = getApprox(argAp) and + PrevStage::returnMayFlowThrough(ret, argApa, apa, kind) + ) + } + + pragma[inline] + private predicate fwdFlowThrough0( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, + Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa) and + fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp) + } + + pragma[nomagic] + private predicate fwdFlowThrough( + DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, + ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa) + } + + /** + * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` + * and data might flow through the target callable and back out at `call`. + */ + pragma[nomagic] + private predicate fwdFlowIsEntered( + DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, + ParamNodeEx p, Ap ap + ) { + exists(ApApprox apa | + fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, + pragma[only_bind_into](apa)) and + PrevStage::parameterMayFlowThrough(p, apa) and + PrevStage::callMayFlowThroughRev(call) + ) + } + + pragma[nomagic] + private predicate storeStepFwd(NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2) { + fwdFlowStore(node1, ap1, tc, node2, _, _, _, _) and + ap2 = apCons(tc, ap1) and + fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _) + } + + private predicate readStepFwd(NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2) { + fwdFlowRead(ap1, c, n1, n2, _, _, _, _) and + fwdFlowConsCand(ap1, c, ap2) + } + + pragma[nomagic] + private predicate returnFlowsThrough0( + DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, + ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa + ) { + fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, + innerArgApa) + } + + pragma[nomagic] + private predicate returnFlowsThrough( + RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, + Ap ap + ) { + exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | + returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa) and + flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa) and + pos = ret.getReturnPosition() and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowThroughIntoCall( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap + ) { + exists(ApApprox argApa | + flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), + allowsFieldFlow, argApa) and + fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa) and + returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap) and + if allowsFieldFlow = false then argAp instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate flowIntoCallAp( + DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap + ) { + exists(ApApprox apa | + flowIntoCallApa(call, arg, p, allowsFieldFlow, apa) and + fwdFlow(arg, _, _, _, _, ap, apa) + ) + } + + pragma[nomagic] + private predicate flowOutOfCallAp( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, + Ap ap + ) { + exists(ApApprox apa | + flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa) and + fwdFlow(ret, _, _, _, _, ap, apa) and + pos = ret.getReturnPosition() + ) + } + + /** + * Holds if `node` with access path `ap` is part of a path from a source to a + * sink. + * + * The parameter `returnCtx` records whether (and how) the node must be returned + * from the enclosing callable in order to reach a sink, and if so, `returnAp` + * records the access path of the returned value. + */ + pragma[nomagic] + additional predicate revFlow( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + revFlow0(node, state, returnCtx, returnAp, ap) and + fwdFlow(node, state, _, _, _, ap) + } + + pragma[nomagic] + private predicate revFlow0( + NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap + ) { + fwdFlow(node, state, _, _, _, ap) and + sinkNode(node, state) and + ( + if hasSinkCallCtx() + then returnCtx = TReturnCtxNoFlowThrough() + else returnCtx = TReturnCtxNone() + ) and + returnAp = apNone() and + ap instanceof ApNil + or + exists(NodeEx mid, FlowState state0 | + localStep(node, state, mid, state0, true, _, _) and + revFlow(mid, state0, returnCtx, returnAp, ap) + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap) and + localStep(node, pragma[only_bind_into](state), mid, state0, false, _, _) and + revFlow(mid, state0, returnCtx, returnAp, nil) and + ap instanceof ApNil + ) + or + exists(NodeEx mid | + jumpStepEx(node, mid) and + revFlow(mid, state, _, _, ap) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() + ) + or + exists(NodeEx mid, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStep(node, mid) and + revFlow(pragma[only_bind_into](mid), state, _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + exists(NodeEx mid, FlowState state0, ApNil nil | + fwdFlow(node, _, _, _, _, ap) and + additionalJumpStateStep(node, state, mid, state0) and + revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil) and + returnCtx = TReturnCtxNone() and + returnAp = apNone() and + ap instanceof ApNil + ) + or + // store + exists(Ap ap0, Content c | + revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp) and + revFlowConsCand(ap0, c, ap) + ) + or + // read + exists(NodeEx mid, Ap ap0 | + revFlow(mid, state, returnCtx, returnAp, ap0) and + readStepFwd(node, ap, _, mid, ap0) + ) + or + // flow into a callable + exists(ParamNodeEx p, boolean allowsFieldFlow | + revFlow(p, state, TReturnCtxNone(), returnAp, ap) and + flowIntoCallAp(_, node, p, allowsFieldFlow, ap) and + (if allowsFieldFlow = false then ap instanceof ApNil else any()) and + returnCtx = TReturnCtxNone() + ) + or + // flow through a callable + exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, node, p, _, ap, innerReturnAp) + ) + or + // flow out of a callable + exists(ReturnPosition pos | + revFlowOut(_, node, pos, state, _, _, ap) and + if returnFlowsThrough(node, pos, state, _, _, _, ap) + then ( + returnCtx = TReturnCtxMaybeFlowThrough(pos) and + returnAp = apSome(ap) + ) else ( + returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() + ) + ) + } + + pragma[nomagic] + private predicate revFlowStore( + Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, + ReturnCtx returnCtx, ApOption returnAp + ) { + revFlow(mid, state, returnCtx, returnAp, ap0) and + storeStepFwd(node, ap, tc, mid, ap0) and + tc.getContent() = c + } + + /** + * Holds if reverse flow with access path `tail` reaches a read of `c` + * resulting in access path `cons`. + */ + pragma[nomagic] + private predicate revFlowConsCand(Ap cons, Content c, Ap tail) { + exists(NodeEx mid, Ap tail0 | + revFlow(mid, _, _, _, tail) and + tail = pragma[only_bind_into](tail0) and + readStepFwd(_, cons, c, mid, tail0) + ) + } + + pragma[nomagic] + private predicate revFlowOut( + DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, + ApOption returnAp, Ap ap + ) { + exists(NodeEx out, boolean allowsFieldFlow | + revFlow(out, state, returnCtx, returnAp, ap) and + flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap) and + if allowsFieldFlow = false then ap instanceof ApNil else any() + ) + } + + pragma[nomagic] + private predicate revFlowParamToReturn( + ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap + ) { + revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), + pragma[only_bind_into](ap)) and + parameterFlowThroughAllowed(p, pos.getKind()) and + PrevStage::parameterMayFlowThrough(p, getApprox(ap)) + } + + pragma[nomagic] + private predicate revFlowThrough( + DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, + ApOption returnAp, Ap ap, Ap innerReturnAp + ) { + revFlowParamToReturn(p, state, pos, innerReturnAp, ap) and + revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp) + } + + /** + * Holds if an output from `call` is reached in the flow covered by `revFlow` + * and data might flow through the target callable resulting in reverse flow + * reaching an argument of `call`. + */ + pragma[nomagic] + private predicate revFlowIsReturned( + DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap + ) { + exists(RetNodeEx ret, FlowState state, CcCall ccc | + revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap) and + returnFlowsThrough(ret, pos, state, ccc, _, _, ap) and + matchesCall(ccc, call) + ) + } + + pragma[nomagic] + predicate storeStepCand( + NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType + ) { + exists(Ap ap2, Content c | + PrevStage::storeStepCand(node1, _, tc, node2, contentType) and + revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _) and + revFlowConsCand(ap2, c, ap1) + ) + } + + predicate readStepCand(NodeEx node1, Content c, NodeEx node2) { + exists(Ap ap1, Ap ap2 | + revFlow(node2, _, _, _, pragma[only_bind_into](ap2)) and + readStepFwd(node1, ap1, c, node2, ap2) and + revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _) + ) + } + + additional predicate revFlow(NodeEx node, FlowState state) { revFlow(node, state, _, _, _) } + + predicate revFlow(NodeEx node, FlowState state, Ap ap) { revFlow(node, state, _, _, ap) } + + pragma[nomagic] + predicate revFlow(NodeEx node) { revFlow(node, _, _, _, _) } + + pragma[nomagic] + predicate revFlowAp(NodeEx node, Ap ap) { revFlow(node, _, _, _, ap) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node) { revFlow(node, _, _, _, _) } + + // use an alias as a workaround for bad functionality-induced joins + pragma[nomagic] + additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap) { + revFlow(node, state, ap) + } + + private predicate fwdConsCand(TypedContent tc, Ap ap) { storeStepFwd(_, ap, tc, _, _) } + + private predicate revConsCand(TypedContent tc, Ap ap) { storeStepCand(_, ap, tc, _, _) } + + private predicate validAp(Ap ap) { + revFlow(_, _, _, _, ap) and ap instanceof ApNil + or + exists(TypedContent head, Ap tail | + consCand(head, tail) and + ap = apCons(head, tail) + ) + } + + additional predicate consCand(TypedContent tc, Ap ap) { + revConsCand(tc, ap) and + validAp(ap) + } + + pragma[nomagic] + private predicate parameterFlowsThroughRev( + ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp + ) { + revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap) and + parameterFlowThroughAllowed(p, pos.getKind()) + } + + pragma[nomagic] + predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap) { + exists(ReturnPosition pos | + returnFlowsThrough(_, pos, _, _, p, ap, _) and + parameterFlowsThroughRev(p, ap, pos, _) + ) + } + + pragma[nomagic] + predicate returnMayFlowThrough(RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind) { + exists(ParamNodeEx p, ReturnPosition pos | + returnFlowsThrough(ret, pos, _, _, p, argAp, ap) and + parameterFlowsThroughRev(p, argAp, pos, ap) and + kind = pos.getKind() + ) + } + + pragma[nomagic] + private predicate revFlowThroughArg( + DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, + Ap ap + ) { + exists(ParamNodeEx p, Ap innerReturnAp | + revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp) and + flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp) + ) + } + + pragma[nomagic] + predicate callMayFlowThroughRev(DataFlowCall call) { + exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | + revFlow(arg, state, returnCtx, returnAp, ap) and + revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap) + ) + } + + additional predicate stats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _)) and + fields = count(TypedContent f0 | fwdConsCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap)) and + states = count(FlowState state | fwdFlow(_, state, _, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | + fwdFlow(n, state, cc, summaryCtx, argAp, ap) + ) + or + fwd = false and + nodes = count(NodeEx node | revFlow(node, _, _, _, _)) and + fields = count(TypedContent f0 | consCand(f0, _)) and + conscand = count(TypedContent f0, Ap ap | consCand(f0, ap)) and + states = count(FlowState state | revFlow(_, state, _, _, _)) and + tuples = + count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | + revFlow(n, state, returnCtx, retAp, ap) + ) + } + /* End: Stage logic. */ + } + } + + private module BooleanCallContext { + class Cc extends boolean { + Cc() { this in [true, false] } + } + + class CcCall extends Cc { + CcCall() { this = true } + } + + /** Holds if the call context may be `call`. */ + predicate matchesCall(CcCall cc, DataFlowCall call) { any() } + + class CcNoCall extends Cc { + CcNoCall() { this = false } + } + + Cc ccNone() { result = false } + + CcCall ccSomeCall() { result = true } - module NoLocalCallContext { class LocalCc = Unit; bindingset[node, cc] LocalCc getLocalCc(NodeEx node, Cc cc) { any() } bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } + } + + private module Level1CallContext { + class Cc = CallContext; + + class CcCall = CallContextCall; + + pragma[inline] + predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } + + class CcNoCall = CallContextNoCall; + + Cc ccNone() { result instanceof CallContextAny } + + CcCall ccSomeCall() { result instanceof CallContextSomeCall } + + module NoLocalCallContext { + class LocalCc = Unit; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { any() } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSiteDispatch(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + module LocalCallContext { + class LocalCc = LocalCallContext; + + bindingset[node, cc] + LocalCc getLocalCc(NodeEx node, Cc cc) { + result = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + node.getEnclosingCallable()) + } + + bindingset[call, c, outercc] + CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { + checkCallContextCall(outercc, call, c) and + if recordDataFlowCallSite(call, c) + then result = TSpecificCall(call) + else result = TSomeCall() + } + } + + bindingset[call, c, innercc] + CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { + checkCallContextReturn(innercc, c, call) and + if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() } } - module LocalCallContext { - class LocalCc = LocalCallContext; + private module Stage2Param implements MkStage::StageParam { + private module PrevStage = Stage1; - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) + class Ap extends boolean { + Ap() { this in [true, false] } } - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() + class ApNil extends Ap { + ApNil() { this = false } } + + bindingset[result, ap] + PrevStage::Ap getApprox(Ap ap) { any() } + + ApNil getApNil(NodeEx node) { Stage1::revFlow(node) and exists(result) } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } + + class ApHeadContent = Unit; + + pragma[inline] + ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } + + ApHeadContent projectToHeadContent(Content c) { any() } + + class ApOption = BooleanOption; + + ApOption apNone() { result = TBooleanNone() } + + ApOption apSome(Ap ap) { result = TBooleanSome(ap) } + + import Level1CallContext + import NoLocalCallContext + + bindingset[node1, state1] + bindingset[node2, state2] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + ( + preservesValue = true and + localFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 + or + preservesValue = false and + additionalLocalStateStep(node1, state1, node2, state2) + ) and + exists(ap) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand1/5; + + predicate flowIntoCall = flowIntoCallNodeCand1/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::revFlowIsReadAndStored(c) and + expectsContentEx(node, c) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + PrevStage::revFlowState(state) and + exists(ap) and + not stateBarrier(node, state) and + ( + notExpectsContent(node) + or + ap = true and + expectsContentCand(node) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } } - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() + private module Stage2 implements StageSig { + import MkStage::Stage } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) + private predicate flowOutOfCallNodeCand2( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) + pragma[nomagic] + private predicate flowIntoCallNodeCand2( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow) and + Stage2::revFlow(node2) and + Stage2::revFlowAlias(node1) } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) + private module LocalFlowBigStep { + /** + * A node where some checking is required, and hence the big-step relation + * is not allowed to step over. + */ + private class FlowCheckNode extends NodeEx { + FlowCheckNode() { + castNode(this.asNode()) or + clearsContentCached(this.asNode(), _) or + expectsContentCached(this.asNode(), _) + } } - } - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) + /** + * Holds if `node` can be the first node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowEntry(NodeEx node, FlowState state) { + Stage2::revFlow(node, state) and + ( + sourceNode(node, state) + or + jumpStepEx(_, node) + or + additionalJumpStep(_, node) + or + additionalJumpStateStep(_, _, node, state) + or + node instanceof ParamNodeEx + or + node.asNode() instanceof OutNodeExt + or + Stage2::storeStepCand(_, _, _, node, _) + or + Stage2::readStepCand(_, _, node) + or + node instanceof FlowCheckNode + or + exists(FlowState s | + additionalLocalStateStep(_, s, node, state) and + s != state + ) + ) + } + + /** + * Holds if `node` can be the last node in a maximal subsequence of local + * flow steps in a dataflow path. + */ + private predicate localFlowExit(NodeEx node, FlowState state) { + exists(NodeEx next | Stage2::revFlow(next, state) | + jumpStepEx(node, next) or + additionalJumpStep(node, next) or + flowIntoCallNodeCand2(_, node, next, _) or + flowOutOfCallNodeCand2(_, node, _, next, _) or + Stage2::storeStepCand(node, _, _, next, _) or + Stage2::readStepCand(node, _, next) + ) or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and + exists(NodeEx next, FlowState s | Stage2::revFlow(next, s) | + additionalJumpStateStep(node, state, next, s) + or + additionalLocalStateStep(node, state, next, s) and s != state ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } + Stage2::revFlow(node, state) and + node instanceof FlowCheckNode + or + sinkNode(node, state) + } - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } + pragma[noinline] + private predicate additionalLocalFlowStepNodeCand2( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2 + ) { + additionalLocalFlowStepNodeCand1(node1, node2) and + state1 = state2 and + Stage2::revFlow(node1, pragma[only_bind_into](state1), false) and + Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false) + or + additionalLocalStateStep(node1, state1, node2, state2) and + Stage2::revFlow(node1, state1, false) and + Stage2::revFlowAlias(node2, state2, false) + } - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and + /** + * Holds if the local path from `node1` to `node2` is a prefix of a maximal + * subsequence of local flow steps in a dataflow path. + * + * This is the transitive closure of `[additional]localFlowStep` beginning + * at `localFlowEntry`. + */ + pragma[nomagic] + private predicate localFlowStepPlus( + NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, + LocalCallContext cc + ) { + not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + localFlowEntry(node1, pragma[only_bind_into](state)) and + ( + localFlowStepNodeCand1(node1, node2) and + preservesValue = true and + t = node1.getDataFlowType() and // irrelevant dummy value + Stage2::revFlow(node2, pragma[only_bind_into](state)) + or + additionalLocalFlowStepNodeCand2(node1, state, node2, state) and + preservesValue = false and + t = node2.getDataFlowType() + ) and + node1 != node2 and + cc.relevantFor(node1.getEnclosingCallable()) and + not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) + exists(NodeEx mid | + localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, cc) and + localFlowStepNodeCand1(mid, node2) and + not mid instanceof FlowCheckNode and + Stage2::revFlow(node2, pragma[only_bind_into](state)) + ) + or + exists(NodeEx mid | + localFlowStepPlus(node1, state, mid, _, _, cc) and + additionalLocalFlowStepNodeCand2(mid, state, node2, state) and + not mid instanceof FlowCheckNode and + preservesValue = false and + t = node2.getDataFlowType() + ) ) + } + + /** + * Holds if `node1` can step to `node2` in one or more local steps and this + * path can occur as a maximal subsequence of local steps in a dataflow path. + */ + pragma[nomagic] + predicate localFlowBigStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + DataFlowType t, LocalCallContext callContext + ) { + localFlowStepPlus(node1, state1, node2, preservesValue, t, callContext) and + localFlowExit(node2, state1) and + state1 = state2 or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() + additionalLocalFlowStepNodeCand2(node1, state1, node2, state2) and + state1 != state2 and + preservesValue = false and + t = node2.getDataFlowType() and + callContext.relevantFor(node1.getEnclosingCallable()) and + not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | + isUnreachableInCallCached(node1.asNode(), call) or + isUnreachableInCallCached(node2.asNode(), call) ) + } + } + + private import LocalFlowBigStep + + private module Stage3Param implements MkStage::StageParam { + private module PrevStage = Stage2; + + class Ap = ApproxAccessPathFront; + + class ApNil = ApproxAccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } + + class ApHeadContent = ContentApprox; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + predicate projectToHeadContent = getContentApprox/1; + + class ApOption = ApproxAccessPathFrontOption; + + ApOption apNone() { result = TApproxAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } + + import BooleanCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApproxAccessPathFrontNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + exists(lcc) + } + + predicate flowOutOfCall = flowOutOfCallNodeCand2/5; + + predicate flowIntoCall = flowIntoCallNodeCand2/4; + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getAHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage3 implements StageSig { + import MkStage::Stage + } + + private module Stage4Param implements MkStage::StageParam { + private module PrevStage = Stage3; + + class Ap = AccessPathFront; + + class ApNil = AccessPathFrontNil; + + PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathFrontOption; + + ApOption apNone() { result = TAccessPathFrontNone() } + + ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + + import BooleanCallContext + + pragma[nomagic] + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), _) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) and + exists(lcc) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + private predicate clearSet(NodeEx node, ContentSet c) { + PrevStage::revFlow(node) and + clearsContentCached(node.asNode(), c) + } + + pragma[nomagic] + private predicate clearContent(NodeEx node, Content c) { + exists(ContentSet cs | + PrevStage::readStepCand(_, pragma[only_bind_into](c), _) and + c = cs.getAReadContent() and + clearSet(node, cs) + ) + } + + pragma[nomagic] + private predicate clear(NodeEx node, Ap ap) { clearContent(node, ap.getHead().getContent()) } + + pragma[nomagic] + private predicate expectsContentCand(NodeEx node, Ap ap) { + exists(Content c | + PrevStage::revFlow(node) and + PrevStage::readStepCand(_, c, _) and + expectsContentEx(node, c) and + c = ap.getHead().getContent() + ) + } + + pragma[nomagic] + private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { + exists(state) and + not clear(node, ap) and + (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and + ( + notExpectsContent(node) + or + expectsContentCand(node, ap) + ) + } + + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { + // We need to typecheck stores here, since reverse flow through a getter + // might have a different type here compared to inside the getter. + compatibleTypes(ap.getType(), contentType) + } + } + + private module Stage4 implements StageSig { + import MkStage::Stage + } + + /** + * Holds if `argApf` is recorded as the summary context for flow reaching `node` + * and remains relevant for the following pruning stage. + */ + private predicate flowCandSummaryCtx(NodeEx node, FlowState state, AccessPathFront argApf) { + exists(AccessPathFront apf | + Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf) and + Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf) ) } /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. + * Holds if a length 2 access path approximation with the head `tc` is expected + * to be expensive. */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() + private predicate expensiveLen2unfolding(TypedContent tc) { + exists(int tails, int nodes, int apLimit, int tupleLimit | + tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf)) and + nodes = + strictcount(NodeEx n, FlowState state | + Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + or + flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc)) + ) and + accessPathApproxCostLimits(apLimit, tupleLimit) and + apLimit < tails and + tupleLimit < (tails - 1) * nodes and + not tc.forceHighPrecision() ) } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + private newtype TAccessPathApprox = + TNil(DataFlowType t) or + TConsNil(TypedContent tc, DataFlowType t) { + Stage4::consCand(tc, TFrontNil(t)) and + not expensiveLen2unfolding(tc) + } or + TConsCons(TypedContent tc1, TypedContent tc2, int len) { + Stage4::consCand(tc1, TFrontHead(tc2)) and + len in [2 .. accessPathLimit()] and + not expensiveLen2unfolding(tc1) + } or + TCons1(TypedContent tc, int len) { + len in [1 .. accessPathLimit()] and + expensiveLen2unfolding(tc) + } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) + /** + * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only + * the first two elements of the list and its length are tracked. If data flows + * from a source to a given node with a given `AccessPathApprox`, this indicates + * the sequence of dereference operations needed to get from the value in the node + * to the tracked object. The final type indicates the type of the tracked object. + */ + abstract private class AccessPathApprox extends TAccessPathApprox { + abstract string toString(); + + abstract TypedContent getHead(); + + abstract int len(); + + abstract DataFlowType getType(); + + abstract AccessPathFront getFront(); + + /** Gets the access path obtained by popping `head` from this path, if any. */ + abstract AccessPathApprox pop(TypedContent head); } - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} + private class AccessPathApproxNil extends AccessPathApprox, TNil { + private DataFlowType t; -private module Stage3 implements StageSig { - import MkStage::Stage -} + AccessPathApproxNil() { this = TNil(t) } -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; + override string toString() { result = concat(": " + ppReprType(t)) } - class Ap = AccessPathFront; + override TypedContent getHead() { none() } - class ApNil = AccessPathFrontNil; + override int len() { result = 0 } - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } + override DataFlowType getType() { result = t } - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) + override AccessPathFront getFront() { result = TFrontNil(t) } + + override AccessPathApprox pop(TypedContent head) { none() } } - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } + abstract private class AccessPathApproxCons extends AccessPathApprox { } - class ApHeadContent = Content; + private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { + private TypedContent tc; + private DataFlowType t; - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + AccessPathApproxConsNil() { this = TConsNil(tc, t) } - ApHeadContent projectToHeadContent(Content c) { result = c } + override string toString() { + // The `concat` becomes "" if `ppReprType` has no result. + result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) + } - class ApOption = AccessPathFrontOption; + override TypedContent getHead() { result = tc } - ApOption apNone() { result = TAccessPathFrontNone() } + override int len() { result = 1 } - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } + override DataFlowType getType() { result = tc.getContainerType() } - import BooleanCallContext + override AccessPathFront getFront() { result = TFrontHead(tc) } - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) + override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } } - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { + private TypedContent tc1; + private TypedContent tc2; + private int len; - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } + AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } + override string toString() { + if len = 2 + then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" + else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" + } - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } + override TypedContent getHead() { result = tc1 } - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } + override int len() { result = len } - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } + override DataFlowType getType() { result = tc1.getContainerType() } - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } + override AccessPathFront getFront() { result = TFrontHead(tc1) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | + override AccessPathApprox pop(TypedContent head) { + head = tc1 and + ( result = TConsCons(tc2, _, len - 1) or len = 2 and @@ -2763,1561 +2489,581 @@ private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { or result = TCons1(tc2, len - 1) ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) + } + } + + private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { + private TypedContent tc; + private int len; + + AccessPathApproxCons1() { this = TCons1(tc, len) } + + override string toString() { + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + } + + override TypedContent getHead() { result = tc } + + override int len() { result = len } + + override DataFlowType getType() { result = tc.getContainerType() } + + override AccessPathFront getFront() { result = TFrontHead(tc) } + + override AccessPathApprox pop(TypedContent head) { + head = tc and + ( + exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2)) | + result = TConsCons(tc2, _, len - 1) + or + len = 2 and + result = TConsNil(tc2, _) + or + result = TCons1(tc2, len - 1) + ) + or + exists(DataFlowType t | + len = 1 and + Stage4::consCand(tc, TFrontNil(t)) and + result = TNil(t) + ) ) - ) + } } -} -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } + /** Gets the access path obtained by popping `tc` from `ap`, if any. */ + private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } + /** Gets the access path obtained by pushing `tc` onto `ap`. */ + private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) + private newtype TAccessPathApproxOption = + TAccessPathApproxNone() or + TAccessPathApproxSome(AccessPathApprox apa) -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + private class AccessPathApproxOption extends TAccessPathApproxOption { + string toString() { + this = TAccessPathApproxNone() and result = "" + or + this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) + } } -} -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; + private module Stage5Param implements MkStage::StageParam { + private module PrevStage = Stage4; - class Ap = AccessPathApprox; + class Ap = AccessPathApprox; - class ApNil = AccessPathApproxNil; + class ApNil = AccessPathApproxNil; + + pragma[nomagic] + PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } + + ApNil getApNil(NodeEx node) { + PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) + } + + bindingset[tc, tail] + Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } + + class ApHeadContent = Content; + + pragma[noinline] + ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } + + ApHeadContent projectToHeadContent(Content c) { result = c } + + class ApOption = AccessPathApproxOption; + + ApOption apNone() { result = TAccessPathApproxNone() } + + ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } + + import Level1CallContext + import LocalCallContext + + predicate localStep( + NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, + ApNil ap, LocalCc lcc + ) { + localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), lcc) and + PrevStage::revFlow(node1, pragma[only_bind_into](state1), _) and + PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _) + } + + pragma[nomagic] + predicate flowOutOfCall( + DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + pragma[nomagic] + predicate flowIntoCall( + DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow + ) { + exists(FlowState state | + flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow) and + PrevStage::revFlow(node2, pragma[only_bind_into](state), _) and + PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _) + ) + } + + bindingset[node, state, ap] + predicate filter(NodeEx node, FlowState state, Ap ap) { any() } + + // Type checking is not necessary here as it has already been done in stage 3. + bindingset[ap, contentType] + predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } + } + + private module Stage5 = MkStage::Stage; pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc + private predicate nodeMayUseSummary0( + NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + exists(AccessPathApprox apa0 | + Stage5::parameterMayFlowThrough(p, _) and + Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0) and + Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), + TAccessPathApproxSome(apa), apa0) ) } pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) + private predicate nodeMayUseSummary(NodeEx n, FlowState state, AccessPathApprox apa) { + exists(ParamNodeEx p | + Stage5::parameterMayFlowThrough(p, apa) and + nodeMayUseSummary0(n, p, state, apa) ) } - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } + private newtype TSummaryCtx = + TSummaryCtxNone() or + TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { + Stage5::parameterMayFlowThrough(p, ap.getApprox()) and + Stage5::revFlow(p, state, _) + } - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} + /** + * A context for generating flow summaries. This represents flow entry through + * a specific parameter with an access path of a specific shape. + * + * Summaries are only created for parameters that may flow through. + */ + abstract private class SummaryCtx extends TSummaryCtx { + abstract string toString(); + } -private module Stage5 = MkStage::Stage; + /** A summary context from which no flow summary can be generated. */ + private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { + override string toString() { result = "" } + } -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} + /** A summary context from which a flow summary can be generated. */ + private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { + private ParamNodeEx p; + private FlowState s; + private AccessPath ap; -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} + SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} + ParameterPosition getParameterPos() { p.isParameterOf(_, result) } -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) + ParamNodeEx getParamNode() { result = p } + + override string toString() { result = p + ": " + ap } + + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + } + + /** + * Gets the number of length 2 access path approximations that correspond to `apa`. + */ + private int count1to2unfold(AccessPathApproxCons1 apa) { + exists(TypedContent tc, int len | + tc = apa.getHead() and + len = apa.len() and + result = + strictcount(AccessPathFront apf | + Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1)) + ) ) } -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and + private int countNodesUsingAccessPath(AccessPathApprox apa) { result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) + strictcount(NodeEx n, FlowState state | + Stage5::revFlow(n, state, apa) or nodeMayUseSummary(n, state, apa) ) - ) -} + } -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else + /** + * Holds if a length 2 access path approximation matching `apa` is expected + * to be expensive. + */ + private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa) { exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and + aps = count1to2unfold(apa) and + nodes = countNodesUsingAccessPath(apa) and accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() + apLimit < aps and + tupleLimit < (aps - 1) * nodes ) } -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() + private AccessPathApprox getATail(AccessPathApprox apa) { + exists(TypedContent head | + apa.pop(head) = result and + Stage5::consCand(head, result) ) } -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" + /** + * Holds with `unfold = false` if a precise head-tail representation of `apa` is + * expected to be expensive. Holds with `unfold = true` otherwise. + */ + private predicate evalUnfold(AccessPathApprox apa, boolean unfold) { + if apa.getHead().forceHighPrecision() + then unfold = true else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 + exists(int aps, int nodes, int apLimit, int tupleLimit | + aps = countPotentialAps(apa) and + nodes = countNodesUsingAccessPath(apa) and + accessPathCostLimits(apLimit, tupleLimit) and + if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true + ) } - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) + /** + * Gets the number of `AccessPath`s that correspond to `apa`. + */ + pragma[assume_small_delta] + private int countAps(AccessPathApprox apa) { + evalUnfold(apa, false) and + result = 1 and + (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa)) or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" + evalUnfold(apa, false) and + result = count1to2unfold(apa) and + not expensiveLen1to2unfolding(apa) or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) + evalUnfold(apa, true) and + result = countPotentialAps(apa) } - private string ppCtx() { - this instanceof PathNodeSink and result = "" + /** + * Gets the number of `AccessPath`s that would correspond to `apa` assuming + * that it is expanded to a precise head-tail representation. + */ + language[monotonicAggregates] + pragma[assume_small_delta] + private int countPotentialAps(AccessPathApprox apa) { + apa instanceof AccessPathApproxNil and result = 1 or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + result = strictsum(AccessPathApprox tail | tail = getATail(apa) | countAps(tail)) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) + private newtype TAccessPath = + TAccessPathNil(DataFlowType t) or + TAccessPathCons(TypedContent head, AccessPath tail) { + exists(AccessPathApproxCons apa | + not evalUnfold(apa, false) and + head = apa.getHead() and + tail.getApprox() = getATail(apa) + ) } or - TCallableSrc() or - TCallableSink() + TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + not expensiveLen1to2unfolding(apa) and + apa.len() = len and + head1 = apa.getHead() and + head2 = getATail(apa).getHead() + ) + } or + TAccessPathCons1(TypedContent head, int len) { + exists(AccessPathApproxCons apa | + evalUnfold(apa, false) and + expensiveLen1to2unfolding(apa) and + apa.len() = len and + head = apa.getHead() + ) + } - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + private newtype TPathNode = + pragma[assume_small_delta] + TPathNodeMid(NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap) { + // A PathNode is introduced by a source ... + Stage5::revFlow(node, state) and + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + or + // ... or a step from an existing PathNode to another node. + pathStep(_, node, state, cc, sc, ap) and + Stage5::revFlow(node, state, ap.getApprox()) + } or + TPathNodeSink(NodeEx node, FlowState state) { + exists(PathNodeMid sink | + sink.isAtSink() and + node = sink.getNodeEx() and + state = sink.getState() + ) + } or + TPathNodeSourceGroup(string sourceGroup) { + exists(PathNodeImpl source | sourceGroup = source.getSourceGroup()) + } or + TPathNodeSinkGroup(string sinkGroup) { + exists(PathNodeSink sink | sinkGroup = sink.getSinkGroup()) + } /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the + * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a + * source to a given node with a given `AccessPath`, this indicates the sequence + * of dereference operations needed to get from the value in the node to the * tracked object. The final type indicates the type of the tracked object. */ - private class PartialAccessPath extends TPartialAccessPath { + private class AccessPath extends TAccessPath { + /** Gets the head of this access path, if any. */ + abstract TypedContent getHead(); + + /** Gets the tail of this access path, if any. */ + abstract AccessPath getTail(); + + /** Gets the front of this access path. */ + abstract AccessPathFront getFront(); + + /** Gets the approximation of this access path. */ + abstract AccessPathApprox getApprox(); + + /** Gets the length of this access path. */ + abstract int length(); + + /** Gets a textual representation of this access path. */ abstract string toString(); - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) + /** Gets the access path obtained by popping `tc` from this access path, if any. */ + final AccessPath pop(TypedContent tc) { + result = this.getTail() and + tc = this.getHead() } - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } + /** Gets the access path obtained by pushing `tc` onto this access path. */ + final AccessPath push(TypedContent tc) { this = result.pop(tc) } } - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } + private class AccessPathNil extends AccessPath, TAccessPathNil { + private DataFlowType t; + + AccessPathNil() { this = TAccessPathNil(t) } + + DataFlowType getType() { result = t } + + override TypedContent getHead() { none() } + + override AccessPath getTail() { none() } + + override AccessPathFrontNil getFront() { result = TFrontNil(t) } + + override AccessPathApproxNil getApprox() { result = TNil(t) } + + override int length() { result = 0 } + + override string toString() { result = concat(": " + ppReprType(t)) } } - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + private class AccessPathCons extends AccessPath, TAccessPathCons { + private TypedContent head; + private AccessPath tail; + + AccessPathCons() { this = TAccessPathCons(head, tail) } + + override TypedContent getHead() { result = head } + + override AccessPath getTail() { result = tail } + + override AccessPathFrontHead getFront() { result = TFrontHead(head) } + + pragma[assume_small_delta] + override AccessPathApproxCons getApprox() { + result = TConsNil(head, tail.(AccessPathNil).getType()) + or + result = TConsCons(head, tail.getHead(), this.length()) + or + result = TCons1(head, this.length()) + } + + pragma[assume_small_delta] + override int length() { result = 1 + tail.length() } + + private string toStringImpl(boolean needsSuffix) { + exists(DataFlowType t | + tail = TAccessPathNil(t) and + needsSuffix = false and + result = head.toString() + "]" + concat(" : " + ppReprType(t)) + ) + or + result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) + or + exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | + result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true + or + result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false + ) + or + exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | + result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true + or + result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false ) } - } - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) + result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" + or + result = "[" + this.toStringImpl(false) } } - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) + private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { + private TypedContent head1; + private TypedContent head2; + private int len; + + AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } + + override TypedContent getHead() { result = head1 } + + override AccessPath getTail() { + Stage5::consCand(head1, result.getApprox()) and + result.getHead() = head2 and + result.length() = len - 1 + } + + override AccessPathFrontHead getFront() { result = TFrontHead(head1) } + + override AccessPathApproxCons getApprox() { + result = TConsCons(head1, head2, len) or + result = TCons1(head1, len) + } + + override int length() { result = len } + + override string toString() { + if len = 2 + then result = "[" + head1.toString() + ", " + head2.toString() + "]" + else + result = + "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" + } } - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) + private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { + private TypedContent head; + private int len; - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } + AccessPathCons1() { this = TAccessPathCons1(head, len) } - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) + override TypedContent getHead() { result = head } - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) + override AccessPath getTail() { + Stage5::consCand(head, result.getApprox()) and result.length() = len - 1 + } - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + override AccessPathFrontHead getFront() { result = TFrontHead(head) } - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) + override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and + override int length() { result = len } + + override string toString() { + if len = 1 + then result = "[" + head.toString() + "]" + else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" + } + } + + abstract private class PathNodeImpl extends TPathNode { + /** Gets the `FlowState` of this node. */ + abstract FlowState getState(); + + /** Holds if this node is a source. */ + abstract predicate isSource(); + + abstract PathNodeImpl getASuccessorImpl(); + + private PathNodeImpl getASuccessorIfHidden() { + this.isHidden() and + result = this.getASuccessorImpl() + } + + pragma[nomagic] + private PathNodeImpl getANonHiddenSuccessor0() { + result = this.getASuccessorIfHidden*() and + not result.isHidden() + } + + final PathNodeImpl getANonHiddenSuccessor() { + result = this.getASuccessorImpl().getANonHiddenSuccessor0() and + not this.isHidden() + } + + abstract NodeEx getNodeEx(); + + predicate isHidden() { + not Config::includeHiddenNodes() and ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() + hiddenNode(this.getNodeEx().asNode()) and + not this.isSource() and + not this instanceof PathNodeSink + or + this.getNodeEx() instanceof TNodeImplicitRead + ) } - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } + string getSourceGroup() { + this.isSource() and + Config::sourceGrouping(this.getNodeEx().asNode(), result) + } + + predicate isFlowSource() { + this.isSource() and not exists(this.getSourceGroup()) + or + this instanceof PathNodeSourceGroup + } + + predicate isFlowSink() { + this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or + this instanceof PathNodeSinkGroup + } + + private string ppAp() { + this instanceof PathNodeSink and result = "" + or + exists(string s | s = this.(PathNodeMid).getAp().toString() | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + this instanceof PathNodeSink and result = "" + or + result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + } - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { /** Gets a textual representation of this element. */ string toString() { result = this.getNodeEx().toString() + this.ppAp() } @@ -4341,305 +3087,335 @@ private module FlowExploration { ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } + } + + /** Holds if `n` can reach a sink. */ + private predicate directReach(PathNodeImpl n) { + n instanceof PathNodeSink or + n instanceof PathNodeSinkGroup or + directReach(n.getANonHiddenSuccessor()) + } + + /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ + private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } + + /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ + private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { + n1.getANonHiddenSuccessor() = n2 and directReach(n2) + } + + private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + + /** + * A `Node` augmented with a call context (except for sinks) and an access path. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ + class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } + final Node getNode() { super.getNodeEx().projectToNode() = result } - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group) } - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group) } } /** * Provides the query predicates needed to include a graph in a path-problem query. */ - module PartialPathGraph { + module PathGraph implements PathGraphSig { /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } + + /** Holds if `n` is a node in the graph of data flow path explanations. */ + query predicate nodes(PathNode n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { + Subpaths::subpaths(arg, par, ret, out) + } } - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + /** + * An intermediate flow graph node. This is a tuple consisting of a `Node`, + * a `FlowState`, a `CallContext`, a `SummaryCtx`, and an `AccessPath`. + */ + private class PathNodeMid extends PathNodeImpl, TPathNodeMid { NodeEx node; FlowState state; CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; + SummaryCtx sc; + AccessPath ap; - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } + PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } CallContext getCallContext() { result = cc } - TSummaryCtx1 getSummaryCtx1() { result = sc1 } + SummaryCtx getSummaryCtx() { result = sc } - TSummaryCtx2 getSummaryCtx2() { result = sc2 } + AccessPath getAp() { result = ap } - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) + private PathNodeMid getSuccMid() { + pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx(), result.getAp()) } - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil + override PathNodeImpl getASuccessorImpl() { + // an intermediate step to another intermediate node + result = this.getSuccMid() + or + // a final step to a sink + result = this.getSuccMid().projectToSink() + } + + override predicate isSource() { + sourceNode(node, state) and + sourceCallCtx(cc) and + sc instanceof SummaryCtxNone and + ap = TAccessPathNil(node.getDataFlowType()) + } + + predicate isAtSink() { + sinkNode(node, state) and + ap instanceof AccessPathNil and + if hasSinkCallCtx() + then + // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` + // is exactly what we need to check. This also implies + // `sc instanceof SummaryCtxNone`. + // For `FeatureEqualSourceSinkCallContext` the initial call context was + // set to `CallContextSomeCall` and jumps are disallowed, so + // `cc instanceof CallContextNoCall` never holds. On the other hand, + // in this case there's never any need to enter a call except to identify + // a summary, so the condition in `pathIntoCallable` enforces this, which + // means that `sc instanceof SummaryCtxNone` holds if and only if we are + // in the call context of the source. + sc instanceof SummaryCtxNone or + cc instanceof CallContextNoCall + else any() + } + + PathNodeSink projectToSink() { + this.isAtSink() and + result.getNodeEx() = node and + result.getState() = state } } - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + /** + * A flow graph node corresponding to a sink. This is disjoint from the + * intermediate nodes in order to uniquely correspond to a given sink by + * excluding the `CallContext`. + */ + private class PathNodeSink extends PathNodeImpl, TPathNodeSink { NodeEx node; FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } + PathNodeSink() { this = TPathNodeSink(node, state) } - NodeEx getNodeEx() { result = node } + override NodeEx getNodeEx() { result = node } override FlowState getState() { result = state } - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + override PathNodeImpl getASuccessorImpl() { result = TPathNodeSinkGroup(this.getSinkGroup()) } - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + override predicate isSource() { sourceNode(node, state) } - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + string getSinkGroup() { Config::sinkGrouping(node.asNode(), result) } + } - RevPartialAccessPath getAp() { result = ap } + private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { + string sourceGroup; - override Configuration getConfiguration() { result = config } + PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup) } - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } + override NodeEx getNodeEx() { none() } - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { result.getSourceGroup() = sourceGroup } + + override predicate isSource() { none() } + + override string toString() { result = sourceGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 } } - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { + string sinkGroup; + + PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup) } + + override NodeEx getNodeEx() { none() } + + override FlowState getState() { none() } + + override PathNodeImpl getASuccessorImpl() { none() } + + override predicate isSource() { none() } + + override string toString() { result = sinkGroup } + + override predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 + } + } + + private predicate pathNode( + PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, + LocalCallContext localCC ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and + midnode = mid.getNodeEx() and state = mid.getState() and cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() + sc = mid.getSummaryCtx() and + localCC = + getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), + midnode.getEnclosingCallable()) and + ap = mid.getAp() } - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 + /** + * Holds if data may flow from `mid` to `node`. The last step in or out of + * a callable is recorded by `cc`. + */ + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathStep( + PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) + exists(NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap, localCC) and + localFlowBigStep(midnode, state0, node, state, true, _, localCC) ) + or + exists(AccessPath ap0, NodeEx midnode, FlowState state0, LocalCallContext localCC | + pathNode(mid, midnode, state0, cc, sc, ap0, localCC) and + localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), localCC) and + ap0 instanceof AccessPathNil + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc instanceof SummaryCtxNone and + mid.getAp() instanceof AccessPathNil and + ap = TAccessPathNil(node.getDataFlowType()) + or + exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and + sc = mid.getSummaryCtx() + or + pathIntoCallable(mid, node, state, _, cc, sc, _) and ap = mid.getAp() + or + pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone + or + pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() } pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config + private predicate pathReadStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) + ap0 = mid.getAp() and + tc = ap0.getHead() and + Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node) and + state = mid.getState() and + cc = mid.getCallContext() } pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config + private predicate pathStoreStep( + PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) + ap0 = mid.getAp() and + Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _) and + state = mid.getState() and + cc = mid.getCallContext() } - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable0( + PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa ) { pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and state = mid.getState() and innercc = mid.getCallContext() and innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() + apa = mid.getAp().getApprox() } pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config + private predicate pathOutOfCallable1( + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPathApprox apa ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and + pathOutOfCallable0(mid, pos, state, innercc, apa) and c = pos.getCallable() and kind = pos.getKind() and resolveReturn(innercc, c, call) @@ -4648,53 +3424,86 @@ private module FlowExploration { ) } - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) + pragma[noinline] + private NodeEx getAnOutNodeFlow(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa) { + result.asNode() = kind.getAnOutNode(call) and + Stage5::revFlow(result, _, apa) + } + + /** + * Holds if data may flow from `mid` to `out`. The last step of this path + * is a return from a callable and is recorded by `cc`, if needed. + */ + pragma[noinline] + private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa | + pathOutOfCallable1(mid, call, kind, state, cc, apa) and + out = getAnOutNodeFlow(kind, call, apa) ) } + /** + * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. + */ pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate pathIntoArg( + PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, + AccessPath ap, AccessPathApprox apa ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and + exists(ArgNodeEx arg, ArgumentPosition apos | + pathNode(mid, arg, state, cc, _, ap, _) and + arg.asNode().(ArgNode).argumentOf(call, apos) and + apa = ap.getApprox() and parameterMatch(ppos, apos) ) } pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config + private predicate parameterCand( + DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) + exists(ParamNodeEx p | + Stage5::revFlow(p, _, apa) and + p.isParameterOf(callable, pos) + ) } - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config + pragma[nomagic] + private predicate pathIntoCallable0( + PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, AccessPath ap ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and + exists(AccessPathApprox apa | + pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, + pragma[only_bind_into](apa)) and + callable = resolveCall(call, outercc) and + parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa)) + ) + } + + /** + * Holds if data may flow from `mid` to `p` through `call`. The contexts + * before and after entering the callable are `outercc` and `innercc`, + * respectively. + */ + pragma[nomagic] + private predicate pathIntoCallable( + PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, + SummaryCtx sc, DataFlowCall call + ) { + exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | + pathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) + ( + sc = TSummaryCtxSome(p, state, ap) + or + not exists(TSummaryCtxSome(p, state, ap)) and + sc = TSummaryCtxNone() and + // When the call contexts of source and sink needs to match then there's + // never any reason to enter a callable except to find a summary. See also + // the comment in `PathNodeMid::isAtSink`. + not Config::getAFeature() instanceof FeatureEqualSourceSinkCallContext + ) | if recordDataFlowCallSite(call, callable) then innercc = TSpecificCall(call) @@ -4702,252 +3511,1108 @@ private module FlowExploration { ) } + /** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config + private predicate paramFlowsThrough( + ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, + AccessPathApprox apa ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and + exists(RetNodeEx ret | + pathNode(_, ret, state, cc, sc, ap, _) and kind = ret.getKind() and + apa = ap.getApprox() and + parameterFlowThroughAllowed(sc.getParamNode(), kind) + ) + } + + pragma[assume_small_delta] + pragma[nomagic] + private predicate pathThroughCallable0( + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, + AccessPath ap, AccessPathApprox apa + ) { + exists(CallContext innercc, SummaryCtx sc | + pathIntoCallable(mid, _, _, cc, innercc, sc, call) and + paramFlowsThrough(kind, state, innercc, sc, ap, apa) + ) + } + + /** + * Holds if data may flow from `mid` through a callable to the node `out`. + * The context `cc` is restored to its value prior to entering the callable. + */ + pragma[noinline] + private predicate pathThroughCallable( + PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa | + pathThroughCallable0(call, mid, kind, state, cc, ap, apa) and + out = getAnOutNodeFlow(kind, call, apa) + ) + } + + private module Subpaths { + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths01( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and + pathIntoCallable(arg, par, _, _, innercc, sc, _) and + paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, + pragma[only_bind_into](apout), _) and + not arg.isHidden() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by + * `kind`, `sc`, `sout`, `apout`, and `innercc`. + */ + pragma[nomagic] + private predicate subpaths02( + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + NodeEx out, FlowState sout, AccessPath apout + ) { + subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and + out.asNode() = kind.getAnOutNode(_) + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple. + */ + pragma[nomagic] + private predicate subpaths03( + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, + AccessPath apout + ) { + exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | + subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and + pathNode(ret, retnode, sout, innercc, sc, apout, _) and + kind = retnode.getKind() + ) + } + + private PathNodeImpl localStepToHidden(PathNodeImpl n) { + n.getASuccessorImpl() = result and + result.isHidden() and + exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | + localFlowBigStep(n1, _, n2, _, _, _, _) or + storeEx(n1, _, n2, _) or + readSetEx(n1, _, n2) + ) + } + + pragma[nomagic] + private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { + succ = pred.getANonHiddenSuccessor() and + succNode = succ.getNodeEx() + } + + /** + * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through + * a subpath between `par` and `ret` with the connecting edges `arg -> par` and + * `ret -> out` is summarized as the edge `arg -> out`. + */ + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { + exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | + pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and + subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and + hasSuccessor(pragma[only_bind_into](arg), par, p) and + not ret.isHidden() and + pathNode(out0, o, sout, _, _, apout, _) + | + out = out0 or out = out0.projectToSink() + ) + } + + /** + * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. + */ + predicate retReach(PathNodeImpl n) { + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + or + exists(PathNodeImpl mid | + retReach(mid) and + n.getANonHiddenSuccessor() = mid and + not subpaths(_, mid, _, _) + ) + } + } + + /** + * Holds if data can flow from `source` to `sink`. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { + exists(PathNodeImpl flowsource, PathNodeImpl flowsink | + source = flowsource and sink = flowsink + | + flowsource.isFlowSource() and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.isFlowSink() + ) + } + + private predicate flowsTo(PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink) { + flowsource.isSource() and + flowsource.getNodeEx().asNode() = source and + (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and + flowsink.getNodeEx().asNode() = sink + } + + /** + * Holds if data can flow from `source` to `sink`. + */ + predicate hasFlow(Node source, Node sink) { flowsTo(_, _, source, sink) } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowTo(Node sink) { sink = any(PathNodeSink n).getNodeEx().asNode() } + + /** + * Holds if data can flow from some source to `sink`. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) } + + private predicate finalStats( + boolean fwd, int nodes, int fields, int conscand, int states, int tuples + ) { + fwd = true and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and + fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and + tuples = count(PathNodeImpl pn) + or + fwd = false and + nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and + fields = + count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and + conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and + states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and + tuples = count(PathNode pn) + } + + /** + * INTERNAL: Only for debugging. + * + * Calculates per-stage metrics for data flow. + */ + predicate stageStats( + int n, string stage, int nodes, int fields, int conscand, int states, int tuples + ) { + stage = "1 Fwd" and + n = 10 and + Stage1::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "1 Rev" and + n = 15 and + Stage1::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "2 Fwd" and + n = 20 and + Stage2::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "2 Rev" and + n = 25 and + Stage2::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "3 Fwd" and + n = 30 and + Stage3::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "3 Rev" and + n = 35 and + Stage3::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "4 Fwd" and + n = 40 and + Stage4::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "4 Rev" and + n = 45 and + Stage4::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "5 Fwd" and + n = 50 and + Stage5::stats(true, nodes, fields, conscand, states, tuples) + or + stage = "5 Rev" and + n = 55 and + Stage5::stats(false, nodes, fields, conscand, states, tuples) + or + stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) + or + stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) + } + + module FlowExploration { + private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2) { + exists(NodeEx node1, NodeEx node2 | + jumpStepEx(node1, node2) + or + additionalJumpStep(node1, node2) + or + additionalJumpStateStep(node1, _, node2, _) + or + // flow into callable + viableParamArgEx(_, node2, node1) + or + // flow out of a callable + viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) + | + c1 = node1.getEnclosingCallable() and + c2 = node2.getEnclosingCallable() and + c1 != c2 + ) + } + + private predicate interestingCallableSrc(DataFlowCallable c) { + exists(Node n | Config::isSource(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSrc(mid) and callableStep(mid, c)) + } + + private predicate interestingCallableSink(DataFlowCallable c) { + exists(Node n | Config::isSink(n, _) and c = getNodeEnclosingCallable(n)) + or + exists(DataFlowCallable mid | interestingCallableSink(mid) and callableStep(c, mid)) + } + + private newtype TCallableExt = + TCallable(DataFlowCallable c) { + interestingCallableSrc(c) or + interestingCallableSink(c) + } or + TCallableSrc() or + TCallableSink() + + private predicate callableExtSrc(TCallableSrc src) { any() } + + private predicate callableExtSink(TCallableSink sink) { any() } + + private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { + exists(DataFlowCallable c1, DataFlowCallable c2 | + callableStep(c1, c2) and + ce1 = TCallable(c1) and + ce2 = TCallable(c2) + ) + or + exists(Node n | + ce1 = TCallableSrc() and + Config::isSource(n, _) and + ce2 = TCallable(getNodeEnclosingCallable(n)) + ) + or + exists(Node n | + ce2 = TCallableSink() and + Config::isSink(n, _) and + ce1 = TCallable(getNodeEnclosingCallable(n)) + ) + } + + private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { + callableExtStepFwd(ce2, ce1) + } + + private int distSrcExt(TCallableExt c) = + shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) + + private int distSinkExt(TCallableExt c) = + shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) + + private int distSrc(DataFlowCallable c) { result = distSrcExt(TCallable(c)) - 1 } + + private int distSink(DataFlowCallable c) { result = distSinkExt(TCallable(c)) - 1 } + + private newtype TPartialAccessPath = + TPartialNil(DataFlowType t) or + TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first + * element of the list and its length are tracked. If data flows from a source to + * a given node with a given `AccessPath`, this indicates the sequence of + * dereference operations needed to get from the value in the node to the + * tracked object. The final type indicates the type of the tracked object. + */ + private class PartialAccessPath extends TPartialAccessPath { + abstract string toString(); + + TypedContent getHead() { this = TPartialCons(result, _) } + + int len() { + this = TPartialNil(_) and result = 0 + or + this = TPartialCons(_, result) + } + + DataFlowType getType() { + this = TPartialNil(result) + or + exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) + } + } + + private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { + override string toString() { + exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) + } + } + + private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { + override string toString() { + exists(TypedContent tc, int len | this = TPartialCons(tc, len) | + if len = 1 + then result = "[" + tc.toString() + "]" + else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private newtype TRevPartialAccessPath = + TRevPartialNil() or + TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } + + /** + * Conceptually a list of `Content`s, but only the first + * element of the list and its length are tracked. + */ + private class RevPartialAccessPath extends TRevPartialAccessPath { + abstract string toString(); + + Content getHead() { this = TRevPartialCons(result, _) } + + int len() { + this = TRevPartialNil() and result = 0 + or + this = TRevPartialCons(_, result) + } + } + + private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { + override string toString() { result = "" } + } + + private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { + override string toString() { + exists(Content c, int len | this = TRevPartialCons(c, len) | + if len = 1 + then result = "[" + c.toString() + "]" + else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" + ) + } + } + + private predicate relevantState(FlowState state) { + sourceNode(_, state) or + sinkNode(_, state) or + additionalLocalStateStep(_, state, _, _) or + additionalLocalStateStep(_, _, _, state) or + additionalJumpStateStep(_, state, _, _) or + additionalJumpStateStep(_, _, _, state) + } + + private newtype TSummaryCtx1 = + TSummaryCtx1None() or + TSummaryCtx1Param(ParamNodeEx p) + + private newtype TSummaryCtx2 = + TSummaryCtx2None() or + TSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TSummaryCtx3 = + TSummaryCtx3None() or + TSummaryCtx3Some(PartialAccessPath ap) + + private newtype TRevSummaryCtx1 = + TRevSummaryCtx1None() or + TRevSummaryCtx1Some(ReturnPosition pos) + + private newtype TRevSummaryCtx2 = + TRevSummaryCtx2None() or + TRevSummaryCtx2Some(FlowState s) { relevantState(s) } + + private newtype TRevSummaryCtx3 = + TRevSummaryCtx3None() or + TRevSummaryCtx3Some(RevPartialAccessPath ap) + + private newtype TPartialPathNode = + TPartialPathNodeFwd( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = TPartialNil(node.getDataFlowType()) and + exists(explorationLimit()) + or + partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap) and + distSrc(node.getEnclosingCallable()) <= explorationLimit() + } or + TPartialPathNodeRev( + NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, + RevPartialAccessPath ap + ) { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() and + exists(explorationLimit()) + or + revPartialPathStep(_, node, state, sc1, sc2, sc3, ap) and + not clearsContentEx(node, ap.getHead()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead()) + ) and + not fullBarrier(node) and + not stateBarrier(node, state) and + distSink(node.getEnclosingCallable()) <= explorationLimit() + } + + pragma[nomagic] + private predicate partialPathNodeMk0( + NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap) and + not fullBarrier(node) and + not stateBarrier(node, state) and + not clearsContentEx(node, ap.getHead().getContent()) and + ( + notExpectsContent(node) or + expectsContentEx(node, ap.getHead().getContent()) + ) and + if node.asNode() instanceof CastingNode + then compatibleTypes(node.getDataFlowType(), ap.getType()) + else any() + } + + /** + * A `Node` augmented with a call context, an access path, and a configuration. + */ + class PartialPathNode extends TPartialPathNode { + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { + result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() + } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { this.getNodeEx().projectToNode() = result } + + FlowState getState() { none() } + + private NodeEx getNodeEx() { + result = this.(PartialPathNodeFwd).getNodeEx() or + result = this.(PartialPathNodeRev).getNodeEx() + } + + /** Gets a successor of this node, if any. */ + PartialPathNode getASuccessor() { none() } + + /** + * Gets the approximate distance to the nearest source measured in number + * of interprocedural steps. + */ + int getSourceDistance() { result = distSrc(this.getNodeEx().getEnclosingCallable()) } + + /** + * Gets the approximate distance to the nearest sink measured in number + * of interprocedural steps. + */ + int getSinkDistance() { result = distSink(this.getNodeEx().getEnclosingCallable()) } + + private string ppAp() { + exists(string s | + s = this.(PartialPathNodeFwd).getAp().toString() or + s = this.(PartialPathNodeRev).getAp().toString() + | + if s = "" then result = "" else result = " " + s + ) + } + + private string ppCtx() { + result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" + } + + /** Holds if this is a source in a forward-flow path. */ + predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } + + /** Holds if this is a sink in a reverse-flow path. */ + predicate isRevSink() { this.(PartialPathNodeRev).isSink() } + } + + /** + * Provides the query predicates needed to include a graph in a path-problem query. + */ + module PartialPathGraph { + /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ + query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } + } + + private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { + NodeEx node; + FlowState state; + CallContext cc; + TSummaryCtx1 sc1; + TSummaryCtx2 sc2; + TSummaryCtx3 sc3; + PartialAccessPath ap; + + PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + CallContext getCallContext() { result = cc } + + TSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TSummaryCtx3 getSummaryCtx3() { result = sc3 } + + PartialAccessPath getAp() { result = ap } + + override PartialPathNodeFwd getASuccessor() { + partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), + result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp()) + } + + predicate isSource() { + sourceNode(node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap instanceof TPartialNil + } + } + + private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { + NodeEx node; + FlowState state; + TRevSummaryCtx1 sc1; + TRevSummaryCtx2 sc2; + TRevSummaryCtx3 sc3; + RevPartialAccessPath ap; + + PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap) } + + NodeEx getNodeEx() { result = node } + + override FlowState getState() { result = state } + + TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } + + TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } + + TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } + + RevPartialAccessPath getAp() { result = ap } + + override PartialPathNodeRev getASuccessor() { + revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), + this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp()) + } + + predicate isSink() { + sinkNode(node, state) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = TRevPartialNil() + } + } + + private predicate partialPathStep( + PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, + TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap + ) { + not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and + ( + localFlowStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + or + additionalLocalFlowStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + ) + or + jumpStepEx(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + ap = mid.getAp() + or + additionalJumpStep(mid.getNodeEx(), node) and + state = mid.getState() and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state) and + cc instanceof CallContextAny and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() and + mid.getAp() instanceof PartialAccessPathNil and + ap = TPartialNil(node.getDataFlowType()) + or + partialPathStoreStep(mid, _, _, node, ap) and state = mid.getState() and cc = mid.getCallContext() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and + sc3 = mid.getSummaryCtx3() + or + exists(PartialAccessPath ap0, TypedContent tc | + partialPathReadStep(mid, ap0, tc, node, cc) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsFwd(ap, tc, ap0) + ) + or + partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap) + or + partialPathOutOfCallable(mid, node, state, cc, ap) and + sc1 = TSummaryCtx1None() and + sc2 = TSummaryCtx2None() and + sc3 = TSummaryCtx3None() + or + partialPathThroughCallable(mid, node, state, cc, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } + + bindingset[result, i] + private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } + + pragma[inline] + private predicate partialPathStoreStep( + PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, + PartialAccessPath ap2 + ) { + exists(NodeEx midNode, DataFlowType contentType | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + storeEx(midNode, tc, node, contentType) and + ap2.getHead() = tc and + ap2.len() = unbindInt(ap1.len() + 1) and + compatibleTypes(ap1.getType(), contentType) + ) + } + + pragma[nomagic] + private predicate apConsFwd(PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2) { + partialPathStoreStep(_, ap1, tc, _, ap2) + } + + pragma[nomagic] + private predicate partialPathReadStep( + PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + read(midNode, tc.getContent(), node) and + ap.getHead() = tc and + cc = mid.getCallContext() + ) + } + + private predicate partialPathOutOfCallable0( + PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, + PartialAccessPath ap + ) { + pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and + state = mid.getState() and + innercc = mid.getCallContext() and + innercc instanceof CallContextNoCall and ap = mid.getAp() - ) - } + } - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } + pragma[nomagic] + private predicate partialPathOutOfCallable1( + PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | + partialPathOutOfCallable0(mid, pos, state, innercc, ap) and + c = pos.getCallable() and + kind = pos.getKind() and + resolveReturn(innercc, c, call) + | + if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() + ) + } - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } + private predicate partialPathOutOfCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(ReturnKindExt kind, DataFlowCall call | + partialPathOutOfCallable1(mid, call, kind, state, cc, ap) + | + out.asNode() = kind.getAnOutNode(call) + ) + } - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and + pragma[noinline] + private predicate partialPathIntoArg( + PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ArgNode arg, ArgumentPosition apos | + arg = mid.getNodeEx().asNode() and + state = mid.getState() and + cc = mid.getCallContext() and + arg.argumentOf(call, apos) and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate partialPathIntoCallable0( + PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, + CallContext outercc, DataFlowCall call, PartialAccessPath ap + ) { + partialPathIntoArg(mid, pos, state, outercc, call, ap) and + callable = resolveCall(call, outercc) + } + + private predicate partialPathIntoCallable( + PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, + CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, + DataFlowCall call, PartialAccessPath ap + ) { + exists(ParameterPosition pos, DataFlowCallable callable | + partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap) and + p.isParameterOf(callable, pos) and + sc1 = TSummaryCtx1Param(p) and + sc2 = TSummaryCtx2Some(state) and + sc3 = TSummaryCtx3Some(ap) + | + if recordDataFlowCallSite(call, callable) + then innercc = TSpecificCall(call) + else innercc = TSomeCall() + ) + } + + pragma[nomagic] + private predicate paramFlowsThroughInPartialPath( + ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, + TSummaryCtx3 sc3, PartialAccessPath ap + ) { + exists(PartialPathNodeFwd mid, RetNodeEx ret | + mid.getNodeEx() = ret and + kind = ret.getKind() and + state = mid.getState() and + cc = mid.getCallContext() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() + ) + } + + pragma[noinline] + private predicate partialPathThroughCallable0( + DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, + CallContext cc, PartialAccessPath ap + ) { + exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | + partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _) and + paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap) + ) + } + + private predicate partialPathThroughCallable( + PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap + ) { + exists(DataFlowCall call, ReturnKindExt kind | + partialPathThroughCallable0(call, mid, kind, state, cc, ap) and + out.asNode() = kind.getAnOutNode(call) + ) + } + + pragma[nomagic] + private predicate revPartialPathStep( + PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, + TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, RevPartialAccessPath ap + ) { + localFlowStepEx(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and + ap = mid.getAp() + or + additionalLocalFlowStep(node, mid.getNodeEx()) and state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + jumpStepEx(node, mid.getNodeEx()) and + state = mid.getState() and sc1 = TRevSummaryCtx1None() and sc2 = TRevSummaryCtx2None() and sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and + ap = mid.getAp() + or + additionalJumpStep(node, mid.getNodeEx()) and + state = mid.getState() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState()) and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + mid.getAp() instanceof RevPartialAccessPathNil and + ap = TRevPartialNil() + or + revPartialPathReadStep(mid, _, _, node, ap) and + state = mid.getState() and sc1 = mid.getSummaryCtx1() and sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } + sc3 = mid.getSummaryCtx3() + or + exists(RevPartialAccessPath ap0, Content c | + revPartialPathStoreStep(mid, ap0, c, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + apConsRev(ap, c, ap0) + ) + or + exists(ParamNodeEx p | + mid.getNodeEx() = p and + viableParamArgEx(_, p, node) and + state = mid.getState() and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + sc1 = TRevSummaryCtx1None() and + sc2 = TRevSummaryCtx2None() and + sc3 = TRevSummaryCtx3None() and + ap = mid.getAp() + ) + or + exists(ReturnPosition pos | + revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap) and + pos = getReturnPosition(node.asNode()) + ) + or + revPartialPathThroughCallable(mid, node, state, ap) and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() + } - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } + pragma[inline] + private predicate revPartialPathReadStep( + PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, + RevPartialAccessPath ap2 + ) { + exists(NodeEx midNode | + midNode = mid.getNodeEx() and + ap1 = mid.getAp() and + read(node, c, midNode) and + ap2.getHead() = c and + ap2.len() = unbindInt(ap1.len() + 1) + ) + } - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) + pragma[nomagic] + private predicate apConsRev(RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2) { + revPartialPathReadStep(_, ap1, c, _, ap2) + } + + pragma[nomagic] + private predicate revPartialPathStoreStep( + PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node + ) { + exists(NodeEx midNode, TypedContent tc | + midNode = mid.getNodeEx() and + ap = mid.getAp() and + storeEx(node, tc, midNode, _) and + ap.getHead() = c and + tc.getContent() = c + ) + } + + pragma[nomagic] + private predicate revPartialPathIntoReturn( + PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, + TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap + ) { + exists(NodeEx out | + mid.getNodeEx() = out and + mid.getState() = state and + viableReturnPosOutEx(call, pos, out) and + sc1 = TRevSummaryCtx1Some(pos) and + sc2 = TRevSummaryCtx2Some(state) and + sc3 = TRevSummaryCtx3Some(ap) and + ap = mid.getAp() + ) + } + + pragma[nomagic] + private predicate revPartialPathFlowsThrough( + ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, + TRevSummaryCtx3Some sc3, RevPartialAccessPath ap + ) { + exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | + mid.getNodeEx() = p and + mid.getState() = state and + p.getPosition() = ppos and + sc1 = mid.getSummaryCtx1() and + sc2 = mid.getSummaryCtx2() and + sc3 = mid.getSummaryCtx3() and + ap = mid.getAp() and + parameterMatch(ppos, apos) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable0( + DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, + RevPartialAccessPath ap + ) { + exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | + revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _) and + revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap) + ) + } + + pragma[nomagic] + private predicate revPartialPathThroughCallable( + PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap + ) { + exists(DataFlowCall call, ArgumentPosition pos | + revPartialPathThroughCallable0(call, mid, pos, state, ap) and + node.asNode().(ArgNode).argumentOf(call, pos) + ) + } + + private predicate partialFlow(PartialPathNode source, PartialPathNode node) { + source.isFwdSource() and + node = source.getASuccessor+() + } + + private predicate revPartialFlow(PartialPathNode node, PartialPathNode sink) { + sink.isRevSink() and + node.getASuccessor+() = sink + } + + /** + * Holds if there is a partial data flow path from `source` to `node`. The + * approximate distance between `node` and the closest source is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards sink definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sources is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + */ + predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { + partialFlow(source, node) and + dist = node.getSourceDistance() + } + + /** + * Holds if there is a partial data flow path from `node` to `sink`. The + * approximate distance between `node` and the closest sink is `dist` and + * is restricted to be less than or equal to `explorationLimit()`. This + * predicate completely disregards source definitions. + * + * This predicate is intended for data-flow exploration and debugging and may + * perform poorly if the number of sinks is too big and/or the exploration + * limit is set too high without using barriers. + * + * To use this in a `path-problem` query, import the module `PartialPathGraph`. + * + * Note that reverse flow has slightly lower precision than the corresponding + * forward flow, as reverse flow disregards type pruning among other features. + */ + predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { + revPartialFlow(node, sink) and + dist = node.getSinkDistance() + } } } - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll new file mode 100644 index 00000000000..e6bdc74cceb --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl1.qll @@ -0,0 +1,396 @@ +/** + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. + */ + +private import DataFlowImplCommon +private import DataFlowImplSpecific::Private +import DataFlowImplSpecific::Public +private import DataFlowImpl +import DataFlowImplCommonPublic +import FlowStateString + +/** + * A configuration of interprocedural data flow analysis. This defines + * sources, sinks, and any other configurable aspect of the analysis. Each + * use of the global data flow library must define its own unique extension + * of this abstract class. To create a configuration, extend this class with + * a subclass whose characteristic predicate is a unique singleton string. + * For example, write + * + * ```ql + * class MyAnalysisConfiguration extends DataFlow::Configuration { + * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } + * // Override `isSource` and `isSink`. + * // Optionally override `isBarrier`. + * // Optionally override `isAdditionalFlowStep`. + * } + * ``` + * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and + * the edges are those data-flow steps that preserve the value of the node + * along with any additional edges defined by `isAdditionalFlowStep`. + * Specifying nodes in `isBarrier` will remove those nodes from the graph, and + * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going + * and/or out-going edges from those nodes, respectively. + * + * Then, to query whether there is flow between some `source` and `sink`, + * write + * + * ```ql + * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) + * ``` + * + * Multiple configurations can coexist, but two classes extending + * `DataFlow::Configuration` should never depend on each other. One of them + * should instead depend on a `DataFlow2::Configuration`, a + * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. + */ +abstract class Configuration extends string { + bindingset[this] + Configuration() { any() } + + /** + * Holds if `source` is a relevant data flow source. + */ + predicate isSource(Node source) { none() } + + /** + * Holds if `source` is a relevant data flow source with the given initial + * `state`. + */ + predicate isSource(Node source, FlowState state) { none() } + + /** + * Holds if `sink` is a relevant data flow sink. + */ + predicate isSink(Node sink) { none() } + + /** + * Holds if `sink` is a relevant data flow sink accepting `state`. + */ + predicate isSink(Node sink, FlowState state) { none() } + + /** + * Holds if data flow through `node` is prohibited. This completely removes + * `node` from the data flow graph. + */ + predicate isBarrier(Node node) { none() } + + /** + * Holds if data flow through `node` is prohibited when the flow state is + * `state`. + */ + predicate isBarrier(Node node, FlowState state) { none() } + + /** Holds if data flow into `node` is prohibited. */ + predicate isBarrierIn(Node node) { none() } + + /** Holds if data flow out of `node` is prohibited. */ + predicate isBarrierOut(Node node) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited. + */ + deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } + + /** + * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. + * + * Holds if data flow through nodes guarded by `guard` is prohibited when + * the flow state is `state` + */ + deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + */ + predicate isAdditionalFlowStep(Node node1, Node node2) { none() } + + /** + * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. + * This step is only applicable in `state1` and updates the flow state to `state2`. + */ + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + none() + } + + /** + * Holds if an arbitrary number of implicit read steps of content `c` may be + * taken at `node`. + */ + predicate allowImplicitRead(Node node, ContentSet c) { none() } + + /** + * Gets the virtual dispatch branching limit when calculating field flow. + * This can be overridden to a smaller value to improve performance (a + * value of 0 disables field flow), or a larger value to get more results. + */ + int fieldFlowBranchLimit() { result = 2 } + + /** + * Gets a data flow configuration feature to add restrictions to the set of + * valid flow paths. + * + * - `FeatureHasSourceCallContext`: + * Assume that sources have some existing call context to disallow + * conflicting return-flow directly following the source. + * - `FeatureHasSinkCallContext`: + * Assume that sinks have some existing call context to disallow + * conflicting argument-to-parameter flow directly preceding the sink. + * - `FeatureEqualSourceSinkCallContext`: + * Implies both of the above and additionally ensures that the entire flow + * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. + */ + FlowFeature getAFeature() { none() } + + /** Holds if sources should be grouped in the result of `hasFlowPath`. */ + predicate sourceGrouping(Node source, string sourceGroup) { none() } + + /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ + predicate sinkGrouping(Node sink, string sinkGroup) { none() } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + */ + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } + + /** + * Holds if data may flow from `source` to `sink` for this configuration. + * + * The corresponding paths are generated from the end-points and the graph + * included in the module `PathGraph`. + */ + predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } + + /** + * Holds if data may flow from some source to `sink` for this configuration. + */ + predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } + + /** + * DEPRECATED: Use `FlowExploration` instead. + * + * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` + * measured in approximate number of interprocedural steps. + */ + deprecated int explorationLimit() { none() } + + /** + * Holds if hidden nodes should be included in the data flow graph. + * + * This feature should only be used for debugging or when the data flow graph + * is not visualized (for example in a `path-problem` query). + */ + predicate includeHiddenNodes() { none() } +} + +/** + * This class exists to prevent mutual recursion between the user-overridden + * member predicates of `Configuration` and the rest of the data-flow library. + * Good performance cannot be guaranteed in the presence of such recursion, so + * it should be replaced by using more than one copy of the data flow library. + */ +abstract private class ConfigurationRecursionPrevention extends Configuration { + bindingset[this] + ConfigurationRecursionPrevention() { any() } + + override predicate hasFlow(Node source, Node sink) { + strictcount(Node n | this.isSource(n)) < 0 + or + strictcount(Node n | this.isSource(n, _)) < 0 + or + strictcount(Node n | this.isSink(n)) < 0 + or + strictcount(Node n | this.isSink(n, _)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 + or + strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 + or + super.hasFlow(source, sink) + } +} + +/** A bridge class to access the deprecated `isBarrierGuard`. */ +private class BarrierGuardGuardedNodeBridge extends Unit { + abstract predicate guardedNode(Node n, Configuration config); + + abstract predicate guardedNode(Node n, FlowState state, Configuration config); +} + +private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { + deprecated override predicate guardedNode(Node n, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g) and + n = g.getAGuardedNode() + ) + } + + deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { + exists(BarrierGuard g | + config.isBarrierGuard(g, state) and + n = g.getAGuardedNode() + ) + } +} + +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) + or + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) + or + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) + or + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 + } + + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) + } + + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } + + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } + + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) + } + + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) + } + + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } +} + +private import Impl as I +import I + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof I::PathNode { + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { result = super.getNode() } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = getState(super.getState()) } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = getConfig(super.getState()) } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getASuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } + + /** Holds if this node is a grouping of source nodes. */ + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } + + /** Holds if this node is a grouping of sink nodes. */ + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } +} + +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink + ) +} + +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config +} + +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } + +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 1b969756b09..e6bdc74cceb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 1b969756b09..e6bdc74cceb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 1b969756b09..e6bdc74cceb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 1b969756b09..e6bdc74cceb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index 1b969756b09..e6bdc74cceb 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -1,16 +1,16 @@ /** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. + * DEPRECATED: Use `Make` and `MakeWithState` instead. + * + * Provides a `Configuration` class backwards-compatible interface to the data + * flow library. */ private import DataFlowImplCommon private import DataFlowImplSpecific::Private import DataFlowImplSpecific::Public +private import DataFlowImpl import DataFlowImplCommonPublic +import FlowStateString /** * A configuration of interprocedural data flow analysis. This defines @@ -144,6 +144,10 @@ abstract class Configuration extends string { * - `FeatureEqualSourceSinkCallContext`: * Implies both of the above and additionally ensures that the entire flow * path preserves the call context. + * + * These features are generally not relevant for typical end-to-end data flow + * queries, but should only be used for constructing paths that need to + * somehow be pluggable in another path context. */ FlowFeature getAFeature() { none() } @@ -156,7 +160,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from `source` to `sink` for this configuration. */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } + predicate hasFlow(Node source, Node sink) { hasFlow(source, sink, this) } /** * Holds if data may flow from `source` to `sink` for this configuration. @@ -169,9 +173,7 @@ abstract class Configuration extends string { /** * Holds if data may flow from some source to `sink` for this configuration. */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } + predicate hasFlowTo(Node sink) { hasFlowTo(sink, this) } /** * Holds if data may flow from some source to `sink` for this configuration. @@ -179,10 +181,12 @@ abstract class Configuration extends string { predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } /** + * DEPRECATED: Use `FlowExploration` instead. + * * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` * measured in approximate number of interprocedural steps. */ - int explorationLimit() { none() } + deprecated int explorationLimit() { none() } /** * Holds if hidden nodes should be included in the data flow graph. @@ -191,49 +195,6 @@ abstract class Configuration extends string { * is not visualized (for example in a `path-problem` query). */ predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } } /** @@ -263,90 +224,6 @@ abstract private class ConfigurationRecursionPrevention extends Configuration { } } -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - /** A bridge class to access the deprecated `isBarrierGuard`. */ private class BarrierGuardGuardedNodeBridge extends Unit { abstract predicate guardedNode(Node n, Configuration config); @@ -370,3019 +247,94 @@ private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { } } -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) +private FlowState relevantState(Configuration config) { + config.isSource(_, result) or + config.isSink(_, result) or + config.isBarrier(_, result) or + config.isAdditionalFlowStep(_, result, _, _) or + config.isAdditionalFlowStep(_, _, _, result) +} + +private newtype TConfigState = + TMkConfigState(Configuration config, FlowState state) { + state = relevantState(config) or state instanceof FlowStateEmpty + } + +private Configuration getConfig(TConfigState state) { state = TMkConfigState(result, _) } + +private FlowState getState(TConfigState state) { state = TMkConfigState(_, result) } + +private predicate singleConfiguration() { 1 = strictcount(Configuration c) } + +private module Config implements FullStateConfigSig { + class FlowState = TConfigState; + + predicate isSource(Node source, FlowState state) { + getConfig(state).isSource(source, getState(state)) or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) + getConfig(state).isSource(source) and getState(state) instanceof FlowStateEmpty + } + + predicate isSink(Node sink, FlowState state) { + getConfig(state).isSink(sink, getState(state)) or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) + getConfig(state).isSink(sink) and getState(state) instanceof FlowStateEmpty + } + + predicate isBarrier(Node node) { none() } + + predicate isBarrier(Node node, FlowState state) { + getConfig(state).isBarrier(node, getState(state)) or + getConfig(state).isBarrier(node) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getState(state), getConfig(state)) or + any(BarrierGuardGuardedNodeBridge b).guardedNode(node, getConfig(state)) + } + + predicate isBarrierIn(Node node) { any(Configuration config).isBarrierIn(node) } + + predicate isBarrierOut(Node node) { any(Configuration config).isBarrierOut(node) } + + predicate isAdditionalFlowStep(Node node1, Node node2) { + singleConfiguration() and + any(Configuration config).isAdditionalFlowStep(node1, node2) + } + + predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { + getConfig(state1).isAdditionalFlowStep(node1, getState(state1), node2, getState(state2)) and + getConfig(state2) = getConfig(state1) or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) + not singleConfiguration() and + getConfig(state1).isAdditionalFlowStep(node1, node2) and + state2 = state1 } - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup + predicate allowImplicitRead(Node node, ContentSet c) { + any(Configuration config).allowImplicitRead(node, c) } - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } + int fieldFlowBranchLimit() { result = min(any(Configuration config).fieldFlowBranchLimit()) } - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } + FlowFeature getAFeature() { result = any(Configuration config).getAFeature() } - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" + predicate sourceGrouping(Node source, string sourceGroup) { + any(Configuration config).sourceGrouping(source, sourceGroup) } - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + predicate sinkGrouping(Node sink, string sinkGroup) { + any(Configuration config).sinkGrouping(sink, sinkGroup) } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) + predicate includeHiddenNodes() { any(Configuration config).includeHiddenNodes() } } -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) +private import Impl as I +import I /** * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - +class PathNode instanceof I::PathNode { /** Gets a textual representation of this element. */ final string toString() { result = super.toString() } @@ -3406,1548 +358,39 @@ class PathNode instanceof PathNodeImpl { } /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } + final Node getNode() { result = super.getNode() } /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } + final FlowState getState() { result = getState(super.getState()) } /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } + final Configuration getConfiguration() { result = getConfig(super.getState()) } /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + final PathNode getASuccessor() { result = super.getASuccessor() } /** Holds if this node is a source. */ final predicate isSource() { super.isSource() } /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } + final predicate isSourceGroup(string group) { super.isSourceGroup(group) } /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } + final predicate isSinkGroup(string group) { super.isSinkGroup(group) } } -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() +private predicate hasFlow(Node source, Node sink, Configuration config) { + exists(PathNode source0, PathNode sink0 | + hasFlowPath(source0, sink0, config) and + source0.getNode() = source and + sink0.getNode() = sink ) } -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) +private predicate hasFlowPath(PathNode source, PathNode sink, Configuration config) { + hasFlowPath(source, sink) and source.getConfiguration() = config } -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} +private predicate hasFlowTo(Node sink, Configuration config) { hasFlow(_, sink, config) } -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} +predicate flowsTo = hasFlow/3; diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 5d3becc8078..d09fdcfca3e 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -3,15 +3,18 @@ private import DataFlowImplSpecific::Public import Cached module DataFlowImplCommonPublic { - /** A state value to track during data flow. */ - class FlowState = string; + /** Provides `FlowState = string`. */ + module FlowStateString { + /** A state value to track during data flow. */ + class FlowState = string; - /** - * The default state, which is used when the state is unspecified for a source - * or a sink. - */ - class FlowStateEmpty extends FlowState { - FlowStateEmpty() { this = "" } + /** + * The default state, which is used when the state is unspecified for a source + * or a sink. + */ + class FlowStateEmpty extends FlowState { + FlowStateEmpty() { this = "" } + } } private newtype TFlowFeature = @@ -179,6 +182,7 @@ private module LambdaFlow { boolean toJump, DataFlowCallOption lastCall ) { revLambdaFlow0(lambdaCall, kind, node, t, toReturn, toJump, lastCall) and + not expectsContent(node, _) and if castNode(node) or node instanceof ArgNode or node instanceof ReturnNode then compatibleTypes(t, getNodeDataFlowType(node)) else any() diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll index 9bbc70fbdf9..7da63f6c4fa 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplConsistency.qll @@ -18,6 +18,9 @@ module Consistency { /** Holds if `n` should be excluded from the consistency test `uniqueEnclosingCallable`. */ predicate uniqueEnclosingCallableExclude(Node n) { none() } + /** Holds if `call` should be excluded from the consistency test `uniqueCallEnclosingCallable`. */ + predicate uniqueCallEnclosingCallableExclude(DataFlowCall call) { none() } + /** Holds if `n` should be excluded from the consistency test `uniqueNodeLocation`. */ predicate uniqueNodeLocationExclude(Node n) { none() } @@ -86,6 +89,15 @@ module Consistency { ) } + query predicate uniqueCallEnclosingCallable(DataFlowCall call, string msg) { + exists(int c | + c = count(call.getEnclosingCallable()) and + c != 1 and + not any(ConsistencyConfiguration conf).uniqueCallEnclosingCallableExclude(call) and + msg = "Call should have one enclosing callable but has " + c + "." + ) + } + query predicate uniqueType(Node n, string msg) { exists(int c | n instanceof RelevantNode and diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll deleted file mode 100644 index 1b969756b09..00000000000 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ /dev/null @@ -1,4953 +0,0 @@ -/** - * Provides an implementation of global (interprocedural) data flow. This file - * re-exports the local (intraprocedural) data flow analysis from - * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed - * through the `Configuration` class. This file exists in several identical - * copies, allowing queries to use multiple `Configuration` classes that depend - * on each other without introducing mutual recursion among those configurations. - */ - -private import DataFlowImplCommon -private import DataFlowImplSpecific::Private -import DataFlowImplSpecific::Public -import DataFlowImplCommonPublic - -/** - * A configuration of interprocedural data flow analysis. This defines - * sources, sinks, and any other configurable aspect of the analysis. Each - * use of the global data flow library must define its own unique extension - * of this abstract class. To create a configuration, extend this class with - * a subclass whose characteristic predicate is a unique singleton string. - * For example, write - * - * ```ql - * class MyAnalysisConfiguration extends DataFlow::Configuration { - * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" } - * // Override `isSource` and `isSink`. - * // Optionally override `isBarrier`. - * // Optionally override `isAdditionalFlowStep`. - * } - * ``` - * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and - * the edges are those data-flow steps that preserve the value of the node - * along with any additional edges defined by `isAdditionalFlowStep`. - * Specifying nodes in `isBarrier` will remove those nodes from the graph, and - * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going - * and/or out-going edges from those nodes, respectively. - * - * Then, to query whether there is flow between some `source` and `sink`, - * write - * - * ```ql - * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink)) - * ``` - * - * Multiple configurations can coexist, but two classes extending - * `DataFlow::Configuration` should never depend on each other. One of them - * should instead depend on a `DataFlow2::Configuration`, a - * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`. - */ -abstract class Configuration extends string { - bindingset[this] - Configuration() { any() } - - /** - * Holds if `source` is a relevant data flow source. - */ - predicate isSource(Node source) { none() } - - /** - * Holds if `source` is a relevant data flow source with the given initial - * `state`. - */ - predicate isSource(Node source, FlowState state) { none() } - - /** - * Holds if `sink` is a relevant data flow sink. - */ - predicate isSink(Node sink) { none() } - - /** - * Holds if `sink` is a relevant data flow sink accepting `state`. - */ - predicate isSink(Node sink, FlowState state) { none() } - - /** - * Holds if data flow through `node` is prohibited. This completely removes - * `node` from the data flow graph. - */ - predicate isBarrier(Node node) { none() } - - /** - * Holds if data flow through `node` is prohibited when the flow state is - * `state`. - */ - predicate isBarrier(Node node, FlowState state) { none() } - - /** Holds if data flow into `node` is prohibited. */ - predicate isBarrierIn(Node node) { none() } - - /** Holds if data flow out of `node` is prohibited. */ - predicate isBarrierOut(Node node) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited. - */ - deprecated predicate isBarrierGuard(BarrierGuard guard) { none() } - - /** - * DEPRECATED: Use `isBarrier` and `BarrierGuard` module instead. - * - * Holds if data flow through nodes guarded by `guard` is prohibited when - * the flow state is `state` - */ - deprecated predicate isBarrierGuard(BarrierGuard guard, FlowState state) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - */ - predicate isAdditionalFlowStep(Node node1, Node node2) { none() } - - /** - * Holds if data may flow from `node1` to `node2` in addition to the normal data-flow steps. - * This step is only applicable in `state1` and updates the flow state to `state2`. - */ - predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) { - none() - } - - /** - * Holds if an arbitrary number of implicit read steps of content `c` may be - * taken at `node`. - */ - predicate allowImplicitRead(Node node, ContentSet c) { none() } - - /** - * Gets the virtual dispatch branching limit when calculating field flow. - * This can be overridden to a smaller value to improve performance (a - * value of 0 disables field flow), or a larger value to get more results. - */ - int fieldFlowBranchLimit() { result = 2 } - - /** - * Gets a data flow configuration feature to add restrictions to the set of - * valid flow paths. - * - * - `FeatureHasSourceCallContext`: - * Assume that sources have some existing call context to disallow - * conflicting return-flow directly following the source. - * - `FeatureHasSinkCallContext`: - * Assume that sinks have some existing call context to disallow - * conflicting argument-to-parameter flow directly preceding the sink. - * - `FeatureEqualSourceSinkCallContext`: - * Implies both of the above and additionally ensures that the entire flow - * path preserves the call context. - */ - FlowFeature getAFeature() { none() } - - /** Holds if sources should be grouped in the result of `hasFlowPath`. */ - predicate sourceGrouping(Node source, string sourceGroup) { none() } - - /** Holds if sinks should be grouped in the result of `hasFlowPath`. */ - predicate sinkGrouping(Node sink, string sinkGroup) { none() } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - */ - predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) } - - /** - * Holds if data may flow from `source` to `sink` for this configuration. - * - * The corresponding paths are generated from the end-points and the graph - * included in the module `PathGraph`. - */ - predicate hasFlowPath(PathNode source, PathNode sink) { hasFlowPath(source, sink, this) } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowTo(Node sink) { - sink = any(PathNodeSink n | this = n.getConfiguration()).getNodeEx().asNode() - } - - /** - * Holds if data may flow from some source to `sink` for this configuration. - */ - predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) } - - /** - * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev` - * measured in approximate number of interprocedural steps. - */ - int explorationLimit() { none() } - - /** - * Holds if hidden nodes should be included in the data flow graph. - * - * This feature should only be used for debugging or when the data flow graph - * is not visualized (for example in a `path-problem` query). - */ - predicate includeHiddenNodes() { none() } - - /** - * Holds if there is a partial data flow path from `source` to `node`. The - * approximate distance between `node` and the closest source is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards sink definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sources is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - */ - final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) { - partialFlow(source, node, this) and - dist = node.getSourceDistance() - } - - /** - * Holds if there is a partial data flow path from `node` to `sink`. The - * approximate distance between `node` and the closest sink is `dist` and - * is restricted to be less than or equal to `explorationLimit()`. This - * predicate completely disregards source definitions. - * - * This predicate is intended for data-flow exploration and debugging and may - * perform poorly if the number of sinks is too big and/or the exploration - * limit is set too high without using barriers. - * - * This predicate is disabled (has no results) by default. Override - * `explorationLimit()` with a suitable number to enable this predicate. - * - * To use this in a `path-problem` query, import the module `PartialPathGraph`. - * - * Note that reverse flow has slightly lower precision than the corresponding - * forward flow, as reverse flow disregards type pruning among other features. - */ - final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) { - revPartialFlow(node, sink, this) and - dist = node.getSinkDistance() - } -} - -/** - * This class exists to prevent mutual recursion between the user-overridden - * member predicates of `Configuration` and the rest of the data-flow library. - * Good performance cannot be guaranteed in the presence of such recursion, so - * it should be replaced by using more than one copy of the data flow library. - */ -abstract private class ConfigurationRecursionPrevention extends Configuration { - bindingset[this] - ConfigurationRecursionPrevention() { any() } - - override predicate hasFlow(Node source, Node sink) { - strictcount(Node n | this.isSource(n)) < 0 - or - strictcount(Node n | this.isSource(n, _)) < 0 - or - strictcount(Node n | this.isSink(n)) < 0 - or - strictcount(Node n | this.isSink(n, _)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0 - or - strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0 - or - super.hasFlow(source, sink) - } -} - -private newtype TNodeEx = - TNodeNormal(Node n) or - TNodeImplicitRead(Node n, boolean hasRead) { - any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true] - } - -private class NodeEx extends TNodeEx { - string toString() { - result = this.asNode().toString() - or - exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]") - } - - Node asNode() { this = TNodeNormal(result) } - - predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) } - - Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) } - - pragma[nomagic] - private DataFlowCallable getEnclosingCallable0() { - nodeEnclosingCallable(this.projectToNode(), result) - } - - pragma[inline] - DataFlowCallable getEnclosingCallable() { - pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result) - } - - pragma[nomagic] - private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) } - - pragma[inline] - DataFlowType getDataFlowType() { - pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result) - } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -private class ArgNodeEx extends NodeEx { - ArgNodeEx() { this.asNode() instanceof ArgNode } -} - -private class ParamNodeEx extends NodeEx { - ParamNodeEx() { this.asNode() instanceof ParamNode } - - predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) { - this.asNode().(ParamNode).isParameterOf(c, pos) - } - - ParameterPosition getPosition() { this.isParameterOf(_, result) } -} - -private class RetNodeEx extends NodeEx { - RetNodeEx() { this.asNode() instanceof ReturnNodeExt } - - ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) } - - ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() } -} - -private predicate inBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierIn(n) - | - config.isSource(n) or config.isSource(n, _) - ) -} - -private predicate outBarrier(NodeEx node, Configuration config) { - exists(Node n | - node.asNode() = n and - config.isBarrierOut(n) - | - config.isSink(n) or config.isSink(n, _) - ) -} - -/** A bridge class to access the deprecated `isBarrierGuard`. */ -private class BarrierGuardGuardedNodeBridge extends Unit { - abstract predicate guardedNode(Node n, Configuration config); - - abstract predicate guardedNode(Node n, FlowState state, Configuration config); -} - -private class BarrierGuardGuardedNode extends BarrierGuardGuardedNodeBridge { - deprecated override predicate guardedNode(Node n, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g) and - n = g.getAGuardedNode() - ) - } - - deprecated override predicate guardedNode(Node n, FlowState state, Configuration config) { - exists(BarrierGuard g | - config.isBarrierGuard(g, state) and - n = g.getAGuardedNode() - ) - } -} - -pragma[nomagic] -private predicate fullBarrier(NodeEx node, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n) - or - config.isBarrierIn(n) and - not config.isSource(n) and - not config.isSource(n, _) - or - config.isBarrierOut(n) and - not config.isSink(n) and - not config.isSink(n, _) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, config) - ) -} - -pragma[nomagic] -private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) { - exists(Node n | node.asNode() = n | - config.isBarrier(n, state) - or - any(BarrierGuardGuardedNodeBridge b).guardedNode(n, state, config) - ) -} - -pragma[nomagic] -private predicate sourceNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSource(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSource(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -pragma[nomagic] -private predicate sinkNode(NodeEx node, FlowState state, Configuration config) { - ( - config.isSink(node.asNode()) and state instanceof FlowStateEmpty - or - config.isSink(node.asNode(), state) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) -} - -/** Provides the relevant barriers for a step from `node1` to `node2`. */ -pragma[inline] -private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) { - not outBarrier(node1, config) and - not inBarrier(node2, config) and - not fullBarrier(node1, config) and - not fullBarrier(node2, config) -} - -/** - * Holds if data can flow in one local step from `node1` to `node2`. - */ -private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - simpleLocalFlowStepExt(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.asNode() = n and - node2.isImplicitReadNode(n, false) and - not fullBarrier(node1, config) - ) -} - -/** - * Holds if the additional step from `node1` to `node2` does not jump between callables. - */ -private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) - ) - or - exists(Node n | - config.allowImplicitRead(n, _) and - node1.isImplicitReadNode(n, true) and - node2.asNode() = n and - not fullBarrier(node2, config) - ) -} - -private predicate additionalLocalStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) - ) -} - -/** - * Holds if data can flow from `node1` to `node2` in a way that discards call contexts. - */ -private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - jumpStepCached(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if the additional step from `node1` to `node2` jumps between callables. - */ -private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), pragma[only_bind_into](n2)) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate additionalJumpStateStep( - NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config -) { - exists(Node n1, Node n2 | - node1.asNode() = n1 and - node2.asNode() = n2 and - config.isAdditionalFlowStep(pragma[only_bind_into](n1), s1, pragma[only_bind_into](n2), s2) and - getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and - stepFilter(node1, node2, config) and - not stateBarrier(node1, s1, config) and - not stateBarrier(node2, s2, config) and - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) -} - -pragma[nomagic] -private predicate readSet(NodeEx node1, ContentSet c, NodeEx node2, Configuration config) { - readSet(pragma[only_bind_into](node1.asNode()), c, pragma[only_bind_into](node2.asNode())) and - stepFilter(node1, node2, config) - or - exists(Node n | - node2.isImplicitReadNode(n, true) and - node1.isImplicitReadNode(n, _) and - config.allowImplicitRead(n, c) - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(ContentSet cs | - readSet(node1, cs, node2, config) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate clearsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - clearsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -// inline to reduce fan-out via `getAReadContent` -bindingset[c] -private predicate expectsContentEx(NodeEx n, Content c) { - exists(ContentSet cs | - expectsContentCached(n.asNode(), cs) and - pragma[only_bind_out](c) = pragma[only_bind_into](cs).getAReadContent() - ) -} - -pragma[nomagic] -private predicate notExpectsContent(NodeEx n) { not expectsContentCached(n.asNode(), _) } - -pragma[nomagic] -private predicate hasReadStep(Content c, Configuration config) { read(_, c, _, config) } - -pragma[nomagic] -private predicate store( - NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config -) { - store(pragma[only_bind_into](node1.asNode()), tc, pragma[only_bind_into](node2.asNode()), - contentType) and - hasReadStep(tc.getContent(), config) and - stepFilter(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) { - viableReturnPosOut(call, pos, out.asNode()) -} - -pragma[nomagic] -private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) { - viableParamArg(call, p.asNode(), arg.asNode()) -} - -/** - * Holds if field flow should be used for the given configuration. - */ -private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } - -private predicate hasSourceCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSourceCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -private predicate hasSinkCallCtx(Configuration config) { - exists(FlowFeature feature | feature = config.getAFeature() | - feature instanceof FeatureHasSinkCallContext or - feature instanceof FeatureEqualSourceSinkCallContext - ) -} - -/** - * Holds if flow from `p` to a return node of kind `kind` is allowed. - * - * We don't expect a parameter to return stored in itself, unless - * explicitly allowed - */ -bindingset[p, kind] -private predicate parameterFlowThroughAllowed(ParamNodeEx p, ReturnKindExt kind) { - exists(ParameterPosition pos | p.isParameterOf(_, pos) | - not kind.(ParamUpdateReturnKind).getPosition() = pos - or - allowParameterReturnInSelfCached(p.asNode()) - ) -} - -private module Stage1 implements StageSig { - class Ap extends int { - // workaround for bad functionality-induced joins (happens when using `Unit`) - pragma[nomagic] - Ap() { this in [0 .. 1] and this < 1 } - } - - private class Cc = boolean; - - /* Begin: Stage 1 logic. */ - /** - * Holds if `node` is reachable from a source in the configuration `config`. - * - * The Boolean `cc` records whether the node is reached through an - * argument in a call. - */ - private predicate fwdFlow(NodeEx node, Cc cc, Configuration config) { - sourceNode(node, _, config) and - if hasSourceCallCtx(config) then cc = true else cc = false - or - exists(NodeEx mid | fwdFlow(mid, cc, config) | - localFlowStep(mid, node, config) or - additionalLocalFlowStep(mid, node, config) or - additionalLocalStateStep(mid, _, node, _, config) - ) - or - exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false | - jumpStep(mid, node, config) or - additionalJumpStep(mid, node, config) or - additionalJumpStateStep(mid, _, node, _, config) - ) - or - // store - exists(NodeEx mid | - useFieldFlow(config) and - fwdFlow(mid, cc, config) and - store(mid, _, node, _, config) - ) - or - // read - exists(ContentSet c | - fwdFlowReadSet(c, node, cc, config) and - fwdFlowConsCandSet(c, _, config) - ) - or - // flow into a callable - fwdFlowIn(_, _, _, node, config) and - cc = true - or - // flow out of a callable - fwdFlowOut(_, node, false, config) and - cc = false - or - // flow through a callable - exists(DataFlowCall call | - fwdFlowOutFromArg(call, node, config) and - fwdFlowIsEntered(call, cc, config) - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowIn( - DataFlowCall call, NodeEx arg, Cc cc, ParamNodeEx p, Configuration config - ) { - // call context cannot help reduce virtual dispatch - fwdFlow(arg, cc, config) and - viableParamArgEx(call, p, arg) and - not fullBarrier(p, config) and - ( - cc = false - or - cc = true and - not reducedViableImplInCallContext(call, _, _) - ) - or - // call context may help reduce virtual dispatch - exists(DataFlowCallable target | - fwdFlowInReducedViableImplInSomeCallContext(call, arg, p, target, config) and - target = viableImplInSomeFwdFlowCallContextExt(call, config) and - cc = true - ) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) { - fwdFlowIn(call, _, cc, _, config) - } - - pragma[nomagic] - private predicate fwdFlowInReducedViableImplInSomeCallContext( - DataFlowCall call, NodeEx arg, ParamNodeEx p, DataFlowCallable target, Configuration config - ) { - fwdFlow(arg, true, config) and - viableParamArgEx(call, p, arg) and - reducedViableImplInCallContext(call, _, _) and - target = p.getEnclosingCallable() and - not fullBarrier(p, config) - } - - /** - * Gets a viable dispatch target of `call` in the context `ctx`. This is - * restricted to those `call`s for which a context might make a difference, - * and to `ctx`s that are reachable in `fwdFlow`. - */ - pragma[nomagic] - private DataFlowCallable viableImplInSomeFwdFlowCallContextExt( - DataFlowCall call, Configuration config - ) { - exists(DataFlowCall ctx | - fwdFlowIsEntered(ctx, _, config) and - result = viableImplInCallContextExt(call, ctx) - ) - } - - private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) } - - pragma[nomagic] - private predicate fwdFlowReadSet(ContentSet c, NodeEx node, Cc cc, Configuration config) { - exists(NodeEx mid | - fwdFlow(mid, cc, config) and - readSet(mid, c, node, config) - ) - } - - /** - * Holds if `c` is the target of a store in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, TypedContent tc | - not fullBarrier(node, config) and - useFieldFlow(config) and - fwdFlow(mid, _, config) and - store(mid, tc, node, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `cs` may be interpreted in a read as the target of some store - * into `c`, in the flow covered by `fwdFlow`. - */ - pragma[nomagic] - private predicate fwdFlowConsCandSet(ContentSet cs, Content c, Configuration config) { - fwdFlowConsCand(c, config) and - c = cs.getAReadContent() - } - - pragma[nomagic] - private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) { - exists(RetNodeEx ret | - fwdFlow(ret, cc, config) and - ret.getReturnPosition() = pos - ) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) { - exists(ReturnPosition pos | - fwdFlowReturnPosition(pos, cc, config) and - viableReturnPosOutEx(call, pos, out) and - not fullBarrier(out, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) { - fwdFlowOut(call, out, true, config) - } - - private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1 | - additionalLocalStateStep(node1, state1, _, state2, config) or - additionalJumpStateStep(node1, state1, _, state2, config) - | - fwdFlow(node1, config) - ) - } - - private predicate fwdFlowState(FlowState state, Configuration config) { - sourceNode(_, state, config) - or - exists(FlowState state0 | - fwdFlowState(state0, config) and - stateStepFwd(state0, state, config) - ) - } - - /** - * Holds if `node` is part of a path from a source to a sink in the - * configuration `config`. - * - * The Boolean `toReturn` records whether the node must be returned from - * the enclosing callable in order to reach a sink. - */ - pragma[nomagic] - private predicate revFlow(NodeEx node, boolean toReturn, Configuration config) { - revFlow0(node, toReturn, config) and - fwdFlow(node, config) - } - - pragma[nomagic] - private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) { - exists(FlowState state | - fwdFlow(node, pragma[only_bind_into](config)) and - sinkNode(node, state, config) and - fwdFlowState(state, pragma[only_bind_into](config)) and - if hasSinkCallCtx(config) then toReturn = true else toReturn = false - ) - or - exists(NodeEx mid | revFlow(mid, toReturn, config) | - localFlowStep(node, mid, config) or - additionalLocalFlowStep(node, mid, config) or - additionalLocalStateStep(node, _, mid, _, config) - ) - or - exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false | - jumpStep(node, mid, config) or - additionalJumpStep(node, mid, config) or - additionalJumpStateStep(node, _, mid, _, config) - ) - or - // store - exists(Content c | - revFlowStore(c, node, toReturn, config) and - revFlowConsCand(c, config) - ) - or - // read - exists(NodeEx mid, ContentSet c | - readSet(node, c, mid, config) and - fwdFlowConsCandSet(c, _, pragma[only_bind_into](config)) and - revFlow(mid, toReturn, pragma[only_bind_into](config)) - ) - or - // flow into a callable - revFlowIn(_, node, false, config) and - toReturn = false - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(pos, config) and - node.(RetNodeEx).getReturnPosition() = pos and - toReturn = true - ) - or - // flow through a callable - exists(DataFlowCall call | - revFlowInToReturn(call, node, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - /** - * Holds if `c` is the target of a read in the flow covered by `revFlow`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Content c, Configuration config) { - exists(NodeEx mid, NodeEx node, ContentSet cs | - fwdFlow(node, pragma[only_bind_into](config)) and - readSet(node, cs, mid, config) and - fwdFlowConsCandSet(cs, c, pragma[only_bind_into](config)) and - revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) { - exists(NodeEx mid, TypedContent tc | - revFlow(mid, toReturn, pragma[only_bind_into](config)) and - fwdFlowConsCand(c, pragma[only_bind_into](config)) and - store(node, tc, mid, _, config) and - c = tc.getContent() - ) - } - - /** - * Holds if `c` is the target of both a read and a store in the flow covered - * by `revFlow`. - */ - pragma[nomagic] - additional predicate revFlowIsReadAndStored(Content c, Configuration conf) { - revFlowConsCand(c, conf) and - revFlowStore(c, _, _, conf) - } - - pragma[nomagic] - additional predicate viableReturnPosOutNodeCandFwd1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config - ) { - fwdFlowReturnPosition(pos, _, config) and - viableReturnPosOutEx(call, pos, out) - } - - pragma[nomagic] - private predicate revFlowOut(ReturnPosition pos, Configuration config) { - exists(NodeEx out | - revFlow(out, _, config) and - viableReturnPosOutNodeCandFwd1(_, pos, out, config) - ) - } - - pragma[nomagic] - additional predicate viableParamArgNodeCandFwd1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config - ) { - fwdFlowIn(call, arg, _, p, config) - } - - // inline to reduce the number of iterations - pragma[inline] - private predicate revFlowIn( - DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config - ) { - exists(ParamNodeEx p | - revFlow(p, toReturn, config) and - viableParamArgNodeCandFwd1(call, p, arg, config) - ) - } - - pragma[nomagic] - private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) { - revFlowIn(call, arg, true, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) { - exists(NodeEx out | - revFlow(out, toReturn, config) and - fwdFlowOutFromArg(call, out, config) - ) - } - - private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - additionalLocalStateStep(node1, state1, node2, state2, config) or - additionalJumpStateStep(node1, state1, node2, state2, config) - | - revFlow(node1, _, pragma[only_bind_into](config)) and - revFlow(node2, _, pragma[only_bind_into](config)) and - fwdFlowState(state1, pragma[only_bind_into](config)) and - fwdFlowState(state2, pragma[only_bind_into](config)) - ) - } - - additional predicate revFlowState(FlowState state, Configuration config) { - exists(NodeEx node | - sinkNode(node, state, config) and - revFlow(node, _, pragma[only_bind_into](config)) and - fwdFlowState(state, pragma[only_bind_into](config)) - ) - or - exists(FlowState state0 | - revFlowState(state0, config) and - stateStepRev(state, state0, config) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Content c | - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - revFlow(node2, pragma[only_bind_into](config)) and - store(node1, tc, node2, contentType, config) and - c = tc.getContent() and - exists(ap1) - ) - } - - pragma[nomagic] - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) { - revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - read(n1, c, n2, pragma[only_bind_into](config)) and - revFlow(n2, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, config) and - exists(ap) - } - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, _, pragma[only_bind_into](config)) and - exists(state) and - exists(ap) - } - - private predicate throughFlowNodeCand(NodeEx node, Configuration config) { - revFlow(node, true, config) and - fwdFlow(node, true, config) and - not inBarrier(node, config) and - not outBarrier(node, config) - } - - /** Holds if flow may return from `callable`. */ - pragma[nomagic] - private predicate returnFlowCallableNodeCand( - DataFlowCallable callable, ReturnKindExt kind, Configuration config - ) { - exists(RetNodeEx ret | - throughFlowNodeCand(ret, config) and - callable = ret.getEnclosingCallable() and - kind = ret.getKind() - ) - } - - /** - * Holds if flow may enter through `p` and reach a return node making `p` a - * candidate for the origin of a summary. - */ - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(DataFlowCallable c, ReturnKindExt kind | - throughFlowNodeCand(p, config) and - returnFlowCallableNodeCand(c, kind, config) and - p.getEnclosingCallable() = c and - exists(ap) and - parameterFlowThroughAllowed(p, kind) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - throughFlowNodeCand(ret, config) and - kind = ret.getKind() and - exists(argAp) and - exists(ap) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, boolean toReturn | - revFlow(arg, toReturn, config) and - revFlowInToReturn(call, arg, config) and - revFlowIsReturned(call, toReturn, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, config)) and - fields = count(Content f0 | fwdFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | fwdFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config)) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, config)) and - fields = count(Content f0 | revFlowConsCand(f0, config)) and - conscand = -1 and - states = count(FlowState state | revFlowState(state, config)) and - tuples = count(NodeEx n, boolean b | revFlow(n, b, config)) - } - /* End: Stage 1 logic. */ -} - -pragma[noinline] -private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - localFlowStep(node1, node2, config) -} - -pragma[noinline] -private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) { - Stage1::revFlow(node2, config) and - additionalLocalFlowStep(node1, node2, config) -} - -pragma[nomagic] -private predicate viableReturnPosOutNodeCand1( - DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config -) { - Stage1::revFlow(out, config) and - Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, Configuration config -) { - exists(ReturnPosition pos | - viableReturnPosOutNodeCand1(call, pos, out, config) and - pos = ret.getReturnPosition() and - kind = pos.getKind() and - Stage1::revFlow(ret, config) and - not outBarrier(ret, config) and - not inBarrier(out, config) - ) -} - -pragma[nomagic] -private predicate viableParamArgNodeCand1( - DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config -) { - Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and - Stage1::revFlow(arg, config) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config -) { - viableParamArgNodeCand1(call, p, arg, config) and - Stage1::revFlow(p, config) and - not outBarrier(arg, config) and - not inBarrier(p, config) -} - -/** - * Gets the amount of forward branching on the origin of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int branch(NodeEx n1, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n1, _, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf) - ) -} - -/** - * Gets the amount of backward branching on the target of a cross-call path - * edge in the graph of paths between sources and sinks that ignores call - * contexts. - */ -pragma[nomagic] -private int join(NodeEx n2, Configuration conf) { - result = - strictcount(NodeEx n | - flowOutOfCallNodeCand1(_, n, _, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf) - ) -} - -/** - * Holds if data can flow out of `call` from `ret` to `out`, either - * through a `ReturnNode` or through an argument that has been mutated, and - * that this step is part of a path from a source to a sink. The - * `allowsFieldFlow` flag indicates whether the branching is within the limit - * specified by the configuration. - */ -pragma[nomagic] -private predicate flowOutOfCallNodeCand1( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, ret, kind, out, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(ret, pragma[only_bind_into](config)) and - j = join(out, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -/** - * Holds if data can flow into `call` and that this step is part of a - * path from a source to a sink. The `allowsFieldFlow` flag indicates whether - * the branching is within the limit specified by the configuration. - */ -pragma[nomagic] -private predicate flowIntoCallNodeCand1( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config -) { - flowIntoCallNodeCand1(call, arg, p, pragma[only_bind_into](config)) and - exists(int b, int j | - b = branch(arg, pragma[only_bind_into](config)) and - j = join(p, pragma[only_bind_into](config)) and - if b.minimum(j) <= config.fieldFlowBranchLimit() - then allowsFieldFlow = true - else allowsFieldFlow = false - ) -} - -private signature module StageSig { - class Ap; - - predicate revFlow(NodeEx node, Configuration config); - - predicate revFlowAp(NodeEx node, Ap ap, Configuration config); - - bindingset[node, state, config] - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config); - - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config); - - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config); - - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ); - - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ); - - predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config); -} - -private module MkStage { - class ApApprox = PrevStage::Ap; - - signature module StageParam { - class Ap; - - class ApNil extends Ap; - - bindingset[result, ap] - ApApprox getApprox(Ap ap); - - ApNil getApNil(NodeEx node); - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail); - - /** - * An approximation of `Content` that corresponds to the precision level of - * `Ap`, such that the mappings from both `Ap` and `Content` to this type - * are functional. - */ - class ApHeadContent; - - ApHeadContent getHeadContent(Ap ap); - - ApHeadContent projectToHeadContent(Content c); - - class ApOption; - - ApOption apNone(); - - ApOption apSome(Ap ap); - - class Cc; - - class CcCall extends Cc; - - // TODO: member predicate on CcCall - predicate matchesCall(CcCall cc, DataFlowCall call); - - class CcNoCall extends Cc; - - Cc ccNone(); - - CcCall ccSomeCall(); - - class LocalCc; - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc); - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc); - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc); - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ); - - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - Configuration config - ); - - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config - ); - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config); - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType); - } - - module Stage implements StageSig { - import Param - - /* Begin: Stage logic. */ - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - private predicate revFlowApAlias(NodeEx node, ApApprox apa, Configuration config) { - PrevStage::revFlowAp(node, apa, config) - } - - pragma[nomagic] - private predicate flowIntoCallApa( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, ApApprox apa, - Configuration config - ) { - flowIntoCall(call, arg, p, allowsFieldFlow, config) and - PrevStage::revFlowAp(p, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(arg, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowOutOfCallApa( - DataFlowCall call, RetNodeEx ret, ReturnKindExt kind, NodeEx out, boolean allowsFieldFlow, - ApApprox apa, Configuration config - ) { - flowOutOfCall(call, ret, kind, out, allowsFieldFlow, config) and - PrevStage::revFlowAp(out, pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - revFlowApAlias(ret, pragma[only_bind_into](apa), pragma[only_bind_into](config)) - } - - pragma[nomagic] - private predicate flowThroughOutOfCall( - DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, - ApApprox argApa, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - flowOutOfCallApa(call, ret, kind, out, allowsFieldFlow, apa, pragma[only_bind_into](config)) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) and - matchesCall(ccc, call) - ) - } - - /** - * Holds if `node` is reachable with access path `ap` from a source in the - * configuration `config`. - * - * The call context `cc` records whether the node is reached through an - * argument in a call, and if so, `summaryCtx` and `argAp` record the - * corresponding parameter position and access path of that argument, respectively. - */ - pragma[nomagic] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - fwdFlow0(node, state, cc, summaryCtx, argAp, ap, apa, config) and - PrevStage::revFlow(node, state, apa, config) and - filter(node, state, ap, config) - } - - pragma[inline] - additional predicate fwdFlow( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, cc, summaryCtx, argAp, ap, _, config) - } - - pragma[nomagic] - private predicate fwdFlow0( - NodeEx node, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap, - ApApprox apa, Configuration config - ) { - sourceNode(node, state, config) and - (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and - argAp = apNone() and - summaryCtx = TParamNodeNone() and - ap = getApNil(node) and - apa = getApprox(ap) - or - exists(NodeEx mid, FlowState state0, Ap ap0, ApApprox apa0, LocalCc localCc | - fwdFlow(mid, state0, cc, summaryCtx, argAp, ap0, apa0, config) and - localCc = getLocalCc(mid, cc) - | - localStep(mid, state0, node, state, true, _, config, localCc) and - ap = ap0 and - apa = apa0 - or - localStep(mid, state0, node, state, false, ap, config, localCc) and - ap0 instanceof ApNil and - apa = getApprox(ap) - ) - or - exists(NodeEx mid | - fwdFlow(mid, pragma[only_bind_into](state), _, _, _, ap, apa, pragma[only_bind_into](config)) and - jumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(mid, state, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStep(mid, node, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(mid, state0, _, _, _, nil, pragma[only_bind_into](config)) and - additionalJumpStateStep(mid, state0, node, state, config) and - cc = ccNone() and - summaryCtx = TParamNodeNone() and - argAp = apNone() and - ap = getApNil(node) and - apa = getApprox(ap) - ) - or - // store - exists(TypedContent tc, Ap ap0 | - fwdFlowStore(_, ap0, tc, node, state, cc, summaryCtx, argAp, config) and - ap = apCons(tc, ap0) and - apa = getApprox(ap) - ) - or - // read - exists(Ap ap0, Content c | - fwdFlowRead(ap0, c, _, node, state, cc, summaryCtx, argAp, config) and - fwdFlowConsCand(ap0, c, ap, config) and - apa = getApprox(ap) - ) - or - // flow into a callable - fwdFlowIn(_, node, state, _, cc, _, _, ap, apa, config) and - if PrevStage::parameterMayFlowThrough(node, apa, config) - then ( - summaryCtx = TParamNodeSome(node.asNode()) and - argAp = apSome(ap) - ) else ( - summaryCtx = TParamNodeNone() and argAp = apNone() - ) - or - // flow out of a callable - exists( - DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc, - DataFlowCallable inner - | - fwdFlow(ret, state, innercc, summaryCtx, argAp, ap, apa, config) and - flowOutOfCallApa(call, ret, _, node, allowsFieldFlow, apa, config) and - inner = ret.getEnclosingCallable() and - cc = getCallContextReturn(inner, call, innercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - or - // flow through a callable - exists( - DataFlowCall call, CcCall ccc, RetNodeEx ret, boolean allowsFieldFlow, ApApprox innerArgApa - | - fwdFlowThrough(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, node, allowsFieldFlow, innerArgApa, apa, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowStore( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(DataFlowType contentType, ApApprox apa1 | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap1, apa1, config) and - PrevStage::storeStepCand(node1, apa1, tc, node2, contentType, config) and - typecheckStore(ap1, contentType) - ) - } - - /** - * Holds if forward flow with access path `tail` reaches a store of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(TypedContent tc | - fwdFlowStore(_, tail, tc, _, _, _, _, _, config) and - tc.getContent() = c and - cons = apCons(tc, tail) - ) - } - - pragma[nomagic] - private predicate readStepCand( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - PrevStage::readStepCand(node1, c, node2, config) and - apc = projectToHeadContent(c) - } - - bindingset[node1, apc] - pragma[inline_late] - private predicate readStepCand0( - NodeEx node1, ApHeadContent apc, Content c, NodeEx node2, Configuration config - ) { - readStepCand(node1, apc, c, node2, config) - } - - pragma[nomagic] - private predicate fwdFlowRead( - Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, - ParamNodeOption summaryCtx, ApOption argAp, Configuration config - ) { - exists(ApHeadContent apc | - fwdFlow(node1, state, cc, summaryCtx, argAp, ap, config) and - apc = getHeadContent(ap) and - readStepCand0(node1, apc, c, node2, config) - ) - } - - pragma[nomagic] - private predicate fwdFlowIn( - DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, CcCall innercc, - ParamNodeOption summaryCtx, ApOption argAp, Ap ap, ApApprox apa, Configuration config - ) { - exists(ArgNodeEx arg, boolean allowsFieldFlow | - fwdFlow(arg, state, outercc, summaryCtx, argAp, ap, apa, config) and - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate fwdFlowRetFromArg( - RetNodeEx ret, FlowState state, CcCall ccc, ParamNodeEx summaryCtx, Ap argAp, ApApprox argApa, - Ap ap, ApApprox apa, Configuration config - ) { - exists(ReturnKindExt kind | - fwdFlow(pragma[only_bind_into](ret), state, ccc, - TParamNodeSome(pragma[only_bind_into](summaryCtx.asNode())), - pragma[only_bind_into](apSome(argAp)), ap, pragma[only_bind_into](apa), - pragma[only_bind_into](config)) and - kind = ret.getKind() and - parameterFlowThroughAllowed(summaryCtx, kind) and - argApa = getApprox(argAp) and - PrevStage::returnMayFlowThrough(ret, argApa, apa, kind, pragma[only_bind_into](config)) - ) - } - - pragma[inline] - private predicate fwdFlowThrough0( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ParamNodeEx innerSummaryCtx, - Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowRetFromArg(ret, state, ccc, innerSummaryCtx, innerArgAp, innerArgApa, ap, apa, config) and - fwdFlowIsEntered(call, cc, ccc, summaryCtx, argAp, innerSummaryCtx, innerArgAp, config) - } - - pragma[nomagic] - private predicate fwdFlowThrough( - DataFlowCall call, Cc cc, FlowState state, CcCall ccc, ParamNodeOption summaryCtx, - ApOption argAp, Ap ap, ApApprox apa, RetNodeEx ret, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, cc, state, ccc, summaryCtx, argAp, ap, apa, ret, _, _, innerArgApa, - config) - } - - /** - * Holds if an argument to `call` is reached in the flow covered by `fwdFlow` - * and data might flow through the target callable and back out at `call`. - */ - pragma[nomagic] - private predicate fwdFlowIsEntered( - DataFlowCall call, Cc cc, CcCall innerCc, ParamNodeOption summaryCtx, ApOption argAp, - ParamNodeEx p, Ap ap, Configuration config - ) { - exists(ApApprox apa | - fwdFlowIn(call, pragma[only_bind_into](p), _, cc, innerCc, summaryCtx, argAp, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - PrevStage::parameterMayFlowThrough(p, apa, config) and - PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate storeStepFwd( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config - ) { - fwdFlowStore(node1, ap1, tc, node2, _, _, _, _, config) and - ap2 = apCons(tc, ap1) and - fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, _, config) - } - - private predicate readStepFwd( - NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config - ) { - fwdFlowRead(ap1, c, n1, n2, _, _, _, _, config) and - fwdFlowConsCand(ap1, c, ap2, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough0( - DataFlowCall call, FlowState state, CcCall ccc, Ap ap, ApApprox apa, RetNodeEx ret, - ParamNodeEx innerSummaryCtx, Ap innerArgAp, ApApprox innerArgApa, Configuration config - ) { - fwdFlowThrough0(call, _, state, ccc, _, _, ap, apa, ret, innerSummaryCtx, innerArgAp, - innerArgApa, config) - } - - pragma[nomagic] - private predicate returnFlowsThrough( - RetNodeEx ret, ReturnPosition pos, FlowState state, CcCall ccc, ParamNodeEx p, Ap argAp, - Ap ap, Configuration config - ) { - exists(DataFlowCall call, ApApprox apa, boolean allowsFieldFlow, ApApprox innerArgApa | - returnFlowsThrough0(call, state, ccc, ap, apa, ret, p, argAp, innerArgApa, config) and - flowThroughOutOfCall(call, ccc, ret, _, allowsFieldFlow, innerArgApa, apa, config) and - pos = ret.getReturnPosition() and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowThroughIntoCall( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap argAp, Ap ap, - Configuration config - ) { - exists(ApApprox argApa | - flowIntoCallApa(call, pragma[only_bind_into](arg), pragma[only_bind_into](p), - allowsFieldFlow, argApa, pragma[only_bind_into](config)) and - fwdFlow(arg, _, _, _, _, pragma[only_bind_into](argAp), argApa, - pragma[only_bind_into](config)) and - returnFlowsThrough(_, _, _, _, p, pragma[only_bind_into](argAp), ap, - pragma[only_bind_into](config)) and - if allowsFieldFlow = false then argAp instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate flowIntoCallAp( - DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Ap ap, - Configuration config - ) { - exists(ApApprox apa | - flowIntoCallApa(call, arg, p, allowsFieldFlow, apa, config) and - fwdFlow(arg, _, _, _, _, ap, apa, config) - ) - } - - pragma[nomagic] - private predicate flowOutOfCallAp( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, NodeEx out, boolean allowsFieldFlow, - Ap ap, Configuration config - ) { - exists(ApApprox apa | - flowOutOfCallApa(call, ret, _, out, allowsFieldFlow, apa, config) and - fwdFlow(ret, _, _, _, _, ap, apa, config) and - pos = ret.getReturnPosition() - ) - } - - /** - * Holds if `node` with access path `ap` is part of a path from a source to a - * sink in the configuration `config`. - * - * The parameter `returnCtx` records whether (and how) the node must be returned - * from the enclosing callable in order to reach a sink, and if so, `returnAp` - * records the access path of the returned value. - */ - pragma[nomagic] - additional predicate revFlow( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - revFlow0(node, state, returnCtx, returnAp, ap, config) and - fwdFlow(node, state, _, _, _, ap, config) - } - - pragma[nomagic] - private predicate revFlow0( - NodeEx node, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap, - Configuration config - ) { - fwdFlow(node, state, _, _, _, ap, config) and - sinkNode(node, state, config) and - ( - if hasSinkCallCtx(config) - then returnCtx = TReturnCtxNoFlowThrough() - else returnCtx = TReturnCtxNone() - ) and - returnAp = apNone() and - ap instanceof ApNil - or - exists(NodeEx mid, FlowState state0 | - localStep(node, state, mid, state0, true, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, ap, config) - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, pragma[only_bind_into](state), _, _, _, ap, pragma[only_bind_into](config)) and - localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and - revFlow(mid, state0, returnCtx, returnAp, nil, pragma[only_bind_into](config)) and - ap instanceof ApNil - ) - or - exists(NodeEx mid | - jumpStep(node, mid, config) and - revFlow(mid, state, _, _, ap, config) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() - ) - or - exists(NodeEx mid, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStep(node, mid, config) and - revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - exists(NodeEx mid, FlowState state0, ApNil nil | - fwdFlow(node, _, _, _, _, ap, pragma[only_bind_into](config)) and - additionalJumpStateStep(node, state, mid, state0, config) and - revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil, - pragma[only_bind_into](config)) and - returnCtx = TReturnCtxNone() and - returnAp = apNone() and - ap instanceof ApNil - ) - or - // store - exists(Ap ap0, Content c | - revFlowStore(ap0, c, ap, node, state, _, _, returnCtx, returnAp, config) and - revFlowConsCand(ap0, c, ap, config) - ) - or - // read - exists(NodeEx mid, Ap ap0 | - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - readStepFwd(node, ap, _, mid, ap0, config) - ) - or - // flow into a callable - exists(ParamNodeEx p, boolean allowsFieldFlow | - revFlow(p, state, TReturnCtxNone(), returnAp, ap, config) and - flowIntoCallAp(_, node, p, allowsFieldFlow, ap, config) and - (if allowsFieldFlow = false then ap instanceof ApNil else any()) and - returnCtx = TReturnCtxNone() - ) - or - // flow through a callable - exists(DataFlowCall call, ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, node, p, _, ap, innerReturnAp, config) - ) - or - // flow out of a callable - exists(ReturnPosition pos | - revFlowOut(_, node, pos, state, _, _, ap, config) and - if returnFlowsThrough(node, pos, state, _, _, _, ap, config) - then ( - returnCtx = TReturnCtxMaybeFlowThrough(pos) and - returnAp = apSome(ap) - ) else ( - returnCtx = TReturnCtxNoFlowThrough() and returnAp = apNone() - ) - ) - } - - pragma[nomagic] - private predicate revFlowStore( - Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid, - ReturnCtx returnCtx, ApOption returnAp, Configuration config - ) { - revFlow(mid, state, returnCtx, returnAp, ap0, config) and - storeStepFwd(node, ap, tc, mid, ap0, config) and - tc.getContent() = c - } - - /** - * Holds if reverse flow with access path `tail` reaches a read of `c` - * resulting in access path `cons`. - */ - pragma[nomagic] - private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) { - exists(NodeEx mid, Ap tail0 | - revFlow(mid, _, _, _, tail, config) and - tail = pragma[only_bind_into](tail0) and - readStepFwd(_, cons, c, mid, tail0, config) - ) - } - - pragma[nomagic] - private predicate revFlowOut( - DataFlowCall call, RetNodeEx ret, ReturnPosition pos, FlowState state, ReturnCtx returnCtx, - ApOption returnAp, Ap ap, Configuration config - ) { - exists(NodeEx out, boolean allowsFieldFlow | - revFlow(out, state, returnCtx, returnAp, ap, config) and - flowOutOfCallAp(call, ret, pos, out, allowsFieldFlow, ap, config) and - if allowsFieldFlow = false then ap instanceof ApNil else any() - ) - } - - pragma[nomagic] - private predicate revFlowParamToReturn( - ParamNodeEx p, FlowState state, ReturnPosition pos, Ap returnAp, Ap ap, Configuration config - ) { - revFlow(pragma[only_bind_into](p), state, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), - pragma[only_bind_into](ap), pragma[only_bind_into](config)) and - parameterFlowThroughAllowed(p, pos.getKind()) and - PrevStage::parameterMayFlowThrough(p, getApprox(ap), config) - } - - pragma[nomagic] - private predicate revFlowThrough( - DataFlowCall call, ReturnCtx returnCtx, ParamNodeEx p, FlowState state, ReturnPosition pos, - ApOption returnAp, Ap ap, Ap innerReturnAp, Configuration config - ) { - revFlowParamToReturn(p, state, pos, innerReturnAp, ap, config) and - revFlowIsReturned(call, returnCtx, returnAp, pos, innerReturnAp, config) - } - - /** - * Holds if an output from `call` is reached in the flow covered by `revFlow` - * and data might flow through the target callable resulting in reverse flow - * reaching an argument of `call`. - */ - pragma[nomagic] - private predicate revFlowIsReturned( - DataFlowCall call, ReturnCtx returnCtx, ApOption returnAp, ReturnPosition pos, Ap ap, - Configuration config - ) { - exists(RetNodeEx ret, FlowState state, CcCall ccc | - revFlowOut(call, ret, pos, state, returnCtx, returnAp, ap, config) and - returnFlowsThrough(ret, pos, state, ccc, _, _, ap, config) and - matchesCall(ccc, call) - ) - } - - pragma[nomagic] - predicate storeStepCand( - NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType, - Configuration config - ) { - exists(Ap ap2, Content c | - PrevStage::storeStepCand(node1, _, tc, node2, contentType, config) and - revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and - revFlowConsCand(ap2, c, ap1, config) - ) - } - - predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) { - exists(Ap ap1, Ap ap2 | - revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and - readStepFwd(node1, ap1, c, node2, ap2, config) and - revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _, - pragma[only_bind_into](config)) - ) - } - - additional predicate revFlow(NodeEx node, FlowState state, Configuration config) { - revFlow(node, state, _, _, _, config) - } - - predicate revFlow(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, _, _, ap, config) - } - - pragma[nomagic] - predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) } - - pragma[nomagic] - predicate revFlowAp(NodeEx node, Ap ap, Configuration config) { - revFlow(node, _, _, _, ap, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, Configuration config) { - revFlow(node, _, _, _, _, config) - } - - // use an alias as a workaround for bad functionality-induced joins - pragma[nomagic] - additional predicate revFlowAlias(NodeEx node, FlowState state, Ap ap, Configuration config) { - revFlow(node, state, ap, config) - } - - private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepFwd(_, ap, tc, _, _, config) - } - - private predicate revConsCand(TypedContent tc, Ap ap, Configuration config) { - storeStepCand(_, ap, tc, _, _, config) - } - - private predicate validAp(Ap ap, Configuration config) { - revFlow(_, _, _, _, ap, config) and ap instanceof ApNil - or - exists(TypedContent head, Ap tail | - consCand(head, tail, config) and - ap = apCons(head, tail) - ) - } - - additional predicate consCand(TypedContent tc, Ap ap, Configuration config) { - revConsCand(tc, ap, config) and - validAp(ap, config) - } - - pragma[nomagic] - private predicate parameterFlowsThroughRev( - ParamNodeEx p, Ap ap, ReturnPosition pos, Ap returnAp, Configuration config - ) { - revFlow(p, _, TReturnCtxMaybeFlowThrough(pos), apSome(returnAp), ap, config) and - parameterFlowThroughAllowed(p, pos.getKind()) - } - - pragma[nomagic] - predicate parameterMayFlowThrough(ParamNodeEx p, Ap ap, Configuration config) { - exists(ReturnPosition pos | - returnFlowsThrough(_, pos, _, _, p, ap, _, config) and - parameterFlowsThroughRev(p, ap, pos, _, config) - ) - } - - pragma[nomagic] - predicate returnMayFlowThrough( - RetNodeEx ret, Ap argAp, Ap ap, ReturnKindExt kind, Configuration config - ) { - exists(ParamNodeEx p, ReturnPosition pos | - returnFlowsThrough(ret, pos, _, _, p, argAp, ap, config) and - parameterFlowsThroughRev(p, argAp, pos, ap, config) and - kind = pos.getKind() - ) - } - - pragma[nomagic] - private predicate revFlowThroughArg( - DataFlowCall call, ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, - Ap ap, Configuration config - ) { - exists(ParamNodeEx p, Ap innerReturnAp | - revFlowThrough(call, returnCtx, p, state, _, returnAp, ap, innerReturnAp, config) and - flowThroughIntoCall(call, arg, p, _, ap, innerReturnAp, config) - ) - } - - pragma[nomagic] - predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) { - exists(ArgNodeEx arg, FlowState state, ReturnCtx returnCtx, ApOption returnAp, Ap ap | - revFlow(arg, state, returnCtx, returnAp, ap, config) and - revFlowThroughArg(call, arg, state, returnCtx, returnAp, ap, config) - ) - } - - additional predicate stats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config - ) { - fwd = true and - nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, _, config)) and - fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and - states = count(FlowState state | fwdFlow(_, state, _, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, Cc cc, ParamNodeOption summaryCtx, ApOption argAp, Ap ap | - fwdFlow(n, state, cc, summaryCtx, argAp, ap, config) - ) - or - fwd = false and - nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and - fields = count(TypedContent f0 | consCand(f0, _, config)) and - conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and - states = count(FlowState state | revFlow(_, state, _, _, _, config)) and - tuples = - count(NodeEx n, FlowState state, ReturnCtx returnCtx, ApOption retAp, Ap ap | - revFlow(n, state, returnCtx, retAp, ap, config) - ) - } - /* End: Stage logic. */ - } -} - -private module BooleanCallContext { - class Cc extends boolean { - Cc() { this in [true, false] } - } - - class CcCall extends Cc { - CcCall() { this = true } - } - - /** Holds if the call context may be `call`. */ - predicate matchesCall(CcCall cc, DataFlowCall call) { any() } - - class CcNoCall extends Cc { - CcNoCall() { this = false } - } - - Cc ccNone() { result = false } - - CcCall ccSomeCall() { result = true } - - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() } -} - -private module Level1CallContext { - class Cc = CallContext; - - class CcCall = CallContextCall; - - pragma[inline] - predicate matchesCall(CcCall cc, DataFlowCall call) { cc.matchesCall(call) } - - class CcNoCall = CallContextNoCall; - - Cc ccNone() { result instanceof CallContextAny } - - CcCall ccSomeCall() { result instanceof CallContextSomeCall } - - module NoLocalCallContext { - class LocalCc = Unit; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { any() } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSiteDispatch(call, c) - then result = TSpecificCall(call) - else result = TSomeCall() - } - } - - module LocalCallContext { - class LocalCc = LocalCallContext; - - bindingset[node, cc] - LocalCc getLocalCc(NodeEx node, Cc cc) { - result = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - node.getEnclosingCallable()) - } - - bindingset[call, c, outercc] - CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { - checkCallContextCall(outercc, call, c) and - if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall() - } - } - - bindingset[call, c, innercc] - CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { - checkCallContextReturn(innercc, c, call) and - if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone() - } -} - -private module Stage2Param implements MkStage::StageParam { - private module PrevStage = Stage1; - - class Ap extends boolean { - Ap() { this in [true, false] } - } - - class ApNil extends Ap { - ApNil() { this = false } - } - - bindingset[result, ap] - PrevStage::Ap getApprox(Ap ap) { any() } - - ApNil getApNil(NodeEx node) { Stage1::revFlow(node, _) and exists(result) } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) } - - class ApHeadContent = Unit; - - pragma[inline] - ApHeadContent getHeadContent(Ap ap) { exists(result) and ap = true } - - ApHeadContent projectToHeadContent(Content c) { any() } - - class ApOption = BooleanOption; - - ApOption apNone() { result = TBooleanNone() } - - ApOption apSome(Ap ap) { result = TBooleanSome(ap) } - - import Level1CallContext - import NoLocalCallContext - - bindingset[node1, state1, config] - bindingset[node2, state2, config] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - ( - preservesValue = true and - localFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 - or - preservesValue = false and - additionalLocalStateStep(node1, state1, node2, state2, config) - ) and - exists(ap) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand1/6; - - predicate flowIntoCall = flowIntoCallNodeCand1/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and - expectsContentEx(node, c) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - PrevStage::revFlowState(state, pragma[only_bind_into](config)) and - exists(ap) and - not stateBarrier(node, state, config) and - ( - notExpectsContent(node) - or - ap = true and - expectsContentCand(node, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage2 implements StageSig { - import MkStage::Stage -} - -pragma[nomagic] -private predicate flowOutOfCallNodeCand2( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowOutOfCallNodeCand1(call, node1, kind, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -pragma[nomagic] -private predicate flowIntoCallNodeCand2( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config -) { - flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and - Stage2::revFlow(node2, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node1, pragma[only_bind_into](config)) -} - -private module LocalFlowBigStep { - /** - * A node where some checking is required, and hence the big-step relation - * is not allowed to step over. - */ - private class FlowCheckNode extends NodeEx { - FlowCheckNode() { - castNode(this.asNode()) or - clearsContentCached(this.asNode(), _) or - expectsContentCached(this.asNode(), _) - } - } - - /** - * Holds if `node` can be the first node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) { - Stage2::revFlow(node, state, config) and - ( - sourceNode(node, state, config) - or - jumpStep(_, node, config) - or - additionalJumpStep(_, node, config) - or - additionalJumpStateStep(_, _, node, state, config) - or - node instanceof ParamNodeEx - or - node.asNode() instanceof OutNodeExt - or - Stage2::storeStepCand(_, _, _, node, _, config) - or - Stage2::readStepCand(_, _, node, config) - or - node instanceof FlowCheckNode - or - exists(FlowState s | - additionalLocalStateStep(_, s, node, state, config) and - s != state - ) - ) - } - - /** - * Holds if `node` can be the last node in a maximal subsequence of local - * flow steps in a dataflow path. - */ - private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) { - exists(NodeEx next | Stage2::revFlow(next, state, config) | - jumpStep(node, next, config) or - additionalJumpStep(node, next, config) or - flowIntoCallNodeCand2(_, node, next, _, config) or - flowOutOfCallNodeCand2(_, node, _, next, _, config) or - Stage2::storeStepCand(node, _, _, next, _, config) or - Stage2::readStepCand(node, _, next, config) - ) - or - exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) | - additionalJumpStateStep(node, state, next, s, config) - or - additionalLocalStateStep(node, state, next, s, config) and - s != state - ) - or - Stage2::revFlow(node, state, config) and - node instanceof FlowCheckNode - or - sinkNode(node, state, config) - } - - pragma[noinline] - private predicate additionalLocalFlowStepNodeCand2( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config - ) { - additionalLocalFlowStepNodeCand1(node1, node2, config) and - state1 = state2 and - Stage2::revFlow(node1, pragma[only_bind_into](state1), false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), false, - pragma[only_bind_into](config)) - or - additionalLocalStateStep(node1, state1, node2, state2, config) and - Stage2::revFlow(node1, state1, false, pragma[only_bind_into](config)) and - Stage2::revFlowAlias(node2, state2, false, pragma[only_bind_into](config)) - } - - /** - * Holds if the local path from `node1` to `node2` is a prefix of a maximal - * subsequence of local flow steps in a dataflow path. - * - * This is the transitive closure of `[additional]localFlowStep` beginning - * at `localFlowEntry`. - */ - pragma[nomagic] - private predicate localFlowStepPlus( - NodeEx node1, FlowState state, NodeEx node2, boolean preservesValue, DataFlowType t, - Configuration config, LocalCallContext cc - ) { - not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and - ( - localFlowEntry(node1, pragma[only_bind_into](state), pragma[only_bind_into](config)) and - ( - localFlowStepNodeCand1(node1, node2, config) and - preservesValue = true and - t = node1.getDataFlowType() and // irrelevant dummy value - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - or - additionalLocalFlowStepNodeCand2(node1, state, node2, state, config) and - preservesValue = false and - t = node2.getDataFlowType() - ) and - node1 != node2 and - cc.relevantFor(node1.getEnclosingCallable()) and - not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) - or - exists(NodeEx mid | - localFlowStepPlus(node1, pragma[only_bind_into](state), mid, preservesValue, t, - pragma[only_bind_into](config), cc) and - localFlowStepNodeCand1(mid, node2, config) and - not mid instanceof FlowCheckNode and - Stage2::revFlow(node2, pragma[only_bind_into](state), pragma[only_bind_into](config)) - ) - or - exists(NodeEx mid | - localFlowStepPlus(node1, state, mid, _, _, pragma[only_bind_into](config), cc) and - additionalLocalFlowStepNodeCand2(mid, state, node2, state, config) and - not mid instanceof FlowCheckNode and - preservesValue = false and - t = node2.getDataFlowType() - ) - ) - } - - /** - * Holds if `node1` can step to `node2` in one or more local steps and this - * path can occur as a maximal subsequence of local steps in a dataflow path. - */ - pragma[nomagic] - predicate localFlowBigStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - DataFlowType t, Configuration config, LocalCallContext callContext - ) { - localFlowStepPlus(node1, state1, node2, preservesValue, t, config, callContext) and - localFlowExit(node2, state1, config) and - state1 = state2 - or - additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and - state1 != state2 and - preservesValue = false and - t = node2.getDataFlowType() and - callContext.relevantFor(node1.getEnclosingCallable()) and - not exists(DataFlowCall call | call = callContext.(LocalCallContextSpecificCall).getCall() | - isUnreachableInCallCached(node1.asNode(), call) or - isUnreachableInCallCached(node2.asNode(), call) - ) - } -} - -private import LocalFlowBigStep - -private module Stage3Param implements MkStage::StageParam { - private module PrevStage = Stage2; - - class Ap = ApproxAccessPathFront; - - class ApNil = ApproxAccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TApproxFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getAHead() = tc and exists(tail) } - - class ApHeadContent = ContentApprox; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - predicate projectToHeadContent = getContentApprox/1; - - class ApOption = ApproxAccessPathFrontOption; - - ApOption apNone() { result = TApproxAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TApproxAccessPathFrontSome(ap) } - - import BooleanCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApproxAccessPathFrontNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - exists(lcc) - } - - predicate flowOutOfCall = flowOutOfCallNodeCand2/6; - - predicate flowIntoCall = flowIntoCallNodeCand2/5; - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getAHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage3 implements StageSig { - import MkStage::Stage -} - -private module Stage4Param implements MkStage::StageParam { - private module PrevStage = Stage3; - - class Ap = AccessPathFront; - - class ApNil = AccessPathFrontNil; - - PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathFrontOption; - - ApOption apNone() { result = TAccessPathFrontNone() } - - ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) } - - import BooleanCallContext - - pragma[nomagic] - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, _) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) and - exists(lcc) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clearSet(NodeEx node, ContentSet c, Configuration config) { - PrevStage::revFlow(node, config) and - clearsContentCached(node.asNode(), c) - } - - pragma[nomagic] - private predicate clearContent(NodeEx node, Content c, Configuration config) { - exists(ContentSet cs | - PrevStage::readStepCand(_, pragma[only_bind_into](c), _, pragma[only_bind_into](config)) and - c = cs.getAReadContent() and - clearSet(node, cs, pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - private predicate clear(NodeEx node, Ap ap, Configuration config) { - clearContent(node, ap.getHead().getContent(), config) - } - - pragma[nomagic] - private predicate expectsContentCand(NodeEx node, Ap ap, Configuration config) { - exists(Content c | - PrevStage::revFlow(node, pragma[only_bind_into](config)) and - PrevStage::readStepCand(_, c, _, pragma[only_bind_into](config)) and - expectsContentEx(node, c) and - c = ap.getHead().getContent() - ) - } - - pragma[nomagic] - private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { - exists(state) and - exists(config) and - not clear(node, ap, config) and - (if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()) and - ( - notExpectsContent(node) - or - expectsContentCand(node, ap, config) - ) - } - - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { - // We need to typecheck stores here, since reverse flow through a getter - // might have a different type here compared to inside the getter. - compatibleTypes(ap.getType(), contentType) - } -} - -private module Stage4 implements StageSig { - import MkStage::Stage -} - -/** - * Holds if `argApf` is recorded as the summary context for flow reaching `node` - * and remains relevant for the following pruning stage. - */ -private predicate flowCandSummaryCtx( - NodeEx node, FlowState state, AccessPathFront argApf, Configuration config -) { - exists(AccessPathFront apf | - Stage4::revFlow(node, state, TReturnCtxMaybeFlowThrough(_), _, apf, config) and - Stage4::fwdFlow(node, state, any(Stage4::CcCall ccc), _, TAccessPathFrontSome(argApf), apf, - config) - ) -} - -/** - * Holds if a length 2 access path approximation with the head `tc` is expected - * to be expensive. - */ -private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) { - exists(int tails, int nodes, int apLimit, int tupleLimit | - tails = strictcount(AccessPathFront apf | Stage4::consCand(tc, apf, config)) and - nodes = - strictcount(NodeEx n, FlowState state | - Stage4::revFlow(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - or - flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config) - ) and - accessPathApproxCostLimits(apLimit, tupleLimit) and - apLimit < tails and - tupleLimit < (tails - 1) * nodes and - not tc.forceHighPrecision() - ) -} - -private newtype TAccessPathApprox = - TNil(DataFlowType t) or - TConsNil(TypedContent tc, DataFlowType t) { - Stage4::consCand(tc, TFrontNil(t), _) and - not expensiveLen2unfolding(tc, _) - } or - TConsCons(TypedContent tc1, TypedContent tc2, int len) { - Stage4::consCand(tc1, TFrontHead(tc2), _) and - len in [2 .. accessPathLimit()] and - not expensiveLen2unfolding(tc1, _) - } or - TCons1(TypedContent tc, int len) { - len in [1 .. accessPathLimit()] and - expensiveLen2unfolding(tc, _) - } - -/** - * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only - * the first two elements of the list and its length are tracked. If data flows - * from a source to a given node with a given `AccessPathApprox`, this indicates - * the sequence of dereference operations needed to get from the value in the node - * to the tracked object. The final type indicates the type of the tracked object. - */ -abstract private class AccessPathApprox extends TAccessPathApprox { - abstract string toString(); - - abstract TypedContent getHead(); - - abstract int len(); - - abstract DataFlowType getType(); - - abstract AccessPathFront getFront(); - - /** Gets the access path obtained by popping `head` from this path, if any. */ - abstract AccessPathApprox pop(TypedContent head); -} - -private class AccessPathApproxNil extends AccessPathApprox, TNil { - private DataFlowType t; - - AccessPathApproxNil() { this = TNil(t) } - - override string toString() { result = concat(": " + ppReprType(t)) } - - override TypedContent getHead() { none() } - - override int len() { result = 0 } - - override DataFlowType getType() { result = t } - - override AccessPathFront getFront() { result = TFrontNil(t) } - - override AccessPathApprox pop(TypedContent head) { none() } -} - -abstract private class AccessPathApproxCons extends AccessPathApprox { } - -private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil { - private TypedContent tc; - private DataFlowType t; - - AccessPathApproxConsNil() { this = TConsNil(tc, t) } - - override string toString() { - // The `concat` becomes "" if `ppReprType` has no result. - result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t)) - } - - override TypedContent getHead() { result = tc } - - override int len() { result = 1 } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) } -} - -private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons { - private TypedContent tc1; - private TypedContent tc2; - private int len; - - AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) } - - override string toString() { - if len = 2 - then result = "[" + tc1.toString() + ", " + tc2.toString() + "]" - else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc1 } - - override int len() { result = len } - - override DataFlowType getType() { result = tc1.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc1) } - - override AccessPathApprox pop(TypedContent head) { - head = tc1 and - ( - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - } -} - -private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 { - private TypedContent tc; - private int len; - - AccessPathApproxCons1() { this = TCons1(tc, len) } - - override string toString() { - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - } - - override TypedContent getHead() { result = tc } - - override int len() { result = len } - - override DataFlowType getType() { result = tc.getContainerType() } - - override AccessPathFront getFront() { result = TFrontHead(tc) } - - override AccessPathApprox pop(TypedContent head) { - head = tc and - ( - exists(TypedContent tc2 | Stage4::consCand(tc, TFrontHead(tc2), _) | - result = TConsCons(tc2, _, len - 1) - or - len = 2 and - result = TConsNil(tc2, _) - or - result = TCons1(tc2, len - 1) - ) - or - exists(DataFlowType t | - len = 1 and - Stage4::consCand(tc, TFrontNil(t), _) and - result = TNil(t) - ) - ) - } -} - -/** Gets the access path obtained by popping `tc` from `ap`, if any. */ -private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) } - -/** Gets the access path obtained by pushing `tc` onto `ap`. */ -private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) } - -private newtype TAccessPathApproxOption = - TAccessPathApproxNone() or - TAccessPathApproxSome(AccessPathApprox apa) - -private class AccessPathApproxOption extends TAccessPathApproxOption { - string toString() { - this = TAccessPathApproxNone() and result = "" - or - this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString())) - } -} - -private module Stage5Param implements MkStage::StageParam { - private module PrevStage = Stage4; - - class Ap = AccessPathApprox; - - class ApNil = AccessPathApproxNil; - - pragma[nomagic] - PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() } - - ApNil getApNil(NodeEx node) { - PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType()) - } - - bindingset[tc, tail] - Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) } - - class ApHeadContent = Content; - - pragma[noinline] - ApHeadContent getHeadContent(Ap ap) { result = ap.getHead().getContent() } - - ApHeadContent projectToHeadContent(Content c) { result = c } - - class ApOption = AccessPathApproxOption; - - ApOption apNone() { result = TAccessPathApproxNone() } - - ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) } - - import Level1CallContext - import LocalCallContext - - predicate localStep( - NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue, - ApNil ap, Configuration config, LocalCc lcc - ) { - localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getType(), config, lcc) and - PrevStage::revFlow(node1, pragma[only_bind_into](state1), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node2, pragma[only_bind_into](state2), _, pragma[only_bind_into](config)) - } - - pragma[nomagic] - predicate flowOutOfCall( - DataFlowCall call, RetNodeEx node1, ReturnKindExt kind, NodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowOutOfCallNodeCand2(call, node1, kind, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - pragma[nomagic] - predicate flowIntoCall( - DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow, - Configuration config - ) { - exists(FlowState state | - flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and - PrevStage::revFlow(node2, pragma[only_bind_into](state), _, pragma[only_bind_into](config)) and - PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, - pragma[only_bind_into](config)) - ) - } - - bindingset[node, state, ap, config] - predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() } - - // Type checking is not necessary here as it has already been done in stage 3. - bindingset[ap, contentType] - predicate typecheckStore(Ap ap, DataFlowType contentType) { any() } -} - -private module Stage5 = MkStage::Stage; - -bindingset[conf, result] -private Configuration unbindConf(Configuration conf) { - exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c)) -} - -pragma[nomagic] -private predicate nodeMayUseSummary0( - NodeEx n, ParamNodeEx p, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(AccessPathApprox apa0 | - Stage5::parameterMayFlowThrough(p, _, _) and - Stage5::revFlow(n, state, TReturnCtxMaybeFlowThrough(_), _, apa0, config) and - Stage5::fwdFlow(n, state, any(CallContextCall ccc), TParamNodeSome(p.asNode()), - TAccessPathApproxSome(apa), apa0, config) - ) -} - -pragma[nomagic] -private predicate nodeMayUseSummary( - NodeEx n, FlowState state, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::parameterMayFlowThrough(p, apa, config) and - nodeMayUseSummary0(n, p, state, apa, config) - ) -} - -private newtype TSummaryCtx = - TSummaryCtxNone() or - TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) { - exists(Configuration config | - Stage5::parameterMayFlowThrough(p, ap.getApprox(), config) and - Stage5::revFlow(p, state, _, config) - ) - } - -/** - * A context for generating flow summaries. This represents flow entry through - * a specific parameter with an access path of a specific shape. - * - * Summaries are only created for parameters that may flow through. - */ -abstract private class SummaryCtx extends TSummaryCtx { - abstract string toString(); -} - -/** A summary context from which no flow summary can be generated. */ -private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone { - override string toString() { result = "" } -} - -/** A summary context from which a flow summary can be generated. */ -private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome { - private ParamNodeEx p; - private FlowState s; - private AccessPath ap; - - SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) } - - ParameterPosition getParameterPos() { p.isParameterOf(_, result) } - - ParamNodeEx getParamNode() { result = p } - - override string toString() { result = p + ": " + ap } - - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * Gets the number of length 2 access path approximations that correspond to `apa`. - */ -private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) { - exists(TypedContent tc, int len | - tc = apa.getHead() and - len = apa.len() and - result = - strictcount(AccessPathFront apf | - Stage5::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1), - config) - ) - ) -} - -private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) { - result = - strictcount(NodeEx n, FlowState state | - Stage5::revFlow(n, state, apa, config) or nodeMayUseSummary(n, state, apa, config) - ) -} - -/** - * Holds if a length 2 access path approximation matching `apa` is expected - * to be expensive. - */ -private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) { - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = count1to2unfold(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - apLimit < aps and - tupleLimit < (aps - 1) * nodes - ) -} - -private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) { - exists(TypedContent head | - apa.pop(head) = result and - Stage5::consCand(head, result, config) - ) -} - -/** - * Holds with `unfold = false` if a precise head-tail representation of `apa` is - * expected to be expensive. Holds with `unfold = true` otherwise. - */ -private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) { - if apa.getHead().forceHighPrecision() - then unfold = true - else - exists(int aps, int nodes, int apLimit, int tupleLimit | - aps = countPotentialAps(apa, config) and - nodes = countNodesUsingAccessPath(apa, config) and - accessPathCostLimits(apLimit, tupleLimit) and - if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true - ) -} - -/** - * Gets the number of `AccessPath`s that correspond to `apa`. - */ -pragma[assume_small_delta] -private int countAps(AccessPathApprox apa, Configuration config) { - evalUnfold(apa, false, config) and - result = 1 and - (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config)) - or - evalUnfold(apa, false, config) and - result = count1to2unfold(apa, config) and - not expensiveLen1to2unfolding(apa, config) - or - evalUnfold(apa, true, config) and - result = countPotentialAps(apa, config) -} - -/** - * Gets the number of `AccessPath`s that would correspond to `apa` assuming - * that it is expanded to a precise head-tail representation. - */ -language[monotonicAggregates] -pragma[assume_small_delta] -private int countPotentialAps(AccessPathApprox apa, Configuration config) { - apa instanceof AccessPathApproxNil and result = 1 - or - result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config)) -} - -private newtype TAccessPath = - TAccessPathNil(DataFlowType t) or - TAccessPathCons(TypedContent head, AccessPath tail) { - exists(AccessPathApproxCons apa | - not evalUnfold(apa, false, _) and - head = apa.getHead() and - tail.getApprox() = getATail(apa, _) - ) - } or - TAccessPathCons2(TypedContent head1, TypedContent head2, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - not expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head1 = apa.getHead() and - head2 = getATail(apa, _).getHead() - ) - } or - TAccessPathCons1(TypedContent head, int len) { - exists(AccessPathApproxCons apa | - evalUnfold(apa, false, _) and - expensiveLen1to2unfolding(apa, _) and - apa.len() = len and - head = apa.getHead() - ) - } - -private newtype TPathNode = - pragma[assume_small_delta] - TPathNodeMid( - NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config - ) { - // A PathNode is introduced by a source ... - Stage5::revFlow(node, state, config) and - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - or - // ... or a step from an existing PathNode to another node. - exists(PathNodeMid mid | - pathStep(mid, node, state, cc, sc, ap) and - pragma[only_bind_into](config) = mid.getConfiguration() and - Stage5::revFlow(node, state, ap.getApprox(), pragma[only_bind_into](config)) - ) - } or - TPathNodeSink(NodeEx node, FlowState state, Configuration config) { - exists(PathNodeMid sink | - sink.isAtSink() and - node = sink.getNodeEx() and - state = sink.getState() and - config = sink.getConfiguration() - ) - } or - TPathNodeSourceGroup(string sourceGroup, Configuration config) { - exists(PathNodeImpl source | - sourceGroup = source.getSourceGroup() and - config = source.getConfiguration() - ) - } or - TPathNodeSinkGroup(string sinkGroup, Configuration config) { - exists(PathNodeSink sink | - sinkGroup = sink.getSinkGroup() and - config = sink.getConfiguration() - ) - } - -/** - * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a - * source to a given node with a given `AccessPath`, this indicates the sequence - * of dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ -private class AccessPath extends TAccessPath { - /** Gets the head of this access path, if any. */ - abstract TypedContent getHead(); - - /** Gets the tail of this access path, if any. */ - abstract AccessPath getTail(); - - /** Gets the front of this access path. */ - abstract AccessPathFront getFront(); - - /** Gets the approximation of this access path. */ - abstract AccessPathApprox getApprox(); - - /** Gets the length of this access path. */ - abstract int length(); - - /** Gets a textual representation of this access path. */ - abstract string toString(); - - /** Gets the access path obtained by popping `tc` from this access path, if any. */ - final AccessPath pop(TypedContent tc) { - result = this.getTail() and - tc = this.getHead() - } - - /** Gets the access path obtained by pushing `tc` onto this access path. */ - final AccessPath push(TypedContent tc) { this = result.pop(tc) } -} - -private class AccessPathNil extends AccessPath, TAccessPathNil { - private DataFlowType t; - - AccessPathNil() { this = TAccessPathNil(t) } - - DataFlowType getType() { result = t } - - override TypedContent getHead() { none() } - - override AccessPath getTail() { none() } - - override AccessPathFrontNil getFront() { result = TFrontNil(t) } - - override AccessPathApproxNil getApprox() { result = TNil(t) } - - override int length() { result = 0 } - - override string toString() { result = concat(": " + ppReprType(t)) } -} - -private class AccessPathCons extends AccessPath, TAccessPathCons { - private TypedContent head; - private AccessPath tail; - - AccessPathCons() { this = TAccessPathCons(head, tail) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { result = tail } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - pragma[assume_small_delta] - override AccessPathApproxCons getApprox() { - result = TConsNil(head, tail.(AccessPathNil).getType()) - or - result = TConsCons(head, tail.getHead(), this.length()) - or - result = TCons1(head, this.length()) - } - - pragma[assume_small_delta] - override int length() { result = 1 + tail.length() } - - private string toStringImpl(boolean needsSuffix) { - exists(DataFlowType t | - tail = TAccessPathNil(t) and - needsSuffix = false and - result = head.toString() + "]" + concat(" : " + ppReprType(t)) - ) - or - result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix) - or - exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) | - result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true - or - result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false - ) - or - exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) | - result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true - or - result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false - ) - } - - override string toString() { - result = "[" + this.toStringImpl(true) + this.length().toString() + ")]" - or - result = "[" + this.toStringImpl(false) - } -} - -private class AccessPathCons2 extends AccessPath, TAccessPathCons2 { - private TypedContent head1; - private TypedContent head2; - private int len; - - AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) } - - override TypedContent getHead() { result = head1 } - - override AccessPath getTail() { - Stage5::consCand(head1, result.getApprox(), _) and - result.getHead() = head2 and - result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head1) } - - override AccessPathApproxCons getApprox() { - result = TConsCons(head1, head2, len) or - result = TCons1(head1, len) - } - - override int length() { result = len } - - override string toString() { - if len = 2 - then result = "[" + head1.toString() + ", " + head2.toString() + "]" - else - result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]" - } -} - -private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { - private TypedContent head; - private int len; - - AccessPathCons1() { this = TAccessPathCons1(head, len) } - - override TypedContent getHead() { result = head } - - override AccessPath getTail() { - Stage5::consCand(head, result.getApprox(), _) and result.length() = len - 1 - } - - override AccessPathFrontHead getFront() { result = TFrontHead(head) } - - override AccessPathApproxCons getApprox() { result = TCons1(head, len) } - - override int length() { result = len } - - override string toString() { - if len = 1 - then result = "[" + head.toString() + "]" - else result = "[" + head.toString() + ", ... (" + len.toString() + ")]" - } -} - -abstract private class PathNodeImpl extends TPathNode { - /** Gets the `FlowState` of this node. */ - abstract FlowState getState(); - - /** Gets the associated configuration. */ - abstract Configuration getConfiguration(); - - /** Holds if this node is a source. */ - abstract predicate isSource(); - - abstract PathNodeImpl getASuccessorImpl(); - - private PathNodeImpl getASuccessorIfHidden() { - this.isHidden() and - result = this.getASuccessorImpl() - } - - pragma[nomagic] - private PathNodeImpl getANonHiddenSuccessor0() { - result = this.getASuccessorIfHidden*() and - not result.isHidden() - } - - final PathNodeImpl getANonHiddenSuccessor() { - result = this.getASuccessorImpl().getANonHiddenSuccessor0() and - not this.isHidden() - } - - abstract NodeEx getNodeEx(); - - predicate isHidden() { - not this.getConfiguration().includeHiddenNodes() and - ( - hiddenNode(this.getNodeEx().asNode()) and - not this.isSource() and - not this instanceof PathNodeSink - or - this.getNodeEx() instanceof TNodeImplicitRead - ) - } - - string getSourceGroup() { - this.isSource() and - this.getConfiguration().sourceGrouping(this.getNodeEx().asNode(), result) - } - - predicate isFlowSource() { - this.isSource() and not exists(this.getSourceGroup()) - or - this instanceof PathNodeSourceGroup - } - - predicate isFlowSink() { - this = any(PathNodeSink sink | not exists(sink.getSinkGroup())) or - this instanceof PathNodeSinkGroup - } - - private string ppAp() { - this instanceof PathNodeSink and result = "" - or - exists(string s | s = this.(PathNodeMid).getAp().toString() | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - this instanceof PathNodeSink and result = "" - or - result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** Holds if `n` can reach a sink. */ -private predicate directReach(PathNodeImpl n) { - n instanceof PathNodeSink or - n instanceof PathNodeSinkGroup or - directReach(n.getANonHiddenSuccessor()) -} - -/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } - -/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { - n1.getANonHiddenSuccessor() = n2 and directReach(n2) -} - -private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) - -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. - */ -class PathNode instanceof PathNodeImpl { - PathNode() { reach(this) } - - /** Gets a textual representation of this element. */ - final string toString() { result = super.toString() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - final string toStringWithContext() { result = super.toStringWithContext() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - final predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { super.getNodeEx().projectToNode() = result } - - /** Gets the `FlowState` of this node. */ - final FlowState getState() { result = super.getState() } - - /** Gets the associated configuration. */ - final Configuration getConfiguration() { result = super.getConfiguration() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } - - /** Holds if this node is a source. */ - final predicate isSource() { super.isSource() } - - /** Holds if this node is a grouping of source nodes. */ - final predicate isSourceGroup(string group) { this = TPathNodeSourceGroup(group, _) } - - /** Holds if this node is a grouping of sink nodes. */ - final predicate isSinkGroup(string group) { this = TPathNodeSinkGroup(group, _) } -} - -/** - * Provides the query predicates needed to include a graph in a path-problem query. - */ -module PathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b } - - /** Holds if `n` is a node in the graph of data flow path explanations. */ - query predicate nodes(PathNode n, string key, string val) { - key = "semmle.label" and val = n.toString() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) - } -} - -/** - * An intermediate flow graph node. This is a triple consisting of a `Node`, - * a `CallContext`, and a `Configuration`. - */ -private class PathNodeMid extends PathNodeImpl, TPathNodeMid { - NodeEx node; - FlowState state; - CallContext cc; - SummaryCtx sc; - AccessPath ap; - Configuration config; - - PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - SummaryCtx getSummaryCtx() { result = sc } - - AccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - private PathNodeMid getSuccMid() { - pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx(), result.getAp()) and - result.getConfiguration() = unbindConf(this.getConfiguration()) - } - - override PathNodeImpl getASuccessorImpl() { - // an intermediate step to another intermediate node - result = this.getSuccMid() - or - // a final step to a sink - result = this.getSuccMid().projectToSink() - } - - override predicate isSource() { - sourceNode(node, state, config) and - ( - if hasSourceCallCtx(config) - then cc instanceof CallContextSomeCall - else cc instanceof CallContextAny - ) and - sc instanceof SummaryCtxNone and - ap = TAccessPathNil(node.getDataFlowType()) - } - - predicate isAtSink() { - sinkNode(node, state, config) and - ap instanceof AccessPathNil and - if hasSinkCallCtx(config) - then - // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall` - // is exactly what we need to check. This also implies - // `sc instanceof SummaryCtxNone`. - // For `FeatureEqualSourceSinkCallContext` the initial call context was - // set to `CallContextSomeCall` and jumps are disallowed, so - // `cc instanceof CallContextNoCall` never holds. On the other hand, - // in this case there's never any need to enter a call except to identify - // a summary, so the condition in `pathIntoCallable` enforces this, which - // means that `sc instanceof SummaryCtxNone` holds if and only if we are - // in the call context of the source. - sc instanceof SummaryCtxNone or - cc instanceof CallContextNoCall - else any() - } - - PathNodeSink projectToSink() { - this.isAtSink() and - result.getNodeEx() = node and - result.getState() = state and - result.getConfiguration() = unbindConf(config) - } -} - -/** - * A flow graph node corresponding to a sink. This is disjoint from the - * intermediate nodes in order to uniquely correspond to a given sink by - * excluding the `CallContext`. - */ -private class PathNodeSink extends PathNodeImpl, TPathNodeSink { - NodeEx node; - FlowState state; - Configuration config; - - PathNodeSink() { this = TPathNodeSink(node, state, config) } - - override NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result = TPathNodeSinkGroup(this.getSinkGroup(), config) - } - - override predicate isSource() { sourceNode(node, state, config) } - - string getSinkGroup() { config.sinkGrouping(node.asNode(), result) } -} - -private class PathNodeSourceGroup extends PathNodeImpl, TPathNodeSourceGroup { - string sourceGroup; - Configuration config; - - PathNodeSourceGroup() { this = TPathNodeSourceGroup(sourceGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { - result.getSourceGroup() = sourceGroup and - result.getConfiguration() = config - } - - override predicate isSource() { none() } - - override string toString() { result = sourceGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private class PathNodeSinkGroup extends PathNodeImpl, TPathNodeSinkGroup { - string sinkGroup; - Configuration config; - - PathNodeSinkGroup() { this = TPathNodeSinkGroup(sinkGroup, config) } - - override NodeEx getNodeEx() { none() } - - override FlowState getState() { none() } - - override Configuration getConfiguration() { result = config } - - override PathNodeImpl getASuccessorImpl() { none() } - - override predicate isSource() { none() } - - override string toString() { result = sinkGroup } - - override predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - filepath = "" and startline = 0 and startcolumn = 0 and endline = 0 and endcolumn = 0 - } -} - -private predicate pathNode( - PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, - Configuration conf, LocalCallContext localCC -) { - midnode = mid.getNodeEx() and - state = mid.getState() and - conf = mid.getConfiguration() and - cc = mid.getCallContext() and - sc = mid.getSummaryCtx() and - localCC = - getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)), - midnode.getEnclosingCallable()) and - ap = mid.getAp() -} - -/** - * Holds if data may flow from `mid` to `node`. The last step in or out of - * a callable is recorded by `cc`. - */ -pragma[assume_small_delta] -pragma[nomagic] -private predicate pathStep( - PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap -) { - exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC | - pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC) - ) - or - exists( - AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC - | - pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and - localFlowBigStep(midnode, state0, node, state, false, ap.(AccessPathNil).getType(), conf, - localCC) and - ap0 instanceof AccessPathNil - ) - or - jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - ap = mid.getAp() - or - additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and - state = mid.getState() and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and - cc instanceof CallContextAny and - sc instanceof SummaryCtxNone and - mid.getAp() instanceof AccessPathNil and - ap = TAccessPathNil(node.getDataFlowType()) - or - exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and - sc = mid.getSummaryCtx() - or - pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp() - or - pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone - or - pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx() -} - -pragma[nomagic] -private predicate pathReadStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - tc = ap0.getHead() and - Stage5::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -pragma[nomagic] -private predicate pathStoreStep( - PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc -) { - ap0 = mid.getAp() and - Stage5::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and - state = mid.getState() and - cc = mid.getCallContext() -} - -private predicate pathOutOfCallable0( - PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa, - Configuration config -) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - apa = mid.getAp().getApprox() and - config = mid.getConfiguration() -} - -pragma[nomagic] -private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPathApprox apa, Configuration config -) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - pathOutOfCallable0(mid, pos, state, innercc, apa, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) -} - -pragma[noinline] -private NodeEx getAnOutNodeFlow( - ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config -) { - result.asNode() = kind.getAnOutNode(call) and - Stage5::revFlow(result, _, apa, config) -} - -/** - * Holds if data may flow from `mid` to `out`. The last step of this path - * is a return from a callable and is recorded by `cc`, if needed. - */ -pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) { - exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config | - pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`. - */ -pragma[noinline] -private predicate pathIntoArg( - PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(ArgNodeEx arg, ArgumentPosition apos | - pathNode(mid, arg, state, cc, _, ap, config, _) and - arg.asNode().(ArgNode).argumentOf(call, apos) and - apa = ap.getApprox() and - parameterMatch(ppos, apos) - ) -} - -pragma[nomagic] -private predicate parameterCand( - DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config -) { - exists(ParamNodeEx p | - Stage5::revFlow(p, _, apa, config) and - p.isParameterOf(callable, pos) - ) -} - -pragma[nomagic] -private predicate pathIntoCallable0( - PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config -) { - exists(AccessPathApprox apa | - pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap, - pragma[only_bind_into](apa), pragma[only_bind_into](config)) and - callable = resolveCall(call, outercc) and - parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa), - pragma[only_bind_into](config)) - ) -} - -/** - * Holds if data may flow from `mid` to `p` through `call`. The contexts - * before and after entering the callable are `outercc` and `innercc`, - * respectively. - */ -pragma[nomagic] -private predicate pathIntoCallable( - PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc, - SummaryCtx sc, DataFlowCall call, Configuration config -) { - exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap | - pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - ( - sc = TSummaryCtxSome(p, state, ap) - or - not exists(TSummaryCtxSome(p, state, ap)) and - sc = TSummaryCtxNone() and - // When the call contexts of source and sink needs to match then there's - // never any reason to enter a callable except to find a summary. See also - // the comment in `PathNodeMid::isAtSink`. - not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext - ) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) -} - -/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */ -pragma[nomagic] -private predicate paramFlowsThrough( - ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, - AccessPathApprox apa, Configuration config -) { - exists(RetNodeEx ret | - pathNode(_, ret, state, cc, sc, ap, config, _) and - kind = ret.getKind() and - apa = ap.getApprox() and - parameterFlowThroughAllowed(sc.getParamNode(), kind) - ) -} - -pragma[nomagic] -private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc, - AccessPath ap, AccessPathApprox apa, Configuration config -) { - exists(CallContext innercc, SummaryCtx sc | - pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and - paramFlowsThrough(kind, state, innercc, sc, ap, apa, config) - ) -} - -/** - * Holds if data may flow from `mid` through a callable to the node `out`. - * The context `cc` is restored to its value prior to entering the callable. - */ -pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap -) { - exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config | - pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and - out = getAnOutNodeFlow(kind, call, apa, config) - ) -} - -private module Subpaths { - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths01( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - exists(Configuration config | - pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and - pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and - paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc, - pragma[only_bind_into](apout), _, unbindConf(config)) and - not arg.isHidden() - ) - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by - * `kind`, `sc`, `sout`, `apout`, and `innercc`. - */ - pragma[nomagic] - private predicate subpaths02( - PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, - NodeEx out, FlowState sout, AccessPath apout - ) { - subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and - out.asNode() = kind.getAnOutNode(_) - } - - pragma[nomagic] - private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple. - */ - pragma[nomagic] - private predicate subpaths03( - PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout - ) { - exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | - subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and - pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and - kind = retnode.getKind() - ) - } - - private PathNodeImpl localStepToHidden(PathNodeImpl n) { - n.getASuccessorImpl() = result and - result.isHidden() and - exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() | - localFlowBigStep(n1, _, n2, _, _, _, _, _) or - store(n1, _, n2, _, _) or - readSet(n1, _, n2, _) - ) - } - - pragma[nomagic] - private predicate hasSuccessor(PathNodeImpl pred, PathNodeMid succ, NodeEx succNode) { - succ = pred.getANonHiddenSuccessor() and - succNode = succ.getNodeEx() - } - - /** - * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through - * a subpath between `par` and `ret` with the connecting edges `arg -> par` and - * `ret -> out` is summarized as the edge `arg -> out`. - */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { - exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | - pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and - subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and - hasSuccessor(pragma[only_bind_into](arg), par, p) and - not ret.isHidden() and - pathNode(out0, o, sout, _, _, apout, _, _) - | - out = out0 or out = out0.projectToSink() - ) - } - - /** - * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. - */ - predicate retReach(PathNodeImpl n) { - exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) - or - exists(PathNodeImpl mid | - retReach(mid) and - n.getANonHiddenSuccessor() = mid and - not subpaths(_, mid, _, _) - ) - } -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -private predicate hasFlowPath( - PathNodeImpl flowsource, PathNodeImpl flowsink, Configuration configuration -) { - flowsource.isFlowSource() and - flowsource.getConfiguration() = configuration and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.isFlowSink() -} - -private predicate flowsTo( - PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, - Configuration configuration -) { - flowsource.isSource() and - flowsource.getConfiguration() = configuration and - flowsource.getNodeEx().asNode() = source and - (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and - flowsink.getNodeEx().asNode() = sink -} - -/** - * Holds if data can flow (inter-procedurally) from `source` to `sink`. - * - * Will only have results if `configuration` has non-empty sources and - * sinks. - */ -predicate flowsTo(Node source, Node sink, Configuration configuration) { - flowsTo(_, _, source, sink, configuration) -} - -private predicate finalStats( - boolean fwd, int nodes, int fields, int conscand, int states, int tuples -) { - fwd = true and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNodeImpl pn) - or - fwd = false and - nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and - fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and - conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and - states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn) -} - -/** - * INTERNAL: Only for debugging. - * - * Calculates per-stage metrics for data flow. - */ -predicate stageStats( - int n, string stage, int nodes, int fields, int conscand, int states, int tuples, - Configuration config -) { - stage = "1 Fwd" and - n = 10 and - Stage1::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "1 Rev" and - n = 15 and - Stage1::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Fwd" and - n = 20 and - Stage2::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "2 Rev" and - n = 25 and - Stage2::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Fwd" and - n = 30 and - Stage3::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "3 Rev" and - n = 35 and - Stage3::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Fwd" and - n = 40 and - Stage4::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "4 Rev" and - n = 45 and - Stage4::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Fwd" and - n = 50 and - Stage5::stats(true, nodes, fields, conscand, states, tuples, config) - or - stage = "5 Rev" and - n = 55 and - Stage5::stats(false, nodes, fields, conscand, states, tuples, config) - or - stage = "6 Fwd" and n = 60 and finalStats(true, nodes, fields, conscand, states, tuples) - or - stage = "6 Rev" and n = 65 and finalStats(false, nodes, fields, conscand, states, tuples) -} - -private module FlowExploration { - private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) { - exists(NodeEx node1, NodeEx node2 | - jumpStep(node1, node2, config) - or - additionalJumpStep(node1, node2, config) - or - additionalJumpStateStep(node1, _, node2, _, config) - or - // flow into callable - viableParamArgEx(_, node2, node1) - or - // flow out of a callable - viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2) - | - c1 = node1.getEnclosingCallable() and - c2 = node2.getEnclosingCallable() and - c1 != c2 - ) - } - - private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSrc(mid, config) and callableStep(mid, c, config) - ) - } - - private predicate interestingCallableSink(DataFlowCallable c, Configuration config) { - exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n)) - or - exists(DataFlowCallable mid | - interestingCallableSink(mid, config) and callableStep(c, mid, config) - ) - } - - private newtype TCallableExt = - TCallable(DataFlowCallable c, Configuration config) { - interestingCallableSrc(c, config) or - interestingCallableSink(c, config) - } or - TCallableSrc() or - TCallableSink() - - private predicate callableExtSrc(TCallableSrc src) { any() } - - private predicate callableExtSink(TCallableSink sink) { any() } - - private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) { - exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config | - callableStep(c1, c2, config) and - ce1 = TCallable(c1, pragma[only_bind_into](config)) and - ce2 = TCallable(c2, pragma[only_bind_into](config)) - ) - or - exists(Node n, Configuration config | - ce1 = TCallableSrc() and - (config.isSource(n) or config.isSource(n, _)) and - ce2 = TCallable(getNodeEnclosingCallable(n), config) - ) - or - exists(Node n, Configuration config | - ce2 = TCallableSink() and - (config.isSink(n) or config.isSink(n, _)) and - ce1 = TCallable(getNodeEnclosingCallable(n), config) - ) - } - - private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) { - callableExtStepFwd(ce2, ce1) - } - - private int distSrcExt(TCallableExt c) = - shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result) - - private int distSinkExt(TCallableExt c) = - shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result) - - private int distSrc(DataFlowCallable c, Configuration config) { - result = distSrcExt(TCallable(c, config)) - 1 - } - - private int distSink(DataFlowCallable c, Configuration config) { - result = distSinkExt(TCallable(c, config)) - 1 - } - - private newtype TPartialAccessPath = - TPartialNil(DataFlowType t) or - TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first - * element of the list and its length are tracked. If data flows from a source to - * a given node with a given `AccessPath`, this indicates the sequence of - * dereference operations needed to get from the value in the node to the - * tracked object. The final type indicates the type of the tracked object. - */ - private class PartialAccessPath extends TPartialAccessPath { - abstract string toString(); - - TypedContent getHead() { this = TPartialCons(result, _) } - - int len() { - this = TPartialNil(_) and result = 0 - or - this = TPartialCons(_, result) - } - - DataFlowType getType() { - this = TPartialNil(result) - or - exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType()) - } - } - - private class PartialAccessPathNil extends PartialAccessPath, TPartialNil { - override string toString() { - exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t))) - } - } - - private class PartialAccessPathCons extends PartialAccessPath, TPartialCons { - override string toString() { - exists(TypedContent tc, int len | this = TPartialCons(tc, len) | - if len = 1 - then result = "[" + tc.toString() + "]" - else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private newtype TRevPartialAccessPath = - TRevPartialNil() or - TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] } - - /** - * Conceptually a list of `Content`s, but only the first - * element of the list and its length are tracked. - */ - private class RevPartialAccessPath extends TRevPartialAccessPath { - abstract string toString(); - - Content getHead() { this = TRevPartialCons(result, _) } - - int len() { - this = TRevPartialNil() and result = 0 - or - this = TRevPartialCons(_, result) - } - } - - private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil { - override string toString() { result = "" } - } - - private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons { - override string toString() { - exists(Content c, int len | this = TRevPartialCons(c, len) | - if len = 1 - then result = "[" + c.toString() + "]" - else result = "[" + c.toString() + ", ... (" + len.toString() + ")]" - ) - } - } - - private predicate relevantState(FlowState state) { - sourceNode(_, state, _) or - sinkNode(_, state, _) or - additionalLocalStateStep(_, state, _, _, _) or - additionalLocalStateStep(_, _, _, state, _) or - additionalJumpStateStep(_, state, _, _, _) or - additionalJumpStateStep(_, _, _, state, _) - } - - private newtype TSummaryCtx1 = - TSummaryCtx1None() or - TSummaryCtx1Param(ParamNodeEx p) - - private newtype TSummaryCtx2 = - TSummaryCtx2None() or - TSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TSummaryCtx3 = - TSummaryCtx3None() or - TSummaryCtx3Some(PartialAccessPath ap) - - private newtype TRevSummaryCtx1 = - TRevSummaryCtx1None() or - TRevSummaryCtx1Some(ReturnPosition pos) - - private newtype TRevSummaryCtx2 = - TRevSummaryCtx2None() or - TRevSummaryCtx2Some(FlowState s) { relevantState(s) } - - private newtype TRevSummaryCtx3 = - TRevSummaryCtx3None() or - TRevSummaryCtx3Some(RevPartialAccessPath ap) - - private newtype TPartialPathNode = - TPartialPathNodeFwd( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = TPartialNil(node.getDataFlowType()) and - exists(config.explorationLimit()) - or - partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and - distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit() - } or - TPartialPathNodeRev( - NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3, - RevPartialAccessPath ap, Configuration config - ) { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() and - exists(config.explorationLimit()) - or - revPartialPathStep(_, node, state, sc1, sc2, sc3, ap, config) and - not clearsContentEx(node, ap.getHead()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead()) - ) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - distSink(node.getEnclosingCallable(), config) <= config.explorationLimit() - } - - pragma[nomagic] - private predicate partialPathNodeMk0( - NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - partialPathStep(_, node, state, cc, sc1, sc2, sc3, ap, config) and - not fullBarrier(node, config) and - not stateBarrier(node, state, config) and - not clearsContentEx(node, ap.getHead().getContent()) and - ( - notExpectsContent(node) or - expectsContentEx(node, ap.getHead().getContent()) - ) and - if node.asNode() instanceof CastingNode - then compatibleTypes(node.getDataFlowType(), ap.getType()) - else any() - } - - /** - * A `Node` augmented with a call context, an access path, and a configuration. - */ - class PartialPathNode extends TPartialPathNode { - /** Gets a textual representation of this element. */ - string toString() { result = this.getNodeEx().toString() + this.ppAp() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.getNodeEx().projectToNode() = result } - - FlowState getState() { none() } - - private NodeEx getNodeEx() { - result = this.(PartialPathNodeFwd).getNodeEx() or - result = this.(PartialPathNodeRev).getNodeEx() - } - - /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - PartialPathNode getASuccessor() { none() } - - /** - * Gets the approximate distance to the nearest source measured in number - * of interprocedural steps. - */ - int getSourceDistance() { - result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - /** - * Gets the approximate distance to the nearest sink measured in number - * of interprocedural steps. - */ - int getSinkDistance() { - result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration()) - } - - private string ppAp() { - exists(string s | - s = this.(PartialPathNodeFwd).getAp().toString() or - s = this.(PartialPathNodeRev).getAp().toString() - | - if s = "" then result = "" else result = " " + s - ) - } - - private string ppCtx() { - result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">" - } - - /** Holds if this is a source in a forward-flow path. */ - predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() } - - /** Holds if this is a sink in a reverse-flow path. */ - predicate isRevSink() { this.(PartialPathNodeRev).isSink() } - } - - /** - * Provides the query predicates needed to include a graph in a path-problem query. - */ - module PartialPathGraph { - /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */ - query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b } - } - - private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd { - NodeEx node; - FlowState state; - CallContext cc; - TSummaryCtx1 sc1; - TSummaryCtx2 sc2; - TSummaryCtx3 sc3; - PartialAccessPath ap; - Configuration config; - - PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - CallContext getCallContext() { result = cc } - - TSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TSummaryCtx3 getSummaryCtx3() { result = sc3 } - - PartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeFwd getASuccessor() { - partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(), - result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(), - result.getConfiguration()) - } - - predicate isSource() { - sourceNode(node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap instanceof TPartialNil - } - } - - private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev { - NodeEx node; - FlowState state; - TRevSummaryCtx1 sc1; - TRevSummaryCtx2 sc2; - TRevSummaryCtx3 sc3; - RevPartialAccessPath ap; - Configuration config; - - PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) } - - NodeEx getNodeEx() { result = node } - - override FlowState getState() { result = state } - - TRevSummaryCtx1 getSummaryCtx1() { result = sc1 } - - TRevSummaryCtx2 getSummaryCtx2() { result = sc2 } - - TRevSummaryCtx3 getSummaryCtx3() { result = sc3 } - - RevPartialAccessPath getAp() { result = ap } - - override Configuration getConfiguration() { result = config } - - override PartialPathNodeRev getASuccessor() { - revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(), - this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration()) - } - - predicate isSink() { - sinkNode(node, state, config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = TRevPartialNil() - } - } - - private predicate partialPathStep( - PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, - TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and - ( - localFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - ) - or - jumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(mid.getNodeEx(), node, config) and - state = mid.getState() and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and - cc instanceof CallContextAny and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() and - mid.getAp() instanceof PartialAccessPathNil and - ap = TPartialNil(node.getDataFlowType()) and - config = mid.getConfiguration() - or - partialPathStoreStep(mid, _, _, node, ap) and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(PartialAccessPath ap0, TypedContent tc | - partialPathReadStep(mid, ap0, tc, node, cc, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsFwd(ap, tc, ap0, config) - ) - or - partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config) - or - partialPathOutOfCallable(mid, node, state, cc, ap, config) and - sc1 = TSummaryCtx1None() and - sc2 = TSummaryCtx2None() and - sc3 = TSummaryCtx3None() - or - partialPathThroughCallable(mid, node, state, cc, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - bindingset[result, i] - private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) } - - pragma[inline] - private predicate partialPathStoreStep( - PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node, - PartialAccessPath ap2 - ) { - exists(NodeEx midNode, DataFlowType contentType | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - store(midNode, tc, node, contentType, mid.getConfiguration()) and - ap2.getHead() = tc and - ap2.len() = unbindInt(ap1.len() + 1) and - compatibleTypes(ap1.getType(), contentType) - ) - } - - pragma[nomagic] - private predicate apConsFwd( - PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeFwd mid | - partialPathStoreStep(mid, ap1, tc, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate partialPathReadStep( - PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc, - Configuration config - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and - ap.getHead() = tc and - pragma[only_bind_into](config) = mid.getConfiguration() and - cc = mid.getCallContext() - ) - } - - private predicate partialPathOutOfCallable0( - PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc, - PartialAccessPath ap, Configuration config - ) { - pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and - state = mid.getState() and - innercc = mid.getCallContext() and - innercc instanceof CallContextNoCall and - ap = mid.getAp() and - config = mid.getConfiguration() - } - - pragma[nomagic] - private predicate partialPathOutOfCallable1( - PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | - partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and - c = pos.getCallable() and - kind = pos.getKind() and - resolveReturn(innercc, c, call) - | - if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext() - ) - } - - private predicate partialPathOutOfCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(ReturnKindExt kind, DataFlowCall call | - partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config) - | - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[noinline] - private predicate partialPathIntoArg( - PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ArgNode arg, ArgumentPosition apos | - arg = mid.getNodeEx().asNode() and - state = mid.getState() and - cc = mid.getCallContext() and - arg.argumentOf(call, apos) and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate partialPathIntoCallable0( - PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state, - CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and - callable = resolveCall(call, outercc) - } - - private predicate partialPathIntoCallable( - PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc, - CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3, - DataFlowCall call, PartialAccessPath ap, Configuration config - ) { - exists(ParameterPosition pos, DataFlowCallable callable | - partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and - p.isParameterOf(callable, pos) and - sc1 = TSummaryCtx1Param(p) and - sc2 = TSummaryCtx2Some(state) and - sc3 = TSummaryCtx3Some(ap) - | - if recordDataFlowCallSite(call, callable) - then innercc = TSpecificCall(call) - else innercc = TSomeCall() - ) - } - - pragma[nomagic] - private predicate paramFlowsThroughInPartialPath( - ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, - TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeFwd mid, RetNodeEx ret | - mid.getNodeEx() = ret and - kind = ret.getKind() and - state = mid.getState() and - cc = mid.getCallContext() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() and - ap = mid.getAp() - ) - } - - pragma[noinline] - private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc, - PartialAccessPath ap, Configuration config - ) { - exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 | - partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and - paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config) - ) - } - - private predicate partialPathThroughCallable( - PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ReturnKindExt kind | - partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and - out.asNode() = kind.getAnOutNode(call) - ) - } - - pragma[nomagic] - private predicate revPartialPathStep( - PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, - TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config - ) { - localFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalLocalFlowStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - jumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - or - additionalJumpStep(node, mid.getNodeEx(), config) and - state = mid.getState() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - mid.getAp() instanceof RevPartialAccessPathNil and - ap = TRevPartialNil() and - config = mid.getConfiguration() - or - revPartialPathReadStep(mid, _, _, node, ap) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - config = mid.getConfiguration() - or - exists(RevPartialAccessPath ap0, Content c | - revPartialPathStoreStep(mid, ap0, c, node, config) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - apConsRev(ap, c, ap0, config) - ) - or - exists(ParamNodeEx p | - mid.getNodeEx() = p and - viableParamArgEx(_, p, node) and - state = mid.getState() and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - sc1 = TRevSummaryCtx1None() and - sc2 = TRevSummaryCtx2None() and - sc3 = TRevSummaryCtx3None() and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - or - exists(ReturnPosition pos | - revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and - pos = getReturnPosition(node.asNode()) - ) - or - revPartialPathThroughCallable(mid, node, state, ap, config) and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() - } - - pragma[inline] - private predicate revPartialPathReadStep( - PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node, - RevPartialAccessPath ap2 - ) { - exists(NodeEx midNode | - midNode = mid.getNodeEx() and - ap1 = mid.getAp() and - read(node, c, midNode, mid.getConfiguration()) and - ap2.getHead() = c and - ap2.len() = unbindInt(ap1.len() + 1) - ) - } - - pragma[nomagic] - private predicate apConsRev( - RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config - ) { - exists(PartialPathNodeRev mid | - revPartialPathReadStep(mid, ap1, c, _, ap2) and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathStoreStep( - PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config - ) { - exists(NodeEx midNode, TypedContent tc | - midNode = mid.getNodeEx() and - ap = mid.getAp() and - store(node, tc, midNode, _, config) and - ap.getHead() = c and - config = mid.getConfiguration() and - tc.getContent() = c - ) - } - - pragma[nomagic] - private predicate revPartialPathIntoReturn( - PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1, - TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap, - Configuration config - ) { - exists(NodeEx out | - mid.getNodeEx() = out and - mid.getState() = state and - viableReturnPosOutEx(call, pos, out) and - sc1 = TRevSummaryCtx1Some(pos) and - sc2 = TRevSummaryCtx2Some(state) and - sc3 = TRevSummaryCtx3Some(ap) and - ap = mid.getAp() and - config = mid.getConfiguration() - ) - } - - pragma[nomagic] - private predicate revPartialPathFlowsThrough( - ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, - TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config - ) { - exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos | - mid.getNodeEx() = p and - mid.getState() = state and - p.getPosition() = ppos and - sc1 = mid.getSummaryCtx1() and - sc2 = mid.getSummaryCtx2() and - sc3 = mid.getSummaryCtx3() and - ap = mid.getAp() and - config = mid.getConfiguration() and - parameterMatch(ppos, apos) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable0( - DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state, - RevPartialAccessPath ap, Configuration config - ) { - exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 | - revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and - revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config) - ) - } - - pragma[nomagic] - private predicate revPartialPathThroughCallable( - PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap, - Configuration config - ) { - exists(DataFlowCall call, ArgumentPosition pos | - revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and - node.asNode().(ArgNode).argumentOf(call, pos) - ) - } -} - -import FlowExploration - -private predicate partialFlow( - PartialPathNode source, PartialPathNode node, Configuration configuration -) { - source.getConfiguration() = configuration and - source.isFwdSource() and - node = source.getASuccessor+() -} - -private predicate revPartialFlow( - PartialPathNode node, PartialPathNode sink, Configuration configuration -) { - sink.getConfiguration() = configuration and - sink.isRevSink() and - node.getASuccessor+() = sink -} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll index ef89d0f51a2..0194b2609f0 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowPrivate.qll @@ -478,3 +478,12 @@ predicate containerContent(Content c) { c instanceof MapKeyContent or c instanceof MapValueContent } + +/** + * Gets an additional term that is added to the `join` and `branch` computations to reflect + * an additional forward or backwards branching factor that is not taken into account + * when calculating the (virtual) dispatch cost. + * + * Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter. + */ +int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p) { none() } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll index 468ed73e81a..e485a5be522 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImpl.qll @@ -301,8 +301,8 @@ module Private { TWithoutContentSummaryComponent(ContentSet c) or TWithContentSummaryComponent(ContentSet c) - private TParameterSummaryComponent thisParam() { - result = TParameterSummaryComponent(instanceParameterPosition()) + private TParameterSummaryComponent callbackSelfParam() { + result = TParameterSummaryComponent(callbackSelfParameterPosition()) } newtype TSummaryComponentStack = @@ -311,7 +311,7 @@ module Private { any(RequiredSummaryComponentStack x).required(head, tail) or any(RequiredSummaryComponentStack x).required(TParameterSummaryComponent(_), tail) and - head = thisParam() + head = callbackSelfParam() or derivedFluentFlowPush(_, _, _, head, tail, _) } @@ -336,7 +336,7 @@ module Private { callbackRef = s.drop(_) and (isCallbackParameter(callbackRef) or callbackRef.head() = TReturnSummaryComponent(_)) and input = callbackRef.tail() and - output = TConsSummaryComponentStack(thisParam(), input) and + output = TConsSummaryComponentStack(callbackSelfParam(), input) and preservesValue = true ) or @@ -439,6 +439,9 @@ module Private { out.head() = TParameterSummaryComponent(_) and s = out.tail() ) + or + // Add the post-update node corresponding to the requested argument node + outputState(c, s) and isCallbackParameter(s) } private newtype TSummaryNodeState = @@ -1012,7 +1015,7 @@ module Private { private predicate relevantSummaryElementGenerated( AccessPath inSpec, AccessPath outSpec, string kind ) { - summaryElement(this, inSpec, outSpec, kind, "generated") and + summaryElement(this, inSpec, outSpec, kind, ["generated", "ai-generated"]) and not summaryElement(this, _, _, _, "manual") } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll index 1f96cef8cc1..cdbcfd30990 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/FlowSummaryImplSpecific.qll @@ -24,7 +24,7 @@ private module SyntheticGlobals { DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c } /** Gets the parameter position of the instance parameter. */ -ArgumentPosition instanceParameterPosition() { result = -1 } +ArgumentPosition callbackSelfParameterPosition() { result = -1 } /** Gets the synthesized summary data-flow node for the given values. */ Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSummaryNode(c, state) } diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll new file mode 100644 index 00000000000..7f96fe5e6fb --- /dev/null +++ b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTracking.qll @@ -0,0 +1,64 @@ +/** + * Provides classes for performing local (intra-procedural) and + * global (inter-procedural) taint-tracking analyses. + */ + +import TaintTrackingParameter::Public +private import TaintTrackingParameter::Private + +private module AddTaintDefaults implements + DataFlowInternal::FullStateConfigSig +{ + import Config + + predicate isBarrier(DataFlow::Node node) { + Config::isBarrier(node) or defaultTaintSanitizer(node) + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + Config::isAdditionalFlowStep(node1, node2) or + defaultAdditionalTaintStep(node1, node2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + Config::allowImplicitRead(node, c) + or + ( + Config::isSink(node, _) or + Config::isAdditionalFlowStep(node, _) or + Config::isAdditionalFlowStep(node, _, _, _) + ) and + defaultImplicitTaintRead(node, c) + } +} + +/** + * Constructs a standard taint tracking computation. + */ +module Make implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import DataFlowInternal::DefaultState + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} + +/** + * Constructs a taint tracking computation using flow state. + */ +module MakeWithState implements DataFlow::DataFlowSig { + private module Config0 implements DataFlowInternal::FullStateConfigSig { + import Config + } + + private module C implements DataFlowInternal::FullStateConfigSig { + import AddTaintDefaults + } + + import DataFlowInternal::Impl +} diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingParameter.qll b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingParameter.qll index d2acc1130e5..2608adffda3 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingParameter.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/tainttracking1/TaintTrackingParameter.qll @@ -2,4 +2,5 @@ import semmle.code.java.dataflow.internal.TaintTrackingUtil as Public module Private { import semmle.code.java.dataflow.DataFlow::DataFlow as DataFlow + import semmle.code.java.dataflow.internal.DataFlowImpl as DataFlowInternal } diff --git a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll index 4499c6d63c8..32690d73626 100644 --- a/java/ql/lib/semmle/code/java/deadcode/DeadField.qll +++ b/java/ql/lib/semmle/code/java/deadcode/DeadField.qll @@ -138,7 +138,8 @@ class ClassReflectivelyReadField extends ReflectivelyReadField { * Consider all `JacksonSerializableField`s as reflectively read. */ class JacksonSerializableReflectivelyReadField extends ReflectivelyReadField, - JacksonSerializableField { } + JacksonSerializableField +{ } /** * A field that is used when applying Jackson mixins. diff --git a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll index 81f5a2d765e..2213960222e 100644 --- a/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/EntryPoints.qll @@ -94,7 +94,8 @@ abstract class ReflectivelyConstructedClass extends EntryPoint, Class { /** * Classes that are deserialized by Jackson are reflectively constructed. */ -library class JacksonReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof JacksonDeserializableType { +library class JacksonReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof JacksonDeserializableType +{ override Callable getALiveCallable() { // Constructors may be called by Jackson, if they are a no-arg, they have a suitable annotation, // or inherit a suitable annotation through a mixin. @@ -308,8 +309,8 @@ class FacesAccessibleMethodEntryPoint extends CallableEntryPoint { * A Java Server Faces custom component, that is reflectively constructed by the framework when * used in a view (JSP or facelet). */ -class FacesComponentReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof FacesComponent { -} +class FacesComponentReflectivelyConstructedClass extends ReflectivelyConstructedClass instanceof FacesComponent +{ } /** * Entry point for EJB home interfaces. @@ -459,5 +460,5 @@ class ArbitraryXmlEntryPoint extends ReflectivelyConstructedClass { deprecated class ArbitraryXMLEntryPoint = ArbitraryXmlEntryPoint; /** A Selenium PageObject, created by a call to PageFactory.initElements(..). */ -class SeleniumPageObjectEntryPoint extends ReflectivelyConstructedClass instanceof SeleniumPageObject { -} +class SeleniumPageObjectEntryPoint extends ReflectivelyConstructedClass instanceof SeleniumPageObject +{ } diff --git a/java/ql/lib/semmle/code/java/deadcode/StrutsEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/StrutsEntryPoints.qll index de2c0c44678..86910a921f8 100644 --- a/java/ql/lib/semmle/code/java/deadcode/StrutsEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/StrutsEntryPoints.qll @@ -33,8 +33,8 @@ class Struts1ActionEntryPoint extends EntryPoint, Class { /** * A struts 2 action class that is reflectively constructed. */ -class Struts2ReflectivelyConstructedAction extends ReflectivelyConstructedClass instanceof Struts2ActionClass { -} +class Struts2ReflectivelyConstructedAction extends ReflectivelyConstructedClass instanceof Struts2ActionClass +{ } /** * A method called on a struts 2 action class when the action is activated. diff --git a/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll b/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll index d659918e815..b8013d2947a 100644 --- a/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll +++ b/java/ql/lib/semmle/code/java/deadcode/TestEntryPoints.qll @@ -78,7 +78,8 @@ class JUnitCategory extends WhitelistedLiveClass { /** * A listener that will be reflectively constructed by TestNG. */ -class TestNGReflectivelyConstructedListener extends ReflectivelyConstructedClass instanceof TestNGListenerImpl { +class TestNGReflectivelyConstructedListener extends ReflectivelyConstructedClass instanceof TestNGListenerImpl +{ // Consider any class that implements a TestNG listener interface to be live. Listeners can be // specified on the command line, in `testng.xml` files and in Ant build files, so it is safest // to assume that all such listeners are live. diff --git a/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll b/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll index 81a303256d0..d4c0d7e5ab5 100644 --- a/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll +++ b/java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll @@ -236,6 +236,12 @@ private VirtualMethodAccess objectToString(ObjNode n) { result.getQualifier() = n.asExpr() and sink(n) } +/** + * Holds if `ma` is an `Object.toString()` call taking possibly improved type + * bounds into account. + */ +predicate objectToStringCall(VirtualMethodAccess ma) { ma = objectToString(_) } + /** * Holds if the qualifier of the `Object.toString()` call `ma` might have type `t`. */ diff --git a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll index eb1878bf7e4..4b880542229 100644 --- a/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll +++ b/java/ql/lib/semmle/code/java/dispatch/VirtualDispatch.qll @@ -93,7 +93,8 @@ private module Dispatch { exists(RefType t | qualUnionType(ma, t, false) | lowConfidenceDispatchType(t.getSourceDeclaration()) ) - ) + ) and + not ObjFlow::objectToStringCall(ma) } private predicate lowConfidenceDispatchType(SrcRefType t) { diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll index 4f6e9e3f5e4..104fd74b5f2 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Intent.qll @@ -123,7 +123,8 @@ class StartServiceMethod extends Method { /** Specifies that if an `Intent` is tainted, then so are its synthetic fields. */ private class IntentFieldsInheritTaint extends DataFlow::SyntheticFieldContent, - TaintInheritingContent { + TaintInheritingContent +{ IntentFieldsInheritTaint() { this.getField().matches("android.content.Intent.%") } } diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll index 6245bc24494..8512308f241 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll @@ -2,7 +2,6 @@ import java private import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.internal.DataFlowForOnActivityResult private import semmle.code.java.frameworks.android.Android private import semmle.code.java.frameworks.android.Fragment private import semmle.code.java.frameworks.android.Intent @@ -28,10 +27,8 @@ class OnActivityResultIncomingIntent extends DataFlow::Node { * Intent to `onActivityResult`. */ predicate isRemoteSource() { - exists( - ImplicitStartActivityForResultConf conf, RefType startingType, Expr startActivityForResultArg - | - conf.hasFlowToExpr(startActivityForResultArg) and + exists(RefType startingType, Expr startActivityForResultArg | + ImplicitStartActivityForResult::hasFlowToExpr(startActivityForResultArg) and // startingType is the class enclosing the method that calls `startActivityForResult`. startingType = startActivityForResultArg.getEnclosingCallable().getDeclaringType() | @@ -66,16 +63,14 @@ class OnActivityResultIncomingIntent extends DataFlow::Node { /** * A data flow configuration for implicit intents being used in `startActivityForResult`. */ -private class ImplicitStartActivityForResultConf extends DataFlowForOnActivityResult::Configuration { - ImplicitStartActivityForResultConf() { this = "ImplicitStartActivityForResultConf" } - - override predicate isSource(DataFlow::Node source) { +private module ImplicitStartActivityForResultConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(ClassInstanceExpr cc | cc.getConstructedType() instanceof TypeIntent and source.asExpr() = cc ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess startActivityForResult | startActivityForResult.getMethod().hasName("startActivityForResult") and startActivityForResult.getMethod().getDeclaringType().getAnAncestor() instanceof @@ -84,11 +79,9 @@ private class ImplicitStartActivityForResultConf extends DataFlowForOnActivityRe ) } - override predicate isBarrier(DataFlow::Node barrier) { - barrier instanceof ExplicitIntentSanitizer - } + predicate isBarrier(DataFlow::Node barrier) { barrier instanceof ExplicitIntentSanitizer } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { // Wrapping the Intent in a chooser exists(MethodAccess ma, Method m | ma.getMethod() = m and @@ -110,6 +103,9 @@ private class ImplicitStartActivityForResultConf extends DataFlowForOnActivityRe } } +private module ImplicitStartActivityForResult = + DataFlow::Make; + /** An Android Activity or Fragment. */ private class ActivityOrFragment extends Class { ActivityOrFragment() { diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll index 33de1ea0d12..96ccb2a4401 100644 --- a/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll +++ b/java/ql/lib/semmle/code/java/frameworks/android/Slice.qll @@ -35,6 +35,7 @@ private class SliceProviderLifecycleStep extends AdditionalValueStep { } private class SliceActionsInheritTaint extends DataFlow::SyntheticFieldContent, - TaintInheritingContent { + TaintInheritingContent +{ SliceActionsInheritTaint() { this.getField() = "androidx.slice.Slice.action" } } diff --git a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll index d98967566e8..72516e5427e 100644 --- a/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll +++ b/java/ql/lib/semmle/code/java/frameworks/google/GoogleHttpClientApi.qll @@ -1,7 +1,6 @@ import java import semmle.code.java.Serializability import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.internal.DataFlowForSerializability /** The method `parseAs` in `com.google.api.client.http.HttpResponse`. */ private class ParseAsMethod extends Method { @@ -11,29 +10,29 @@ private class ParseAsMethod extends Method { } } -private class TypeLiteralToParseAsFlowConfiguration extends DataFlowForSerializability::Configuration { - TypeLiteralToParseAsFlowConfiguration() { - this = "GoogleHttpClientApi::TypeLiteralToParseAsFlowConfiguration" - } +private module TypeLiteralToParseAsFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral } - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | ma.getAnArgument() = sink.asExpr() and ma.getMethod() instanceof ParseAsMethod ) } +} - TypeLiteral getSourceWithFlowToParseAs() { this.hasFlow(DataFlow::exprNode(result), _) } +private module TypeLiteralToParseAsFlow = DataFlow::Make; + +private TypeLiteral getSourceWithFlowToParseAs() { + TypeLiteralToParseAsFlow::hasFlow(DataFlow::exprNode(result), _) } /** A field that is deserialized by `HttpResponse.parseAs`. */ class HttpResponseParseAsDeserializableField extends DeserializableField { HttpResponseParseAsDeserializableField() { - exists(RefType decltype, TypeLiteralToParseAsFlowConfiguration conf | + exists(RefType decltype | decltype = this.getDeclaringType() and - conf.getSourceWithFlowToParseAs().getReferencedType() = decltype and + getSourceWithFlowToParseAs().getReferencedType() = decltype and decltype.fromSource() ) } diff --git a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll index 020c167fab7..e26d2312f1b 100644 --- a/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll +++ b/java/ql/lib/semmle/code/java/frameworks/jackson/JacksonSerializability.qll @@ -7,7 +7,6 @@ import java import semmle.code.java.Serializability import semmle.code.java.Reflection import semmle.code.java.dataflow.DataFlow -private import semmle.code.java.dataflow.internal.DataFlowForSerializability import semmle.code.java.dataflow.FlowSteps /** @@ -91,14 +90,10 @@ private class FieldReferencedJacksonSerializableType extends JacksonSerializable /** A type whose values may be deserialized by the Jackson JSON framework. */ abstract class JacksonDeserializableType extends Type { } -private class TypeLiteralToJacksonDatabindFlowConfiguration extends DataFlowForSerializability::Configuration { - TypeLiteralToJacksonDatabindFlowConfiguration() { - this = "TypeLiteralToJacksonDatabindFlowConfiguration" - } +private module TypeLiteralToJacksonDatabindFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral } - override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma, Method m, int i | ma.getArgument(i) = sink.asExpr() and m = ma.getMethod() and @@ -110,16 +105,19 @@ private class TypeLiteralToJacksonDatabindFlowConfiguration extends DataFlowForS ) ) } +} - TypeLiteral getSourceWithFlowToJacksonDatabind() { this.hasFlow(DataFlow::exprNode(result), _) } +private module TypeLiteralToJacksonDatabindFlow = + DataFlow::Make; + +private TypeLiteral getSourceWithFlowToJacksonDatabind() { + TypeLiteralToJacksonDatabindFlow::hasFlow(DataFlow::exprNode(result), _) } /** A type whose values are explicitly deserialized in a call to a Jackson method. */ private class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializableType { ExplicitlyReadJacksonDeserializableType() { - exists(TypeLiteralToJacksonDatabindFlowConfiguration conf | - usesType(conf.getSourceWithFlowToJacksonDatabind().getReferencedType(), this) - ) + usesType(getSourceWithFlowToJacksonDatabind().getReferencedType(), this) or exists(MethodAccess ma | // A call to a Jackson read method... diff --git a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll index c56571624e6..8df603c5d6a 100644 --- a/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll +++ b/java/ql/lib/semmle/code/java/frameworks/javaee/ejb/EJBRestrictions.qll @@ -75,8 +75,8 @@ class ForbiddenSecurityConfigurationCallable extends ForbiddenCallable { } /** A method or constructor involving serialization that may not be called by an EJB. */ -class ForbiddenSerializationCallable extends ForbiddenCallable instanceof ForbiddenSerializationMethod { -} +class ForbiddenSerializationCallable extends ForbiddenCallable instanceof ForbiddenSerializationMethod +{ } /** A method or constructor involving network factory operations that may not be called by an EJB. */ class ForbiddenSetFactoryCallable extends ForbiddenCallable instanceof ForbiddenSetFactoryMethod { } diff --git a/java/ql/lib/semmle/code/java/os/OSCheck.qll b/java/ql/lib/semmle/code/java/os/OSCheck.qll index d43e2015705..eade97a6e53 100644 --- a/java/ql/lib/semmle/code/java/os/OSCheck.qll +++ b/java/ql/lib/semmle/code/java/os/OSCheck.qll @@ -115,7 +115,8 @@ private class IsWindowsFromApacheCommons extends IsWindowsGuard instanceof Field IsWindowsFromApacheCommons() { isOsFromApacheCommons(this, "IS\\_OS\\_WINDOWS") } } -private class IsSpecificWindowsVariantFromApacheCommons extends IsSpecificWindowsVariant instanceof FieldAccess { +private class IsSpecificWindowsVariantFromApacheCommons extends IsSpecificWindowsVariant instanceof FieldAccess +{ IsSpecificWindowsVariantFromApacheCommons() { isOsFromApacheCommons(this, "IS\\_OS\\_WINDOWS\\_%") } @@ -125,7 +126,8 @@ private class IsUnixFromApacheCommons extends IsUnixGuard instanceof FieldAccess IsUnixFromApacheCommons() { isOsFromApacheCommons(this, "IS\\_OS\\_UNIX") } } -private class IsSpecificUnixVariantFromApacheCommons extends IsSpecificUnixVariant instanceof FieldAccess { +private class IsSpecificUnixVariantFromApacheCommons extends IsSpecificUnixVariant instanceof FieldAccess +{ IsSpecificUnixVariantFromApacheCommons() { isOsFromApacheCommons(this, [ diff --git a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll index b494feb5492..2855f5989cf 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll @@ -122,9 +122,11 @@ private predicate isStartActivityOrServiceSink(DataFlow::Node arg) { } /** + * DEPRECATED: Use `SensitiveCommunicationFlow` instead. + * * Taint configuration tracking flow from variables containing sensitive information to broadcast Intents. */ -class SensitiveCommunicationConfig extends TaintTracking::Configuration { +deprecated class SensitiveCommunicationConfig extends TaintTracking::Configuration { SensitiveCommunicationConfig() { this = "Sensitive Communication Configuration" } override predicate isSource(DataFlow::Node source) { @@ -148,3 +150,27 @@ class SensitiveCommunicationConfig extends TaintTracking::Configuration { this.isSink(node) } } + +private module SensitiveCommunicationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveInfoExpr } + + predicate isSink(DataFlow::Node sink) { + isSensitiveBroadcastSink(sink) + or + isStartActivityOrServiceSink(sink) + } + + /** + * Holds if broadcast doesn't specify receiving package name of the 3rd party app + */ + predicate isBarrier(DataFlow::Node node) { node instanceof ExplicitIntentSanitizer } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + isSink(node) and exists(c) + } +} + +/** + * Tracks taint flow from variables containing sensitive information to broadcast Intents. + */ +module SensitiveCommunicationFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallation.qll b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallation.qll new file mode 100644 index 00000000000..09a74b2e536 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallation.qll @@ -0,0 +1,87 @@ +/** Provide classes to reason about Android Intents that can install APKs. */ + +import java +import semmle.code.java.frameworks.android.Intent +import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.dataflow.ExternalFlow +private import semmle.code.java.dataflow.FlowSources + +/** A string literal that represents the MIME type for Android APKs. */ +class PackageArchiveMimeTypeLiteral extends StringLiteral { + PackageArchiveMimeTypeLiteral() { this.getValue() = "application/vnd.android.package-archive" } +} + +/** The `android.content.Intent.ACTION_INSTALL_PACKAGE` constant. */ +class InstallPackageAction extends Expr { + InstallPackageAction() { + this.(StringLiteral).getValue() = "android.intent.action.INSTALL_PACKAGE" + or + exists(VarAccess va | + va.getVariable().hasName("ACTION_INSTALL_PACKAGE") and + va.getQualifier().getType() instanceof TypeIntent + ) + } +} + +/** A method that sets the MIME type of an intent. */ +class SetTypeMethod extends Method { + SetTypeMethod() { + this.hasName(["setType", "setTypeAndNormalize"]) and + this.getDeclaringType() instanceof TypeIntent + } +} + +/** A method that sets the data URI and the MIME type of an intent. */ +class SetDataAndTypeMethod extends Method { + SetDataAndTypeMethod() { + this.hasName(["setDataAndType", "setDataAndTypeAndNormalize"]) and + this.getDeclaringType() instanceof TypeIntent + } +} + +/** A method that sets the data URI of an intent. */ +class SetDataMethod extends Method { + SetDataMethod() { + this.hasName(["setData", "setDataAndNormalize", "setDataAndType", "setDataAndTypeAndNormalize"]) and + this.getDeclaringType() instanceof TypeIntent + } +} + +/** A dataflow sink for the URI of an intent. */ +class SetDataSink extends DataFlow::ExprNode { + SetDataSink() { + exists(MethodAccess ma | + this.getExpr() = ma.getQualifier() and + ma.getMethod() instanceof SetDataMethod + ) + } +} + +/** A method that generates a URI. */ +class UriConstructorMethod extends Method { + UriConstructorMethod() { + this.hasQualifiedName("android.net", "Uri", ["fromFile", "fromParts"]) or + this.hasQualifiedName("androidx.core.content", "FileProvider", "getUriForFile") + } +} + +/** + * A dataflow source representing the URIs which an APK not controlled by the + * application may come from. Including external storage and web URLs. + */ +class ExternalApkSource extends DataFlow::Node { + ExternalApkSource() { + sourceNode(this, "android-external-storage-dir") or + this.asExpr().(MethodAccess).getMethod() instanceof UriConstructorMethod or + this.asExpr().(StringLiteral).getValue().matches("file://%") or + this instanceof RemoteFlowSource + } +} + +/** The `setAction` method of the `android.content.Intent` class. */ +class SetActionMethod extends Method { + SetActionMethod() { + this.hasName("setAction") and + this.getDeclaringType() instanceof TypeIntent + } +} diff --git a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll new file mode 100644 index 00000000000..68b16f7f902 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll @@ -0,0 +1,120 @@ +/** Provides dataflow configurations to reason about installation of arbitrary Android APKs. */ + +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.TaintTracking +private import semmle.code.java.security.ArbitraryApkInstallation + +/** + * A dataflow configuration for flow from an external source of an APK to the + * `setData[AndType][AndNormalize]` method of an intent. + */ +private module ApkInstallationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof ExternalApkSource } + + predicate isSink(DataFlow::Node node) { + exists(MethodAccess ma | + ma.getMethod() instanceof SetDataMethod and + ma.getArgument(0) = node.asExpr() and + ( + PackageArchiveMimeTypeFlow::hasFlowToExpr(ma.getQualifier()) + or + InstallPackageActionFlow::hasFlowToExpr(ma.getQualifier()) + ) + ) + } +} + +module ApkInstallationFlow = DataFlow::Make; + +private newtype ActionState = + ActionUnset() or + HasInstallPackageAction() + +/** + * A dataflow configuration tracking the flow from the `android.content.Intent.ACTION_INSTALL_PACKAGE` + * constant to either the constructor of an intent or the `setAction` method of an intent. + * + * This is used to track if an intent is used to install an APK. + */ +private module InstallPackageActionConfig implements DataFlow::StateConfigSig { + class FlowState = ActionState; + + predicate isSource(DataFlow::Node source, FlowState state) { + source.asExpr() instanceof InstallPackageAction and state instanceof ActionUnset + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + state1 instanceof ActionUnset and + state2 instanceof HasInstallPackageAction and + ( + exists(ConstructorCall cc | + cc.getConstructedType() instanceof TypeIntent and + node1.asExpr() = cc.getArgument(0) and + node1.asExpr().getType() instanceof TypeString and + node2.asExpr() = cc + ) + or + exists(MethodAccess ma | + ma.getMethod() instanceof SetActionMethod and + node1.asExpr() = ma.getArgument(0) and + node2.asExpr() = ma.getQualifier() + ) + ) + } + + predicate isSink(DataFlow::Node node, FlowState state) { + state instanceof HasInstallPackageAction and node.asExpr().getType() instanceof TypeIntent + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } +} + +private module InstallPackageActionFlow = TaintTracking::MakeWithState; + +private newtype MimeTypeState = + MimeTypeUnset() or + HasPackageArchiveMimeType() + +/** + * A dataflow configuration tracking the flow of the Android APK MIME type to + * the `setType` or `setTypeAndNormalize` method of an intent, followed by a call + * to `setData[AndType][AndNormalize]`. + */ +private module PackageArchiveMimeTypeConfig implements DataFlow::StateConfigSig { + class FlowState = MimeTypeState; + + predicate isSource(DataFlow::Node node, FlowState state) { + node.asExpr() instanceof PackageArchiveMimeTypeLiteral and + state instanceof MimeTypeUnset + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + state1 instanceof MimeTypeUnset and + state2 instanceof HasPackageArchiveMimeType and + exists(MethodAccess ma | + ma.getQualifier() = node2.asExpr() and + ( + ma.getMethod() instanceof SetTypeMethod and + ma.getArgument(0) = node1.asExpr() + or + ma.getMethod() instanceof SetDataAndTypeMethod and + ma.getArgument(1) = node1.asExpr() + ) + ) + } + + predicate isSink(DataFlow::Node node, FlowState state) { + state instanceof HasPackageArchiveMimeType and + node instanceof SetDataSink + } + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } +} + +private module PackageArchiveMimeTypeFlow = + TaintTracking::MakeWithState; diff --git a/java/ql/lib/semmle/code/java/security/FragmentInjection.qll b/java/ql/lib/semmle/code/java/security/FragmentInjection.qll index 046993f6658..aa2a5f3dbfa 100644 --- a/java/ql/lib/semmle/code/java/security/FragmentInjection.qll +++ b/java/ql/lib/semmle/code/java/security/FragmentInjection.qll @@ -47,7 +47,8 @@ private class DefaultFragmentInjectionSink extends FragmentInjectionSink { DefaultFragmentInjectionSink() { sinkNode(this, "fragment-injection") } } -private class DefaultFragmentInjectionAdditionalTaintStep extends FragmentInjectionAdditionalTaintStep { +private class DefaultFragmentInjectionAdditionalTaintStep extends FragmentInjectionAdditionalTaintStep +{ override predicate step(DataFlow::Node n1, DataFlow::Node n2) { exists(ReflectiveClassIdentifierMethodAccess ma | ma.getArgument(0) = n1.asExpr() and ma = n2.asExpr() diff --git a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll index df14504bae4..7564993c1ed 100644 --- a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll @@ -6,10 +6,12 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.FragmentInjection /** + * DEPRECATED: Use `FragmentInjectionFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to create Android fragments dynamically. */ -class FragmentInjectionTaintConf extends TaintTracking::Configuration { +deprecated class FragmentInjectionTaintConf extends TaintTracking::Configuration { FragmentInjectionTaintConf() { this = "FragmentInjectionTaintConf" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -20,3 +22,19 @@ class FragmentInjectionTaintConf extends TaintTracking::Configuration { any(FragmentInjectionAdditionalTaintStep c).step(n1, n2) } } + +private module FragmentInjectionTaintConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof FragmentInjectionSink } + + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + any(FragmentInjectionAdditionalTaintStep c).step(n1, n2) + } +} + +/** + * Taint-tracking flow for unsafe user input + * that is used to create Android fragments dynamically. + */ +module FragmentInjectionTaintFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll index 54a431e28dd..4842d36e86a 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulation.qll @@ -45,7 +45,8 @@ class IntentUriPermissionManipulationAdditionalTaintStep extends Unit { abstract predicate step(DataFlow::Node node1, DataFlow::Node node2); } -private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermissionManipulationSink { +private class DefaultIntentUriPermissionManipulationSink extends IntentUriPermissionManipulationSink +{ DefaultIntentUriPermissionManipulationSink() { exists(MethodAccess ma | ma.getMethod() instanceof ActivitySetResultMethod | ma.getArgument(1) = this.asExpr() diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll index 039eebb98ae..d23a0c8ae4b 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -9,9 +9,11 @@ private import semmle.code.java.dataflow.DataFlow private import IntentUriPermissionManipulation /** + * DEPRECATED: Use `IntentUriPermissionManipulationFlow` instead. + * * A taint tracking configuration for user-provided Intents being returned to third party apps. */ -class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { +deprecated class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { IntentUriPermissionManipulationConf() { this = "UriPermissionManipulationConf" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -32,3 +34,23 @@ class IntentUriPermissionManipulationConf extends TaintTracking::Configuration { any(IntentUriPermissionManipulationAdditionalTaintStep c).step(node1, node2) } } + +private module IntentUriPermissionManipulationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof IntentUriPermissionManipulationSink } + + predicate isBarrier(DataFlow::Node barrier) { + barrier instanceof IntentUriPermissionManipulationSanitizer + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(IntentUriPermissionManipulationAdditionalTaintStep c).step(node1, node2) + } +} + +/** + * Taint tracking flow for user-provided Intents being returned to third party apps. + */ +module IntentUriPermissionManipulationFlow = + TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/JWT.qll b/java/ql/lib/semmle/code/java/security/JWT.qll index 40569c49bd9..7056c7567f2 100644 --- a/java/ql/lib/semmle/code/java/security/JWT.qll +++ b/java/ql/lib/semmle/code/java/security/JWT.qll @@ -55,7 +55,8 @@ class JwtParserWithInsecureParseAdditionalFlowStep extends Unit { } /** A set of additional flow steps to consider when working with JWT parsing related data flows. */ -private class DefaultJwtParserWithInsecureParseAdditionalFlowStep extends JwtParserWithInsecureParseAdditionalFlowStep { +private class DefaultJwtParserWithInsecureParseAdditionalFlowStep extends JwtParserWithInsecureParseAdditionalFlowStep +{ override predicate step(DataFlow::Node node1, DataFlow::Node node2) { jwtParserStep(node1.asExpr(), node2.asExpr()) } diff --git a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll index 6695fcfd0de..a706da71e50 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll @@ -5,9 +5,11 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.LogInjection /** + * DEPRECATED: Use `LogInjectionFlow` instead. + * * A taint-tracking configuration for tracking untrusted user input used in log entries. */ -class LogInjectionConfiguration extends TaintTracking::Configuration { +deprecated class LogInjectionConfiguration extends TaintTracking::Configuration { LogInjectionConfiguration() { this = "LogInjectionConfiguration" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -20,3 +22,20 @@ class LogInjectionConfiguration extends TaintTracking::Configuration { any(LogInjectionAdditionalTaintStep c).step(node1, node2) } } + +private module LogInjectionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof LogInjectionSink } + + predicate isBarrier(DataFlow::Node node) { node instanceof LogInjectionSanitizer } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(LogInjectionAdditionalTaintStep c).step(node1, node2) + } +} + +/** + * Taint-tracking flow for tracking untrusted user input used in log entries. + */ +module LogInjectionFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/RequestForgery.qll b/java/ql/lib/semmle/code/java/security/RequestForgery.qll index e6efc13c8a5..c454da5f035 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgery.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgery.qll @@ -34,7 +34,8 @@ private class DefaultRequestForgeryAdditionalTaintStep extends RequestForgeryAdd } } -private class TypePropertiesRequestForgeryAdditionalTaintStep extends RequestForgeryAdditionalTaintStep { +private class TypePropertiesRequestForgeryAdditionalTaintStep extends RequestForgeryAdditionalTaintStep +{ override predicate propagatesTaint(DataFlow::Node pred, DataFlow::Node succ) { exists(MethodAccess ma | // Properties props = new Properties(); diff --git a/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll b/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll index c8a59f65b0e..1f19d9640e2 100644 --- a/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll +++ b/java/ql/lib/semmle/code/java/security/RequestForgeryConfig.qll @@ -8,9 +8,11 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.RequestForgery /** + * DEPRECATED: Use `RequestForgeryConfiguration` module instead. + * * A taint-tracking configuration characterising request-forgery risks. */ -class RequestForgeryConfiguration extends TaintTracking::Configuration { +deprecated class RequestForgeryConfiguration extends TaintTracking::Configuration { RequestForgeryConfiguration() { this = "Server-Side Request Forgery" } override predicate isSource(DataFlow::Node source) { @@ -29,3 +31,26 @@ class RequestForgeryConfiguration extends TaintTracking::Configuration { override predicate isSanitizer(DataFlow::Node node) { node instanceof RequestForgerySanitizer } } + +/** + * A taint-tracking configuration characterising request-forgery risks. + */ +private module RequestForgeryConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource and + // Exclude results of remote HTTP requests: fetching something else based on that result + // is no worse than following a redirect returned by the remote server, and typically + // we're requesting a resource via https which we trust to only send us to safe URLs. + not source.asExpr().(MethodAccess).getCallee() instanceof UrlConnectionGetInputStreamMethod + } + + predicate isSink(DataFlow::Node sink) { sink instanceof RequestForgerySink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + any(RequestForgeryAdditionalTaintStep r).propagatesTaint(pred, succ) + } + + predicate isBarrier(DataFlow::Node node) { node instanceof RequestForgerySanitizer } +} + +module RequestForgeryFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll index 71cbb565e00..e7888afba5d 100644 --- a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll +++ b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll @@ -4,8 +4,12 @@ import java import Encryption import semmle.code.java.dataflow.DataFlow -/** A configuration for finding RSA ciphers initialized without using OAEP padding. */ -class RsaWithoutOaepConfig extends DataFlow::Configuration { +/** + * DEPRECATED: Use `RsaWithoutOaepFlow` instead. + * + * A configuration for finding RSA ciphers initialized without using OAEP padding. + */ +deprecated class RsaWithoutOaepConfig extends DataFlow::Configuration { RsaWithoutOaepConfig() { this = "RsaWithoutOaepConfig" } override predicate isSource(DataFlow::Node src) { @@ -21,3 +25,21 @@ class RsaWithoutOaepConfig extends DataFlow::Configuration { exists(CryptoAlgoSpec cr | sink.asExpr() = cr.getAlgoSpec()) } } + +private module RsaWithoutOaepConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(CompileTimeConstantExpr specExpr, string spec | + specExpr.getStringValue() = spec and + specExpr = src.asExpr() and + spec.matches("RSA/%") and + not spec.matches("%OAEP%") + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(CryptoAlgoSpec cr | sink.asExpr() = cr.getAlgoSpec()) + } +} + +/** Flow for finding RSA ciphers initialized without using OAEP padding. */ +module RsaWithoutOaepFlow = DataFlow::Make; diff --git a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll index 1956360e120..2ca0c4b69c0 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll @@ -25,8 +25,12 @@ private class TypeType extends RefType { } } -/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */ -class SensitiveLoggerConfiguration extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `SensitiveLoggerConfiguration` module instead. + * + * A data-flow configuration for identifying potentially-sensitive data flowing to a log output. + */ +deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configuration { SensitiveLoggerConfiguration() { this = "SensitiveLoggerConfiguration" } override predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr } @@ -43,3 +47,22 @@ class SensitiveLoggerConfiguration extends TaintTracking::Configuration { override predicate isSanitizerIn(Node node) { this.isSource(node) } } + +/** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */ +private module SensitiveLoggerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr } + + predicate isSink(DataFlow::Node sink) { sinkNode(sink, "logging") } + + predicate isBarrier(DataFlow::Node sanitizer) { + sanitizer.asExpr() instanceof LiveLiteral or + sanitizer.getType() instanceof PrimitiveType or + sanitizer.getType() instanceof BoxedType or + sanitizer.getType() instanceof NumberType or + sanitizer.getType() instanceof TypeType + } + + predicate isBarrierIn(Node node) { isSource(node) } +} + +module SensitiveLoggerFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/SpelInjection.qll b/java/ql/lib/semmle/code/java/security/SpelInjection.qll index 55f526d72f4..bed4d313ff6 100644 --- a/java/ql/lib/semmle/code/java/security/SpelInjection.qll +++ b/java/ql/lib/semmle/code/java/security/SpelInjection.qll @@ -21,7 +21,8 @@ class SpelExpressionInjectionAdditionalTaintStep extends Unit { } /** A set of additional taint steps to consider when taint tracking SpEL related data flows. */ -private class DefaultSpelExpressionInjectionAdditionalTaintStep extends SpelExpressionInjectionAdditionalTaintStep { +private class DefaultSpelExpressionInjectionAdditionalTaintStep extends SpelExpressionInjectionAdditionalTaintStep +{ override predicate step(DataFlow::Node node1, DataFlow::Node node2) { expressionParsingStep(node1, node2) } diff --git a/java/ql/lib/semmle/code/java/security/TemplateInjection.qll b/java/ql/lib/semmle/code/java/security/TemplateInjection.qll index ce2bd9d217d..b8625556c7a 100644 --- a/java/ql/lib/semmle/code/java/security/TemplateInjection.qll +++ b/java/ql/lib/semmle/code/java/security/TemplateInjection.qll @@ -62,8 +62,8 @@ abstract class TemplateInjectionSanitizerWithState extends DataFlow::Node { abstract predicate hasState(DataFlow::FlowState state); } -private class DefaultTemplateInjectionSource extends TemplateInjectionSource instanceof RemoteFlowSource { -} +private class DefaultTemplateInjectionSource extends TemplateInjectionSource instanceof RemoteFlowSource +{ } private class DefaultTemplateInjectionSink extends TemplateInjectionSink { DefaultTemplateInjectionSink() { sinkNode(this, "ssti") } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll index 0bc76e384d1..f347f98c9c3 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll @@ -5,8 +5,12 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.UnsafeContentUriResolution -/** A taint-tracking configuration to find paths from remote sources to content URI resolutions. */ -class UnsafeContentResolutionConf extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `UnsafeContentUriResolutionFlow` instead. + * + * A taint-tracking configuration to find paths from remote sources to content URI resolutions. + */ +deprecated class UnsafeContentResolutionConf extends TaintTracking::Configuration { UnsafeContentResolutionConf() { this = "UnsafeContentResolutionConf" } override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } @@ -21,3 +25,20 @@ class UnsafeContentResolutionConf extends TaintTracking::Configuration { any(ContentUriResolutionAdditionalTaintStep s).step(node1, node2) } } + +private module UnsafeContentResolutionConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof ContentUriResolutionSink } + + predicate isBarrier(DataFlow::Node sanitizer) { + sanitizer instanceof ContentUriResolutionSanitizer + } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(ContentUriResolutionAdditionalTaintStep s).step(node1, node2) + } +} + +/** Taint-tracking flow to find paths from remote sources to content URI resolutions. */ +module UnsafeContentResolutionFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/java/security/XSS.qll b/java/ql/lib/semmle/code/java/security/XSS.qll index fa94fe09cac..a2efc852fd2 100644 --- a/java/ql/lib/semmle/code/java/security/XSS.qll +++ b/java/ql/lib/semmle/code/java/security/XSS.qll @@ -7,7 +7,7 @@ import semmle.code.java.frameworks.spring.SpringController import semmle.code.java.frameworks.spring.SpringHttp import semmle.code.java.frameworks.javaee.jsf.JSFRenderer import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.TaintTracking2 +import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.dataflow.ExternalFlow /** A sink that represent a method that outputs data without applying contextual output encoding. */ @@ -41,9 +41,9 @@ private class DefaultXssSink extends XssSink { DefaultXssSink() { sinkNode(this, "xss") or - exists(XssVulnerableWriterSourceToWritingMethodFlowConfig writer, MethodAccess ma | + exists(MethodAccess ma | ma.getMethod() instanceof WritingMethod and - writer.hasFlowToExpr(ma.getQualifier()) and + XssVulnerableWriterSourceToWritingMethodFlow::hasFlowToExpr(ma.getQualifier()) and this.asExpr() = ma.getArgument(_) ) } @@ -60,22 +60,19 @@ private class DefaultXssSanitizer extends XssSanitizer { } /** A configuration that tracks data from a servlet writer to an output method. */ -private class XssVulnerableWriterSourceToWritingMethodFlowConfig extends TaintTracking2::Configuration { - XssVulnerableWriterSourceToWritingMethodFlowConfig() { - this = "XSS::XssVulnerableWriterSourceToWritingMethodFlowConfig" - } +private module XssVulnerableWriterSourceToWritingMethodFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof XssVulnerableWriterSource - } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod() instanceof WritingMethod ) } } +private module XssVulnerableWriterSourceToWritingMethodFlow = + TaintTracking::Make; + /** A method that can be used to output data to an output stream or writer. */ private class WritingMethod extends Method { WritingMethod() { @@ -107,11 +104,6 @@ class XssVulnerableWriterSource extends MethodAccess { } } -/** - * DEPRECATED: Use `XssVulnerableWriterSource` instead. - */ -deprecated class ServletWriterSource = XssVulnerableWriterSource; - /** * Holds if `s` is an HTTP Content-Type vulnerable to XSS. */ diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll index 5882677c27d..8cdf962584d 100644 --- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll @@ -198,7 +198,8 @@ private class DocumentBuilderConstruction extends MethodAccess { } } -private class SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig extends DataFlow3::Configuration { +private class SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig extends DataFlow3::Configuration +{ SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig() { this = "XmlParsers::SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig" } diff --git a/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll index 34e533c0040..3cfe91f7408 100644 --- a/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XsltInjectionQuery.qll @@ -55,7 +55,8 @@ private predicate newTransformerOrTemplatesStep(DataFlow::Node n1, DataFlow::Nod /** * A data flow configuration for secure processing feature that is enabled on `TransformerFactory`. */ -private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration { +private class TransformerFactoryWithSecureProcessingFeatureFlowConfig extends DataFlow2::Configuration +{ TransformerFactoryWithSecureProcessingFeatureFlowConfig() { this = "TransformerFactoryWithSecureProcessingFeatureFlowConfig" } diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll index 2a822ac69de..b852c8393fb 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll @@ -32,8 +32,12 @@ private class LengthRestrictedMethod extends Method { } } -/** A configuration for Polynomial ReDoS queries. */ -class PolynomialRedosConfig extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `PolynomialRedosFlow` instead. + * + * A configuration for Polynomial ReDoS queries. + */ +deprecated class PolynomialRedosConfig extends TaintTracking::Configuration { PolynomialRedosConfig() { this = "PolynomialRedosConfig" } override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } @@ -47,11 +51,34 @@ class PolynomialRedosConfig extends TaintTracking::Configuration { } } -/** Holds if there is flow from `source` to `sink` that is matched against the regexp term `regexp` that is vulnerable to Polynomial ReDoS. */ -predicate hasPolynomialReDoSResult( +/** + * DEPRECATED: Use `PolynomialRedosFlow` instead. + * + * Holds if there is flow from `source` to `sink` that is matched against the regexp term `regexp` that is vulnerable to Polynomial ReDoS. + */ +deprecated predicate hasPolynomialReDoSResult( DataFlow::PathNode source, DataFlow::PathNode sink, SuperlinearBackTracking::PolynomialBackTrackingTerm regexp ) { any(PolynomialRedosConfig config).hasFlowPath(source, sink) and regexp.getRootTerm() = sink.getNode().(PolynomialRedosSink).getRegExp() } + +/** A configuration for Polynomial ReDoS queries. */ +private module PolynomialRedosConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { + exists(SuperlinearBackTracking::PolynomialBackTrackingTerm regexp | + regexp.getRootTerm() = sink.(PolynomialRedosSink).getRegExp() + ) + } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or + node.getType() instanceof BoxedType or + node.asExpr().(MethodAccess).getMethod() instanceof LengthRestrictedMethod + } +} + +module PolynomialRedosFlow = TaintTracking::Make; diff --git a/java/ql/lib/semmle/code/xml/MavenPom.qll b/java/ql/lib/semmle/code/xml/MavenPom.qll index 612c1468259..313a0e08bd8 100644 --- a/java/ql/lib/semmle/code/xml/MavenPom.qll +++ b/java/ql/lib/semmle/code/xml/MavenPom.qll @@ -454,21 +454,11 @@ class MavenRepoJar extends File { ) } - /** - * DEPRECATED: name changed to `getGroupId` for consistent use of camel-case. - */ - deprecated string getGroupID() { result = this.getGroupId() } - /** * Gets the `artifactId` of this jar. */ string getArtifactId() { result = this.getParentContainer().getParentContainer().getBaseName() } - /** - * DEPRECATED: name changed to `getArtifactId` for consistent casing and consistent spelling with Maven. - */ - deprecated string getArtefactID() { result = this.getArtifactId() } - /** * Gets the artifact version string of this jar. */ @@ -482,11 +472,6 @@ class MavenRepoJar extends File { pom.getArtifact().getValue() = this.getArtifactId() } - /** - * DEPRECATED: name changed to `artifactMatches` for consistent spelling with Maven. - */ - deprecated predicate artefactMatches(ProtoPom pom) { this.artifactMatches(pom) } - /** * Holds if this jar is both an artifact for the POM, and has a version string that matches the POM * version string. Only soft and hard version matches are supported. diff --git a/java/ql/lib/semmle/code/xml/XML.qll b/java/ql/lib/semmle/code/xml/XML.qll index d74129d425e..33f4cd9e9e6 100644 --- a/java/ql/lib/semmle/code/xml/XML.qll +++ b/java/ql/lib/semmle/code/xml/XML.qll @@ -108,20 +108,6 @@ class XmlFile extends XmlParent, File { /** Gets the name of this XML file. */ override string getName() { result = File.super.getAbsolutePath() } - /** - * DEPRECATED: Use `getAbsolutePath()` instead. - * - * Gets the path of this XML file. - */ - deprecated string getPath() { result = this.getAbsolutePath() } - - /** - * DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead. - * - * Gets the path of the folder that contains this XML file. - */ - deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() } - /** Gets the encoding of this XML file. */ string getEncoding() { xmlEncoding(this, result) } diff --git a/java/ql/src/CHANGELOG.md b/java/ql/src/CHANGELOG.md index 0741ea4a1a3..e2a9e8a56f0 100644 --- a/java/ql/src/CHANGELOG.md +++ b/java/ql/src/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.5.4 + +No user-facing changes. + ## 0.5.3 ### New Queries diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql index e64059b63d6..c7c3ce0f835 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -18,32 +18,33 @@ import semmle.code.java.dataflow.FlowSources private import semmle.code.java.dataflow.ExternalFlow import semmle.code.java.security.PathCreation import semmle.code.java.security.PathSanitizer -import DataFlow::PathGraph import TaintedPathCommon -class TaintedPathConfig extends TaintTracking::Configuration { - TaintedPathConfig() { this = "TaintedPathConfig" } +module TaintedPathConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(PathCreation p).getAnInput() or sinkNode(sink, ["create-file", "read-file"]) } - override predicate isSanitizer(DataFlow::Node sanitizer) { + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer.getType() instanceof BoxedType or sanitizer.getType() instanceof PrimitiveType or sanitizer.getType() instanceof NumberType or sanitizer instanceof PathInjectionSanitizer } - override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { any(TaintedPathAdditionalTaintStep s).step(n1, n2) } } +module TaintedPath = TaintTracking::Make; + +import TaintedPath::PathGraph + /** * Gets the data-flow node at which to report a path ending at `sink`. * @@ -52,13 +53,13 @@ class TaintedPathConfig extends TaintTracking::Configuration { * continue to report there; otherwise we report directly at `sink`. */ DataFlow::Node getReportingNode(DataFlow::Node sink) { - any(TaintedPathConfig c).hasFlowTo(sink) and + TaintedPath::hasFlowTo(sink) and if exists(PathCreation pc | pc.getAnInput() = sink.asExpr()) then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr()) else result = sink } -from DataFlow::PathNode source, DataFlow::PathNode sink, TaintedPathConfig conf -where conf.hasFlowPath(source, sink) +from TaintedPath::PathNode source, TaintedPath::PathNode sink +where TaintedPath::hasFlowPath(source, sink) select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-079/XSS.ql b/java/ql/src/Security/CWE/CWE-079/XSS.ql index fe071334c48..f2b0a65f9fe 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSS.ql +++ b/java/ql/src/Security/CWE/CWE-079/XSS.ql @@ -14,25 +14,26 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.XSS -import DataFlow::PathGraph -class XssConfig extends TaintTracking::Configuration { - XssConfig() { this = "XSSConfig" } +module XssConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } + predicate isBarrier(DataFlow::Node node) { node instanceof XssSanitizer } - override predicate isSanitizer(DataFlow::Node node) { node instanceof XssSanitizer } + predicate isBarrierOut(DataFlow::Node node) { node instanceof XssSinkBarrier } - override predicate isSanitizerOut(DataFlow::Node node) { node instanceof XssSinkBarrier } - - override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { any(XssAdditionalTaintStep s).step(node1, node2) } } -from DataFlow::PathNode source, DataFlow::PathNode sink, XssConfig conf -where conf.hasFlowPath(source, sink) +module XssFlow = TaintTracking::Make; + +import XssFlow::PathGraph + +from XssFlow::PathNode source, XssFlow::PathNode sink +where XssFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.qhelp b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.qhelp new file mode 100644 index 00000000000..09431702008 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.qhelp @@ -0,0 +1,72 @@ + + + +

+ Android allows an application to install an Android Package Kit (APK) + using an Intent with + the "application/vnd.android.package-archive" MIME type. If + the file used in the Intent is from a location that is not + controlled by the application (for example, an SD card that is + universally writable), this can result in the unintended installation of untrusted applications. +

+
+ + +

+ You should install packages using + the PackageInstaller class. +

+ +

+ If you need to install from a file, you should use + a FileProvider. Content providers can provide more specific + permissions than file system permissions can. +

+ +

+ When your application does not require package installations, do not add + the REQUEST_INSTALL_PACKAGES permission in the manifest file. +

+
+ + + +

+ In the following (bad) example, the package is installed from a file which + may be altered by another application: +

+ + + +

+ In the following (good) example, the package is installed by using + a FileProvider: +

+ + + +

+ In the following (good) example, the package is installed using an + instance of the android.content.pm.PackageInstaller class: +

+ + +
+ + +
  • + Android Developers: Intent.ACTION_INSTALL_PACKAGE. +
  • +
  • + Android Developers: Manifest.permission.REQUEST_INSTALL_PACKAGES. +
  • +
  • + Android Developers: PackageInstaller. +
  • +
  • + Android Developers: FileProvider. +
  • +
    +
    diff --git a/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql new file mode 100644 index 00000000000..aab75a8d368 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/ArbitraryApkInstallation.ql @@ -0,0 +1,19 @@ +/** + * @id java/android/arbitrary-apk-installation + * @name Android APK installation + * @description Creating an intent with a URI pointing to a untrusted file can lead to the installation of an untrusted application. + * @kind path-problem + * @security-severity 9.3 + * @problem.severity error + * @precision medium + * @tags security + * external/cwe/cwe-094 + */ + +import java +import semmle.code.java.security.ArbitraryApkInstallationQuery +import ApkInstallationFlow::PathGraph + +from ApkInstallationFlow::PathNode source, ApkInstallationFlow::PathNode sink +where ApkInstallationFlow::hasFlowPath(source, sink) +select sink.getNode(), source, sink, "Arbitrary Android APK installation." diff --git a/java/ql/src/Security/CWE/CWE-094/InstallApkWithFile.java b/java/ql/src/Security/CWE/CWE-094/InstallApkWithFile.java new file mode 100644 index 00000000000..39462a43cc9 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/InstallApkWithFile.java @@ -0,0 +1,14 @@ +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; + +import java.io.File; + +/* Get a file from external storage */ +File file = new File(Environment.getExternalStorageDirectory(), "myapp.apk"); +Intent intent = new Intent(Intent.ACTION_VIEW); +/* Set the mimetype to APK */ +intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); + +startActivity(intent); diff --git a/java/ql/src/Security/CWE/CWE-094/InstallApkWithFileProvider.java b/java/ql/src/Security/CWE/CWE-094/InstallApkWithFileProvider.java new file mode 100644 index 00000000000..d6e537caf7d --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/InstallApkWithFileProvider.java @@ -0,0 +1,31 @@ +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import androidx.core.content.FileProvider; + +import java.io.File; +import java.io.FileOutputStream; + +String tempFilename = "temporary.apk"; +byte[] buffer = new byte[16384]; + +/* Copy application asset into temporary file */ +try (InputStream is = getAssets().open(assetName); + FileOutputStream fout = openFileOutput(tempFilename, Context.MODE_PRIVATE)) { + int n; + while ((n=is.read(buffer)) >= 0) { + fout.write(buffer, 0, n); + } +} + +/* Expose temporary file with FileProvider */ +File toInstall = new File(this.getFilesDir(), tempFilename); +Uri applicationUri = FileProvider.getUriForFile(this, "com.example.apkprovider", toInstall); + +/* Create Intent and set data to APK file. */ +Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); +intent.setData(applicationUri); +intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); + +startActivity(intent); diff --git a/java/ql/src/Security/CWE/CWE-094/InstallApkWithPackageInstaller.java b/java/ql/src/Security/CWE/CWE-094/InstallApkWithPackageInstaller.java new file mode 100644 index 00000000000..fbe8eca3f47 --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-094/InstallApkWithPackageInstaller.java @@ -0,0 +1,32 @@ +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInstaller; + +private static final String PACKAGE_INSTALLED_ACTION = + "com.example.SESSION_API_PACKAGE_INSTALLED"; + +/* Create the package installer and session */ +PackageInstaller packageInstaller = getPackageManager().getPackageInstaller(); +PackageInstaller.SessionParams params = + new PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL); +int sessionId = packageInstaller.createSession(params); +session = packageInstaller.openSession(sessionId); + +/* Load asset into session */ +try (OutputStream packageInSession = session.openWrite("package", 0, -1); + InputStream is = getAssets().open(assetName)) { + byte[] buffer = new byte[16384]; + int n; + while ((n = is.read(buffer)) >= 0) { + packageInSession.write(buffer, 0, n); + } +} + +/* Create status receiver */ +Intent intent = new Intent(this, InstallApkSessionApi.class); +intent.setAction(PACKAGE_INSTALLED_ACTION); +PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); +IntentSender statusReceiver = pendingIntent.getIntentSender(); + +/* Commit the session */ +session.commit(statusReceiver); diff --git a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql index 35b85788221..7376aa51e58 100644 --- a/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/NettyResponseSplitting.ql @@ -27,25 +27,29 @@ abstract private class InsecureNettyObjectCreation extends ClassInstanceExpr { abstract string splittingType(); } -abstract private class RequestOrResponseSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation { +abstract private class RequestOrResponseSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation +{ override string splittingType() { result = "Request splitting or response splitting" } } /** * Request splitting can allowing an attacker to inject/smuggle an additional HTTP request into the socket connection. */ -abstract private class RequestSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation { +abstract private class RequestSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation +{ override string splittingType() { result = "Request splitting" } } /** * Response splitting can lead to HTTP vulnerabilities like XSS and cache poisoning. */ -abstract private class ResponseSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation { +abstract private class ResponseSplittingInsecureNettyObjectCreation extends InsecureNettyObjectCreation +{ override string splittingType() { result = "Response splitting" } } -private class InsecureDefaultHttpHeadersClassInstantiation extends RequestOrResponseSplittingInsecureNettyObjectCreation { +private class InsecureDefaultHttpHeadersClassInstantiation extends RequestOrResponseSplittingInsecureNettyObjectCreation +{ InsecureDefaultHttpHeadersClassInstantiation() { this.getConstructedType() .hasQualifiedName("io.netty.handler.codec.http", @@ -54,21 +58,24 @@ private class InsecureDefaultHttpHeadersClassInstantiation extends RequestOrResp } } -private class InsecureDefaultHttpResponseClassInstantiation extends ResponseSplittingInsecureNettyObjectCreation { +private class InsecureDefaultHttpResponseClassInstantiation extends ResponseSplittingInsecureNettyObjectCreation +{ InsecureDefaultHttpResponseClassInstantiation() { this.getConstructedType().hasQualifiedName("io.netty.handler.codec.http", "DefaultHttpResponse") and vulnerableArgumentIndex = 2 } } -private class InsecureDefaultHttpRequestClassInstantiation extends RequestSplittingInsecureNettyObjectCreation { +private class InsecureDefaultHttpRequestClassInstantiation extends RequestSplittingInsecureNettyObjectCreation +{ InsecureDefaultHttpRequestClassInstantiation() { this.getConstructedType().hasQualifiedName("io.netty.handler.codec.http", "DefaultHttpRequest") and vulnerableArgumentIndex = 3 } } -private class InsecureDefaultFullHttpResponseClassInstantiation extends ResponseSplittingInsecureNettyObjectCreation { +private class InsecureDefaultFullHttpResponseClassInstantiation extends ResponseSplittingInsecureNettyObjectCreation +{ InsecureDefaultFullHttpResponseClassInstantiation() { this.getConstructedType() .hasQualifiedName("io.netty.handler.codec.http", "DefaultFullHttpResponse") and @@ -76,7 +83,8 @@ private class InsecureDefaultFullHttpResponseClassInstantiation extends Response } } -private class InsecureDefaultFullHttpRequestClassInstantiation extends RequestSplittingInsecureNettyObjectCreation { +private class InsecureDefaultFullHttpRequestClassInstantiation extends RequestSplittingInsecureNettyObjectCreation +{ InsecureDefaultFullHttpRequestClassInstantiation() { this.getConstructedType() .hasQualifiedName("io.netty.handler.codec.http", "DefaultFullHttpRequest") and diff --git a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql index 641ac5399a0..b1682dd5774 100644 --- a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql @@ -14,19 +14,16 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.ResponseSplitting -import DataFlow::PathGraph -class ResponseSplittingConfig extends TaintTracking::Configuration { - ResponseSplittingConfig() { this = "ResponseSplittingConfig" } - - override predicate isSource(DataFlow::Node source) { +module ResponseSplittingConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource and not source instanceof SafeHeaderSplittingSource } - override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } + predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType @@ -45,8 +42,12 @@ class ResponseSplittingConfig extends TaintTracking::Configuration { } } -from DataFlow::PathNode source, DataFlow::PathNode sink, ResponseSplittingConfig conf -where conf.hasFlowPath(source, sink) +module ResponseSplitting = TaintTracking::Make; + +import ResponseSplitting::PathGraph + +from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink +where ResponseSplitting::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This header depends on a $@, which may cause a response-splitting vulnerability.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql b/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql index 89af15339d0..321f5659e27 100644 --- a/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql +++ b/java/ql/src/Security/CWE/CWE-113/ResponseSplittingLocal.ql @@ -14,23 +14,24 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.ResponseSplitting -import DataFlow::PathGraph -class ResponseSplittingLocalConfig extends TaintTracking::Configuration { - ResponseSplittingLocalConfig() { this = "ResponseSplittingLocalConfig" } +module ResponseSplittingLocalConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - override predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } + predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType } } -from DataFlow::PathNode source, DataFlow::PathNode sink, ResponseSplittingLocalConfig conf -where conf.hasFlowPath(source, sink) +module ResponseSplitting = TaintTracking::Make; + +import ResponseSplitting::PathGraph + +from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink +where ResponseSplitting::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This header depends on a $@, which may cause a response-splitting vulnerability.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql index 81f545baee9..61c1db901b0 100644 --- a/java/ql/src/Security/CWE/CWE-117/LogInjection.ql +++ b/java/ql/src/Security/CWE/CWE-117/LogInjection.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.LogInjectionQuery -import DataFlow::PathGraph +import LogInjectionFlow::PathGraph -from LogInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink -where cfg.hasFlowPath(source, sink) +from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink +where LogInjectionFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This log entry depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql b/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql index 2ace7dcc65a..99d9879d19e 100644 --- a/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql +++ b/java/ql/src/Security/CWE/CWE-190/ArithmeticTainted.ql @@ -15,35 +15,39 @@ import java import semmle.code.java.dataflow.FlowSources import ArithmeticCommon -import DataFlow::PathGraph -class RemoteUserInputOverflowConfig extends TaintTracking::Configuration { - RemoteUserInputOverflowConfig() { this = "ArithmeticTainted.ql:RemoteUserInputOverflowConfig" } +module RemoteUserInputOverflowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSink(DataFlow::Node sink) { overflowSink(_, sink.asExpr()) } - override predicate isSink(DataFlow::Node sink) { overflowSink(_, sink.asExpr()) } - - override predicate isSanitizer(DataFlow::Node n) { overflowBarrier(n) } + predicate isBarrier(DataFlow::Node n) { overflowBarrier(n) } } -class RemoteUserInputUnderflowConfig extends TaintTracking::Configuration { - RemoteUserInputUnderflowConfig() { this = "ArithmeticTainted.ql:RemoteUserInputUnderflowConfig" } +module RemoteUserInputUnderflowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + predicate isSink(DataFlow::Node sink) { underflowSink(_, sink.asExpr()) } - override predicate isSink(DataFlow::Node sink) { underflowSink(_, sink.asExpr()) } - - override predicate isSanitizer(DataFlow::Node n) { underflowBarrier(n) } + predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) } } -from DataFlow::PathNode source, DataFlow::PathNode sink, ArithExpr exp, string effect +module RemoteUserInputOverflow = TaintTracking::Make; + +module RemoteUserInputUnderflow = TaintTracking::Make; + +module Flow = + DataFlow::MergePathGraph; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink, ArithExpr exp, string effect where - any(RemoteUserInputOverflowConfig c).hasFlowPath(source, sink) and + RemoteUserInputOverflow::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and overflowSink(exp, sink.getNode().asExpr()) and effect = "overflow" or - any(RemoteUserInputUnderflowConfig c).hasFlowPath(source, sink) and + RemoteUserInputUnderflow::hasFlowPath(source.asPathNode2(), sink.asPathNode2()) and underflowSink(exp, sink.getNode().asExpr()) and effect = "underflow" select exp, source, sink, diff --git a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql index 16e8bb72c93..76998b40b50 100644 --- a/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql +++ b/java/ql/src/Security/CWE/CWE-200/TempDirLocalInformationDisclosure.ql @@ -14,8 +14,7 @@ import java import semmle.code.java.os.OSCheck import TempDirUtils -import DataFlow::PathGraph -import semmle.code.java.dataflow.TaintTracking2 +import semmle.code.java.dataflow.TaintTracking abstract private class MethodFileSystemFileCreation extends Method { MethodFileSystemFileCreation() { this.getDeclaringType() instanceof TypeFile } @@ -127,19 +126,17 @@ private class IsSpecificWindowsSanitizer extends WindowsOsSanitizer { * A taint tracking configuration tracking the access of the system temporary directory * flowing to the creation of files or directories. */ -private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Configuration { - TempDirSystemGetPropertyToCreateConfig() { this = "TempDirSystemGetPropertyToCreateConfig" } - - override predicate isSource(DataFlow::Node source) { +module TempDirSystemGetPropertyToCreateConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof ExprSystemGetPropertyTempDirTainted } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink instanceof FileCreationSink and - not any(TempDirSystemGetPropertyDirectlyToMkdirConfig config).hasFlowTo(sink) + not TempDirSystemGetPropertyDirectlyToMkdir::hasFlowTo(sink) } - override predicate isSanitizer(DataFlow::Node sanitizer) { + predicate isBarrier(DataFlow::Node sanitizer) { exists(FilesSanitizingCreationMethodAccess sanitisingMethodAccess | sanitizer.asExpr() = sanitisingMethodAccess.getArgument(0) ) @@ -148,6 +145,9 @@ private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Conf } } +module TempDirSystemGetPropertyToCreate = + TaintTracking::Make; + /** * Configuration that tracks calls to to `mkdir` or `mkdirs` that are are directly on the temp directory system property. * Examples: @@ -158,12 +158,8 @@ private class TempDirSystemGetPropertyToCreateConfig extends TaintTracking::Conf * As such, this code pattern is filtered out as an explicit vulnerability in * `TempDirSystemGetPropertyToCreateConfig::isSink`. */ -private class TempDirSystemGetPropertyDirectlyToMkdirConfig extends TaintTracking2::Configuration { - TempDirSystemGetPropertyDirectlyToMkdirConfig() { - this = "TempDirSystemGetPropertyDirectlyToMkdirConfig" - } - - override predicate isSource(DataFlow::Node node) { +module TempDirSystemGetPropertyDirectlyToMkdirConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { exists(ExprSystemGetPropertyTempDirTainted propertyGetExpr, DataFlow::Node callSite | DataFlow::localFlow(DataFlow::exprNode(propertyGetExpr), callSite) | @@ -171,17 +167,20 @@ private class TempDirSystemGetPropertyDirectlyToMkdirConfig extends TaintTrackin ) } - override predicate isSink(DataFlow::Node node) { + predicate isSink(DataFlow::Node node) { exists(MethodAccess ma | ma.getMethod() instanceof MethodFileDirectoryCreation | ma.getQualifier() = node.asExpr() ) } - override predicate isSanitizer(DataFlow::Node sanitizer) { + predicate isBarrier(DataFlow::Node sanitizer) { isFileConstructorArgument(sanitizer.asExpr(), _, _) } } +module TempDirSystemGetPropertyDirectlyToMkdir = + TaintTracking::Make; + // // Begin configuration for tracking single-method calls that are vulnerable. // @@ -193,6 +192,8 @@ abstract class MethodAccessInsecureFileCreation extends MethodAccess { * Gets the type of entity created (e.g. `file`, `directory`, ...). */ abstract string getFileSystemEntityType(); + + DataFlow::Node getNode() { result.asExpr() = this } } /** @@ -235,39 +236,47 @@ class MethodAccessInsecureGuavaFilesCreateTempFile extends MethodAccessInsecureF } /** - * A hack: we include use of inherently insecure methods, which don't have any associated + * We include use of inherently insecure methods, which don't have any associated * flow path, in with results describing a path from reading `java.io.tmpdir` or similar to use * in a file creation op. * - * We achieve this by making inherently-insecure method invocations both a source and a sink in - * this configuration, resulting in a zero-length path which is type-compatible with the actual - * path-flow results. + * We achieve this by making inherently-insecure method invocations into an edge-less graph, + * resulting in a zero-length paths. */ -class InsecureMethodPseudoConfiguration extends DataFlow::Configuration { - InsecureMethodPseudoConfiguration() { this = "InsecureMethodPseudoConfiguration" } - - override predicate isSource(DataFlow::Node node) { - node.asExpr() instanceof MethodAccessInsecureFileCreation +module InsecureMethodPathGraph implements DataFlow::PathGraphSig { + predicate edges(MethodAccessInsecureFileCreation n1, MethodAccessInsecureFileCreation n2) { + none() } - override predicate isSink(DataFlow::Node node) { - node.asExpr() instanceof MethodAccessInsecureFileCreation + predicate nodes(MethodAccessInsecureFileCreation n, string key, string val) { + key = "semmle.label" and val = n.toString() + } + + predicate subpaths( + MethodAccessInsecureFileCreation n1, MethodAccessInsecureFileCreation n2, + MethodAccessInsecureFileCreation n3, MethodAccessInsecureFileCreation n4 + ) { + none() } } -from DataFlow::PathNode source, DataFlow::PathNode sink, string message +module Flow = + DataFlow::MergePathGraph; + +import Flow::PathGraph + +from Flow::PathNode source, Flow::PathNode sink, string message where ( - any(TempDirSystemGetPropertyToCreateConfig conf).hasFlowPath(source, sink) and + TempDirSystemGetPropertyToCreate::hasFlowPath(source.asPathNode1(), sink.asPathNode1()) and message = "Local information disclosure vulnerability from $@ due to use of file or directory readable by other local users." or - any(InsecureMethodPseudoConfiguration conf).hasFlowPath(source, sink) and + source = sink and // Note this message has no "$@" placeholder, so the "system temp directory" template parameter below is not used. message = "Local information disclosure vulnerability due to use of " + - source.getNode().asExpr().(MethodAccessInsecureFileCreation).getFileSystemEntityType() + - " readable by other local users." + source.asPathNode2().getFileSystemEntityType() + " readable by other local users." ) and not isPermissionsProtectedTempDirUse(sink.getNode()) select source.getNode(), source, sink, message, source.getNode(), "system temp directory" diff --git a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql index c7da4c0e1f6..02934e98840 100644 --- a/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql +++ b/java/ql/src/Security/CWE/CWE-209/StackTraceExposure.ql @@ -31,33 +31,27 @@ class PrintStackTraceMethod extends Method { } } -class ServletWriterSourceToPrintStackTraceMethodFlowConfig extends TaintTracking::Configuration { - ServletWriterSourceToPrintStackTraceMethodFlowConfig() { - this = "StackTraceExposure::ServletWriterSourceToPrintStackTraceMethodFlowConfig" - } +module ServletWriterSourceToPrintStackTraceMethodFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof XssVulnerableWriterSource } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof XssVulnerableWriterSource - } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getAnArgument() and ma.getMethod() instanceof PrintStackTraceMethod ) } } +module ServletWriterSourceToPrintStackTraceMethodFlow = + TaintTracking::Make; + /** * A call that uses `Throwable.printStackTrace()` on a stream that is connected * to external output. */ predicate printsStackToWriter(MethodAccess call) { - exists( - ServletWriterSourceToPrintStackTraceMethodFlowConfig writerSource, - PrintStackTraceMethod printStackTrace - | + exists(PrintStackTraceMethod printStackTrace | call.getMethod() = printStackTrace and - writerSource.hasFlowToExpr(call.getAnArgument()) + ServletWriterSourceToPrintStackTraceMethodFlow::hasFlowToExpr(call.getAnArgument()) ) } @@ -86,16 +80,15 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) { ) } -class StackTraceStringToHttpResponseSinkFlowConfig extends TaintTracking::Configuration { - StackTraceStringToHttpResponseSinkFlowConfig() { - this = "StackTraceExposure::StackTraceStringToHttpResponseSinkFlowConfig" - } +module StackTraceStringToHttpResponseSinkFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) } - override predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) } - - override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink } + predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink } } +module StackTraceStringToHttpResponseSinkFlow = + TaintTracking::Make; + /** * A write of stack trace data to an external stream. */ @@ -109,9 +102,10 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) { * A stringified stack trace flows to an external sink. */ predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) { - exists(MethodAccess stackTraceString, StackTraceStringToHttpResponseSinkFlowConfig conf | + exists(MethodAccess stackTraceString | stackTraceExpr(stackTrace, stackTraceString) and - conf.hasFlow(DataFlow::exprNode(stackTraceString), externalExpr) + StackTraceStringToHttpResponseSinkFlow::hasFlow(DataFlow::exprNode(stackTraceString), + externalExpr) ) } diff --git a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql index bc81c3dcc46..281415a0d91 100644 --- a/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql +++ b/java/ql/src/Security/CWE/CWE-266/IntentUriPermissionManipulation.ql @@ -15,10 +15,12 @@ import java import semmle.code.java.security.IntentUriPermissionManipulationQuery import semmle.code.java.dataflow.DataFlow -import DataFlow::PathGraph +import IntentUriPermissionManipulationFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(IntentUriPermissionManipulationConf c).hasFlowPath(source, sink) +from + IntentUriPermissionManipulationFlow::PathNode source, + IntentUriPermissionManipulationFlow::PathNode sink +where IntentUriPermissionManipulationFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This Intent can be set with arbitrary flags from a $@, " + "and used to give access to internal content providers.", source.getNode(), diff --git a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql index 3fa4b63015d..ec7ffcbccc1 100644 --- a/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql +++ b/java/ql/src/Security/CWE/CWE-327/BrokenCryptoAlgorithm.ql @@ -15,7 +15,6 @@ import java import semmle.code.java.security.Encryption import semmle.code.java.dataflow.TaintTracking import DataFlow -import PathGraph private class ShortStringLiteral extends StringLiteral { ShortStringLiteral() { getValue().length() < 100 } @@ -29,24 +28,26 @@ class BrokenAlgoLiteral extends ShortStringLiteral { } } -class InsecureCryptoConfiguration extends TaintTracking::Configuration { - InsecureCryptoConfiguration() { this = "BrokenCryptoAlgortihm::InsecureCryptoConfiguration" } +module InsecureCryptoConfig implements ConfigSig { + predicate isSource(Node n) { n.asExpr() instanceof BrokenAlgoLiteral } - override predicate isSource(Node n) { n.asExpr() instanceof BrokenAlgoLiteral } + predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) } - override predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) } - - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType } } +module InsecureCryptoFlow = TaintTracking::Make; + +import InsecureCryptoFlow::PathGraph + from - PathNode source, PathNode sink, CryptoAlgoSpec c, BrokenAlgoLiteral s, - InsecureCryptoConfiguration conf + InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c, + BrokenAlgoLiteral s where sink.getNode().asExpr() = c.getAlgoSpec() and source.getNode().asExpr() = s and - conf.hasFlowPath(source, sink) + InsecureCryptoFlow::hasFlowPath(source, sink) select c, source, sink, "Cryptographic algorithm $@ is weak and should not be used.", s, s.getValue() diff --git a/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql b/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql index 49de716b1dc..47446211438 100644 --- a/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql +++ b/java/ql/src/Security/CWE/CWE-327/MaybeBrokenCryptoAlgorithm.ql @@ -16,7 +16,6 @@ import semmle.code.java.security.Encryption import semmle.code.java.dataflow.TaintTracking import DataFlow import semmle.code.java.dispatch.VirtualDispatch -import PathGraph private class ShortStringLiteral extends StringLiteral { ShortStringLiteral() { this.getValue().length() < 100 } @@ -51,26 +50,28 @@ class StringContainer extends RefType { } } -class InsecureCryptoConfiguration extends TaintTracking::Configuration { - InsecureCryptoConfiguration() { this = "InsecureCryptoConfiguration" } +module InsecureCryptoConfig implements ConfigSig { + predicate isSource(Node n) { n.asExpr() instanceof InsecureAlgoLiteral } - override predicate isSource(Node n) { n.asExpr() instanceof InsecureAlgoLiteral } + predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) } - override predicate isSink(Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) } - - override predicate isSanitizer(Node n) { + predicate isBarrier(Node n) { objectToString(n.asExpr()) or not n.getType().getErasure() instanceof StringContainer } } +module InsecureCryptoFlow = TaintTracking::Make; + +import InsecureCryptoFlow::PathGraph + from - PathNode source, PathNode sink, CryptoAlgoSpec c, InsecureAlgoLiteral s, - InsecureCryptoConfiguration conf + InsecureCryptoFlow::PathNode source, InsecureCryptoFlow::PathNode sink, CryptoAlgoSpec c, + InsecureAlgoLiteral s where sink.getNode().asExpr() = c.getAlgoSpec() and source.getNode().asExpr() = s and - conf.hasFlowPath(source, sink) + InsecureCryptoFlow::hasFlowPath(source, sink) select c, source, sink, "Cryptographic algorithm $@ may not be secure, consider using a different algorithm.", s, s.getValue() diff --git a/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql b/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql index 37550d1822b..ce90cc5e00f 100644 --- a/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql +++ b/java/ql/src/Security/CWE/CWE-441/UnsafeContentUriResolution.ql @@ -14,10 +14,10 @@ import java import semmle.code.java.security.UnsafeContentUriResolutionQuery -import DataFlow::PathGraph +import UnsafeContentResolutionFlow::PathGraph -from DataFlow::PathNode src, DataFlow::PathNode sink -where any(UnsafeContentResolutionConf c).hasFlowPath(src, sink) +from UnsafeContentResolutionFlow::PathNode src, UnsafeContentResolutionFlow::PathNode sink +where UnsafeContentResolutionFlow::hasFlowPath(src, sink) select sink.getNode(), src, sink, "This ContentResolver method that resolves a URI depends on a $@.", src.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql b/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql index af5fec1f9a0..5ffa7068980 100644 --- a/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql +++ b/java/ql/src/Security/CWE/CWE-470/FragmentInjection.ql @@ -13,10 +13,10 @@ import java import semmle.code.java.security.FragmentInjectionQuery -import DataFlow::PathGraph +import FragmentInjectionTaintFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(FragmentInjectionTaintConf conf).hasFlowPath(source, sink) +from FragmentInjectionTaintFlow::PathNode source, FragmentInjectionTaintFlow::PathNode sink +where FragmentInjectionTaintFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "Fragment depends on a $@, which may allow a malicious application to bypass access controls.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql b/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql index 6f32b9768cb..a884ba6c242 100644 --- a/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql +++ b/java/ql/src/Security/CWE/CWE-532/SensitiveInfoLog.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.SensitiveLoggingQuery -import PathGraph +import SensitiveLoggerFlow::PathGraph -from SensitiveLoggerConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink -where cfg.hasFlowPath(source, sink) +from SensitiveLoggerFlow::PathNode source, SensitiveLoggerFlow::PathNode sink +where SensitiveLoggerFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This $@ is written to a log file.", source.getNode(), "potentially sensitive information" diff --git a/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql b/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql index 87972319903..3caefe3fd09 100644 --- a/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql +++ b/java/ql/src/Security/CWE/CWE-681/NumericCastTainted.ql @@ -15,19 +15,16 @@ import java import semmle.code.java.dataflow.FlowSources import NumericCastCommon -import DataFlow::PathGraph -private class NumericCastFlowConfig extends TaintTracking::Configuration { - NumericCastFlowConfig() { this = "NumericCastTainted::RemoteUserInputToNumericNarrowingCastExpr" } +module NumericCastFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } - override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr() and sink.asExpr() instanceof VarAccess } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { boundedRead(node.asExpr()) or castCheck(node.asExpr()) or node.getType() instanceof SmallType or @@ -37,12 +34,14 @@ private class NumericCastFlowConfig extends TaintTracking::Configuration { } } -from - DataFlow::PathNode source, DataFlow::PathNode sink, NumericNarrowingCastExpr exp, - NumericCastFlowConfig conf +module NumericCastFlow = TaintTracking::Make; + +import NumericCastFlow::PathGraph + +from NumericCastFlow::PathNode source, NumericCastFlow::PathNode sink, NumericNarrowingCastExpr exp where sink.getNode().asExpr() = exp.getExpr() and - conf.hasFlowPath(source, sink) + NumericCastFlow::hasFlowPath(source, sink) select exp, source, sink, "This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql b/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql index 7ebbd73c84e..41757ab419a 100644 --- a/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql +++ b/java/ql/src/Security/CWE/CWE-681/NumericCastTaintedLocal.ql @@ -15,20 +15,15 @@ import java import semmle.code.java.dataflow.FlowSources import NumericCastCommon -import DataFlow::PathGraph -private class NumericCastFlowConfig extends TaintTracking::Configuration { - NumericCastFlowConfig() { - this = "NumericCastTaintedLocal::LocalUserInputToNumericNarrowingCastExpr" - } +module NumericCastFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - override predicate isSource(DataFlow::Node src) { src instanceof LocalUserInput } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(NumericNarrowingCastExpr cast).getExpr() } - override predicate isSanitizer(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { boundedRead(node.asExpr()) or castCheck(node.asExpr()) or node.getType() instanceof SmallType or @@ -37,13 +32,17 @@ private class NumericCastFlowConfig extends TaintTracking::Configuration { } } +module NumericCastFlow = TaintTracking::Make; + +import NumericCastFlow::PathGraph + from - DataFlow::PathNode source, DataFlow::PathNode sink, NumericNarrowingCastExpr exp, - VarAccess tainted, NumericCastFlowConfig conf + NumericCastFlow::PathNode source, NumericCastFlow::PathNode sink, NumericNarrowingCastExpr exp, + VarAccess tainted where exp.getExpr() = tainted and sink.getNode().asExpr() = tainted and - conf.hasFlowPath(source, sink) and + NumericCastFlow::hasFlowPath(source, sink) and not exists(RightShiftOp e | e.getShiftedVariable() = tainted.getVariable()) select exp, source, sink, "This cast to a narrower type depends on a $@, potentially causing truncation.", source.getNode(), diff --git a/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql b/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql index a84f1c5213e..8a1244b93d1 100644 --- a/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql +++ b/java/ql/src/Security/CWE/CWE-730/PolynomialReDoS.ql @@ -15,12 +15,14 @@ import java import semmle.code.java.security.regexp.PolynomialReDoSQuery -import DataFlow::PathGraph +import PolynomialRedosFlow::PathGraph from - DataFlow::PathNode source, DataFlow::PathNode sink, + PolynomialRedosFlow::PathNode source, PolynomialRedosFlow::PathNode sink, SuperlinearBackTracking::PolynomialBackTrackingTerm regexp -where hasPolynomialReDoSResult(source, sink, regexp) +where + PolynomialRedosFlow::hasFlowPath(source, sink) and + regexp.getRootTerm() = sink.getNode().(PolynomialRedosSink).getRegExp() select sink, source, sink, "This $@ that depends on a $@ may run slow on strings " + regexp.getPrefixMessage() + "with many repetitions of '" + regexp.getPumpString() + "'.", regexp, "regular expression", diff --git a/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql b/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql index f4092807281..a2475202dd8 100644 --- a/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql +++ b/java/ql/src/Security/CWE/CWE-780/RsaWithoutOaep.ql @@ -12,9 +12,9 @@ import java import semmle.code.java.security.RsaWithoutOaepQuery -import DataFlow::PathGraph +import RsaWithoutOaepFlow::PathGraph -from RsaWithoutOaepConfig conf, DataFlow::PathNode source, DataFlow::PathNode sink -where conf.hasFlowPath(source, sink) +from RsaWithoutOaepFlow::PathNode source, RsaWithoutOaepFlow::PathNode sink +where RsaWithoutOaepFlow::hasFlowPath(source, sink) select source, source, sink, "This specification is used to $@ without OAEP padding.", sink, "initialize an RSA cipher" diff --git a/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql b/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql index 604dd366513..c3455dc4beb 100644 --- a/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql +++ b/java/ql/src/Security/CWE/CWE-918/RequestForgery.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.RequestForgeryConfig -import DataFlow::PathGraph +import RequestForgeryFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, RequestForgeryConfiguration conf -where conf.hasFlowPath(source, sink) +from RequestForgeryFlow::PathNode source, RequestForgeryFlow::PathNode sink +where RequestForgeryFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "Potential server-side request forgery due to a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql b/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql index c8ebb3e61f4..59a7d827cf6 100644 --- a/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql +++ b/java/ql/src/Security/CWE/CWE-927/SensitiveCommunication.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.AndroidSensitiveCommunicationQuery -import DataFlow::PathGraph +import SensitiveCommunicationFlow::PathGraph -from SensitiveCommunicationConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink -where cfg.hasFlowPath(source, sink) +from SensitiveCommunicationFlow::PathNode source, SensitiveCommunicationFlow::PathNode sink +where SensitiveCommunicationFlow::hasFlowPath(source, sink) select sink.getNode(), source, sink, "This call may leak $@.", source.getNode(), "sensitive information" diff --git a/java/ql/src/change-notes/2023-01-19-arbitrary-apk-installation.md b/java/ql/src/change-notes/2023-01-19-arbitrary-apk-installation.md new file mode 100644 index 00000000000..93eb13f87d5 --- /dev/null +++ b/java/ql/src/change-notes/2023-01-19-arbitrary-apk-installation.md @@ -0,0 +1,5 @@ +--- +category: newQuery +--- +* Added a new query, `java/android/arbitrary-apk-installation`, to detect installation of APKs from untrusted sources. + diff --git a/java/ql/src/change-notes/released/0.5.4.md b/java/ql/src/change-notes/released/0.5.4.md new file mode 100644 index 00000000000..1686ab4354d --- /dev/null +++ b/java/ql/src/change-notes/released/0.5.4.md @@ -0,0 +1,3 @@ +## 0.5.4 + +No user-facing changes. diff --git a/java/ql/src/codeql-pack.release.yml b/java/ql/src/codeql-pack.release.yml index 2164e038a5d..cd3f72e2513 100644 --- a/java/ql/src/codeql-pack.release.yml +++ b/java/ql/src/codeql-pack.release.yml @@ -1,2 +1,2 @@ --- -lastReleaseVersion: 0.5.3 +lastReleaseVersion: 0.5.4 diff --git a/java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll b/java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll index 39d27be133b..0e3d11420ba 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-348/ClientSuppliedIpUsedInSecurityCheckLib.qll @@ -81,8 +81,8 @@ private class CompareSink extends ClientSuppliedIpUsedInSecurityCheckSink { } /** A data flow sink for sql operation. */ -private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink instanceof QueryInjectionSink { -} +private class SqlOperationSink extends ClientSuppliedIpUsedInSecurityCheckSink instanceof QueryInjectionSink +{ } /** A method that split string. */ class SplitMethod extends Method { diff --git a/java/ql/src/qlpack.yml b/java/ql/src/qlpack.yml index 7347b058157..6c1783ce1cb 100644 --- a/java/ql/src/qlpack.yml +++ b/java/ql/src/qlpack.yml @@ -1,5 +1,5 @@ name: codeql/java-queries -version: 0.5.4-dev +version: 0.5.5-dev groups: - java - queries diff --git a/java/ql/test/TestUtilities/InlineFlowTest.qll b/java/ql/test/TestUtilities/InlineFlowTest.qll index e6a0a551d15..bd4ef924da2 100644 --- a/java/ql/test/TestUtilities/InlineFlowTest.qll +++ b/java/ql/test/TestUtilities/InlineFlowTest.qll @@ -47,6 +47,20 @@ private predicate defaultSource(DataFlow::Node src) { src.asExpr().(MethodAccess).getMethod().getName() = ["source", "taint"] } +module DefaultFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { defaultSource(n) } + + predicate isSink(DataFlow::Node n) { + exists(MethodAccess ma | ma.getMethod().hasName("sink") | n.asExpr() = ma.getAnArgument()) + } + + int fieldFlowBranchLimit() { result = 1000 } +} + +private module DefaultValueFlow = DataFlow::Make; + +private module DefaultTaintFlow = TaintTracking::Make; + class DefaultValueFlowConf extends DataFlow::Configuration { DefaultValueFlowConf() { this = "qltest:defaultValueFlowConf" } @@ -76,6 +90,8 @@ private string getSourceArgString(DataFlow::Node src) { src.asExpr().(MethodAccess).getAnArgument().(StringLiteral).getValue() = result } +abstract class EnableLegacyConfiguration extends Unit { } + class InlineFlowTest extends InlineExpectationsTest { InlineFlowTest() { this = "HasFlowTest" } @@ -83,7 +99,7 @@ class InlineFlowTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasValueFlow" and - exists(DataFlow::Node src, DataFlow::Node sink | getValueFlowConfig().hasFlow(src, sink) | + exists(DataFlow::Node src, DataFlow::Node sink | hasValueFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = "" @@ -91,7 +107,7 @@ class InlineFlowTest extends InlineExpectationsTest { or tag = "hasTaintFlow" and exists(DataFlow::Node src, DataFlow::Node sink | - getTaintFlowConfig().hasFlow(src, sink) and not getValueFlowConfig().hasFlow(src, sink) + hasTaintFlow(src, sink) and not hasValueFlow(src, sink) | sink.getLocation() = location and element = sink.toString() and @@ -99,6 +115,18 @@ class InlineFlowTest extends InlineExpectationsTest { ) } + predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { + if exists(EnableLegacyConfiguration e) + then getValueFlowConfig().hasFlow(src, sink) + else DefaultValueFlow::hasFlow(src, sink) + } + + predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + if exists(EnableLegacyConfiguration e) + then getTaintFlowConfig().hasFlow(src, sink) + else DefaultTaintFlow::hasFlow(src, sink) + } + DataFlow::Configuration getValueFlowConfig() { result = any(DefaultValueFlowConf config) } DataFlow::Configuration getTaintFlowConfig() { result = any(DefaultTaintFlowConf config) } diff --git a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected index 172aac49284..00822e1b6df 100644 --- a/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected +++ b/java/ql/test/kotlin/library-tests/jvmoverloads-annotation/PrintAst.expected @@ -13,29 +13,6 @@ test.kt: # 45| 0: [TypeAccess] Test # 45| 1: [Parameter] a # 45| 0: [TypeAccess] int -# 45| 2: [Parameter] c -# 45| 0: [TypeAccess] double -# 45| 3: [Parameter] e -# 45| 0: [TypeAccess] boolean -# 45| 5: [BlockStmt] { ... } -# 45| 0: [ReturnStmt] return ... -# 45| 0: [MethodAccess] testExtensionFunction$default(...) -# 45| -1: [TypeAccess] TestKt -# 0| 0: [ExtensionReceiverAccess] this -# 0| 1: [VarAccess] a -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] c -# 1| 4: [FloatLiteral] 0.0 -# 0| 5: [VarAccess] e -# 1| 6: [IntegerLiteral] 21 -# 1| 7: [NullLiteral] null -# 45| 3: [ExtensionMethod] testExtensionFunction -# 45| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 45| 0: [Parameter] -# 45| 0: [TypeAccess] Test -# 45| 1: [Parameter] a -# 45| 0: [TypeAccess] int # 45| 2: [Parameter] b # 45| 0: [TypeAccess] String # 45| 3: [Parameter] c @@ -54,7 +31,7 @@ test.kt: # 0| 5: [VarAccess] e # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null -# 45| 4: [ExtensionMethod] testExtensionFunction +# 45| 3: [ExtensionMethod] testExtensionFunction #-----| 1: (Annotations) # 44| 1: [Annotation] JvmOverloads # 45| 3: [TypeAccess] int @@ -74,6 +51,29 @@ test.kt: # 45| 5: [BlockStmt] { ... } # 45| 0: [ReturnStmt] return ... # 45| 0: [VarAccess] a +# 45| 4: [ExtensionMethod] testExtensionFunction +# 45| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 45| 0: [Parameter] +# 45| 0: [TypeAccess] Test +# 45| 1: [Parameter] a +# 45| 0: [TypeAccess] int +# 45| 2: [Parameter] c +# 45| 0: [TypeAccess] double +# 45| 3: [Parameter] e +# 45| 0: [TypeAccess] boolean +# 45| 5: [BlockStmt] { ... } +# 45| 0: [ReturnStmt] return ... +# 45| 0: [MethodAccess] testExtensionFunction$default(...) +# 45| -1: [TypeAccess] TestKt +# 0| 0: [ExtensionReceiverAccess] this +# 0| 1: [VarAccess] a +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] c +# 1| 4: [FloatLiteral] 0.0 +# 0| 5: [VarAccess] e +# 1| 6: [IntegerLiteral] 21 +# 1| 7: [NullLiteral] null # 45| 5: [ExtensionMethod] testExtensionFunction$default # 45| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -134,26 +134,6 @@ test.kt: #-----| 4: (Parameters) # 6| 0: [Parameter] a # 6| 0: [TypeAccess] int -# 6| 1: [Parameter] c -# 6| 0: [TypeAccess] double -# 6| 2: [Parameter] e -# 6| 0: [TypeAccess] boolean -# 6| 5: [BlockStmt] { ... } -# 6| 0: [ReturnStmt] return ... -# 6| 0: [MethodAccess] testStaticFunction$default(...) -# 6| -1: [TypeAccess] Test -# 0| 0: [VarAccess] a -# 1| 1: [NullLiteral] null -# 0| 2: [VarAccess] c -# 1| 3: [FloatLiteral] 0.0 -# 0| 4: [VarAccess] e -# 1| 5: [IntegerLiteral] 21 -# 1| 6: [NullLiteral] null -# 6| 3: [Method] testStaticFunction -# 6| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 6| 0: [Parameter] a -# 6| 0: [TypeAccess] int # 6| 1: [Parameter] b # 6| 0: [TypeAccess] String # 6| 2: [Parameter] c @@ -171,7 +151,7 @@ test.kt: # 0| 4: [VarAccess] e # 1| 5: [IntegerLiteral] 23 # 1| 6: [NullLiteral] null -# 6| 4: [Method] testStaticFunction +# 6| 3: [Method] testStaticFunction #-----| 1: (Annotations) # 5| 1: [Annotation] JvmOverloads # 5| 2: [Annotation] JvmStatic @@ -190,6 +170,26 @@ test.kt: # 6| 5: [BlockStmt] { ... } # 6| 0: [ReturnStmt] return ... # 6| 0: [VarAccess] a +# 6| 4: [Method] testStaticFunction +# 6| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 6| 0: [Parameter] a +# 6| 0: [TypeAccess] int +# 6| 1: [Parameter] c +# 6| 0: [TypeAccess] double +# 6| 2: [Parameter] e +# 6| 0: [TypeAccess] boolean +# 6| 5: [BlockStmt] { ... } +# 6| 0: [ReturnStmt] return ... +# 6| 0: [MethodAccess] testStaticFunction$default(...) +# 6| -1: [TypeAccess] Test +# 0| 0: [VarAccess] a +# 1| 1: [NullLiteral] null +# 0| 2: [VarAccess] c +# 1| 3: [FloatLiteral] 0.0 +# 0| 4: [VarAccess] e +# 1| 5: [IntegerLiteral] 21 +# 1| 6: [NullLiteral] null # 6| 5: [Method] testStaticFunction$default # 6| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -242,27 +242,6 @@ test.kt: #-----| 4: (Parameters) # 9| 0: [Parameter] a # 9| 0: [TypeAccess] int -# 9| 1: [Parameter] c -# 9| 0: [TypeAccess] double -# 9| 2: [Parameter] e -# 9| 0: [TypeAccess] boolean -# 9| 5: [BlockStmt] { ... } -# 9| 0: [ReturnStmt] return ... -# 9| 0: [MethodAccess] testMemberFunction$default(...) -# 9| -1: [TypeAccess] Test -# 0| 0: [ThisAccess] this -# 0| 1: [VarAccess] a -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] c -# 1| 4: [FloatLiteral] 0.0 -# 0| 5: [VarAccess] e -# 1| 6: [IntegerLiteral] 21 -# 1| 7: [NullLiteral] null -# 9| 7: [Method] testMemberFunction -# 9| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 9| 0: [Parameter] a -# 9| 0: [TypeAccess] int # 9| 1: [Parameter] b # 9| 0: [TypeAccess] String # 9| 2: [Parameter] c @@ -281,7 +260,7 @@ test.kt: # 0| 5: [VarAccess] e # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null -# 9| 8: [Method] testMemberFunction +# 9| 7: [Method] testMemberFunction #-----| 1: (Annotations) # 8| 1: [Annotation] JvmOverloads # 9| 3: [TypeAccess] int @@ -299,6 +278,27 @@ test.kt: # 9| 5: [BlockStmt] { ... } # 9| 0: [ReturnStmt] return ... # 9| 0: [VarAccess] a +# 9| 8: [Method] testMemberFunction +# 9| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 9| 0: [Parameter] a +# 9| 0: [TypeAccess] int +# 9| 1: [Parameter] c +# 9| 0: [TypeAccess] double +# 9| 2: [Parameter] e +# 9| 0: [TypeAccess] boolean +# 9| 5: [BlockStmt] { ... } +# 9| 0: [ReturnStmt] return ... +# 9| 0: [MethodAccess] testMemberFunction$default(...) +# 9| -1: [TypeAccess] Test +# 0| 0: [ThisAccess] this +# 0| 1: [VarAccess] a +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] c +# 1| 4: [FloatLiteral] 0.0 +# 0| 5: [VarAccess] e +# 1| 6: [IntegerLiteral] 21 +# 1| 7: [NullLiteral] null # 9| 9: [Method] testMemberFunction$default # 9| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -355,31 +355,6 @@ test.kt: # 12| 0: [TypeAccess] Test2 # 12| 1: [Parameter] a # 12| 0: [TypeAccess] int -# 12| 2: [Parameter] c -# 12| 0: [TypeAccess] double -# 12| 3: [Parameter] e -# 12| 0: [TypeAccess] boolean -# 12| 5: [BlockStmt] { ... } -# 12| 0: [ReturnStmt] return ... -# 12| 0: [MethodAccess] testMemberExtensionFunction$default(...) -# 12| -1: [TypeAccess] Test -# 0| 0: [ThisAccess] Test.this -# 0| 0: [TypeAccess] Test -# 0| 1: [ExtensionReceiverAccess] this -# 0| 2: [VarAccess] a -# 1| 3: [NullLiteral] null -# 0| 4: [VarAccess] c -# 1| 5: [FloatLiteral] 0.0 -# 0| 6: [VarAccess] e -# 1| 7: [IntegerLiteral] 21 -# 1| 8: [NullLiteral] null -# 12| 11: [ExtensionMethod] testMemberExtensionFunction -# 12| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 12| 0: [Parameter] -# 12| 0: [TypeAccess] Test2 -# 12| 1: [Parameter] a -# 12| 0: [TypeAccess] int # 12| 2: [Parameter] b # 12| 0: [TypeAccess] String # 12| 3: [Parameter] c @@ -400,7 +375,7 @@ test.kt: # 0| 6: [VarAccess] e # 1| 7: [IntegerLiteral] 23 # 1| 8: [NullLiteral] null -# 12| 12: [ExtensionMethod] testMemberExtensionFunction +# 12| 11: [ExtensionMethod] testMemberExtensionFunction #-----| 1: (Annotations) # 11| 1: [Annotation] JvmOverloads # 12| 3: [TypeAccess] int @@ -420,6 +395,31 @@ test.kt: # 12| 5: [BlockStmt] { ... } # 12| 0: [ReturnStmt] return ... # 12| 0: [VarAccess] a +# 12| 12: [ExtensionMethod] testMemberExtensionFunction +# 12| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 12| 0: [Parameter] +# 12| 0: [TypeAccess] Test2 +# 12| 1: [Parameter] a +# 12| 0: [TypeAccess] int +# 12| 2: [Parameter] c +# 12| 0: [TypeAccess] double +# 12| 3: [Parameter] e +# 12| 0: [TypeAccess] boolean +# 12| 5: [BlockStmt] { ... } +# 12| 0: [ReturnStmt] return ... +# 12| 0: [MethodAccess] testMemberExtensionFunction$default(...) +# 12| -1: [TypeAccess] Test +# 0| 0: [ThisAccess] Test.this +# 0| 0: [TypeAccess] Test +# 0| 1: [ExtensionReceiverAccess] this +# 0| 2: [VarAccess] a +# 1| 3: [NullLiteral] null +# 0| 4: [VarAccess] c +# 1| 5: [FloatLiteral] 0.0 +# 0| 6: [VarAccess] e +# 1| 7: [IntegerLiteral] 21 +# 1| 8: [NullLiteral] null # 12| 13: [ExtensionMethod] testMemberExtensionFunction$default # 12| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -477,23 +477,6 @@ test.kt: #-----| 4: (Parameters) # 16| 0: [Parameter] a # 16| 0: [TypeAccess] int -# 16| 1: [Parameter] c -# 16| 0: [TypeAccess] double -# 16| 2: [Parameter] e -# 16| 0: [TypeAccess] boolean -# 16| 5: [BlockStmt] { ... } -# 16| 0: [ThisConstructorInvocationStmt] this(...) -# 0| 0: [VarAccess] a -# 1| 1: [NullLiteral] null -# 0| 2: [VarAccess] c -# 1| 3: [FloatLiteral] 0.0 -# 0| 4: [VarAccess] e -# 1| 5: [IntegerLiteral] 21 -# 1| 6: [NullLiteral] null -# 16| 2: [Constructor] Test2 -#-----| 4: (Parameters) -# 16| 0: [Parameter] a -# 16| 0: [TypeAccess] int # 16| 1: [Parameter] b # 16| 0: [TypeAccess] String # 16| 2: [Parameter] c @@ -509,7 +492,7 @@ test.kt: # 0| 4: [VarAccess] e # 1| 5: [IntegerLiteral] 23 # 1| 6: [NullLiteral] null -# 16| 3: [Constructor] Test2 +# 16| 2: [Constructor] Test2 #-----| 1: (Annotations) # 16| 1: [Annotation] JvmOverloads #-----| 4: (Parameters) @@ -526,7 +509,7 @@ test.kt: # 16| 5: [BlockStmt] { ... } # 16| 0: [SuperConstructorInvocationStmt] super(...) # 16| 1: [BlockStmt] { ... } -# 16| 4: [Constructor] Test2 +# 16| 3: [Constructor] Test2 #-----| 4: (Parameters) # 16| 0: [Parameter] p0 # 16| 0: [TypeAccess] int @@ -570,6 +553,23 @@ test.kt: # 16| 2: [VarAccess] p2 # 16| 3: [VarAccess] p3 # 16| 4: [VarAccess] p4 +# 16| 4: [Constructor] Test2 +#-----| 4: (Parameters) +# 16| 0: [Parameter] a +# 16| 0: [TypeAccess] int +# 16| 1: [Parameter] c +# 16| 0: [TypeAccess] double +# 16| 2: [Parameter] e +# 16| 0: [TypeAccess] boolean +# 16| 5: [BlockStmt] { ... } +# 16| 0: [ThisConstructorInvocationStmt] this(...) +# 0| 0: [VarAccess] a +# 1| 1: [NullLiteral] null +# 0| 2: [VarAccess] c +# 1| 3: [FloatLiteral] 0.0 +# 0| 4: [VarAccess] e +# 1| 5: [IntegerLiteral] 21 +# 1| 6: [NullLiteral] null # 18| 5: [Class] Companion # 18| 1: [Constructor] Companion # 18| 5: [BlockStmt] { ... } @@ -580,27 +580,6 @@ test.kt: #-----| 4: (Parameters) # 21| 0: [Parameter] a # 21| 0: [TypeAccess] int -# 21| 1: [Parameter] c -# 21| 0: [TypeAccess] double -# 21| 2: [Parameter] e -# 21| 0: [TypeAccess] boolean -# 21| 5: [BlockStmt] { ... } -# 21| 0: [ReturnStmt] return ... -# 21| 0: [MethodAccess] testCompanionFunction$default(...) -# 21| -1: [TypeAccess] Companion -# 0| 0: [ThisAccess] this -# 0| 1: [VarAccess] a -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] c -# 1| 4: [FloatLiteral] 0.0 -# 0| 5: [VarAccess] e -# 1| 6: [IntegerLiteral] 21 -# 1| 7: [NullLiteral] null -# 21| 3: [Method] testCompanionFunction -# 21| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 21| 0: [Parameter] a -# 21| 0: [TypeAccess] int # 21| 1: [Parameter] b # 21| 0: [TypeAccess] String # 21| 2: [Parameter] c @@ -619,7 +598,7 @@ test.kt: # 0| 5: [VarAccess] e # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null -# 21| 4: [Method] testCompanionFunction +# 21| 3: [Method] testCompanionFunction #-----| 1: (Annotations) # 20| 1: [Annotation] JvmOverloads # 21| 3: [TypeAccess] int @@ -637,6 +616,27 @@ test.kt: # 21| 5: [BlockStmt] { ... } # 21| 0: [ReturnStmt] return ... # 21| 0: [VarAccess] a +# 21| 4: [Method] testCompanionFunction +# 21| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 21| 0: [Parameter] a +# 21| 0: [TypeAccess] int +# 21| 1: [Parameter] c +# 21| 0: [TypeAccess] double +# 21| 2: [Parameter] e +# 21| 0: [TypeAccess] boolean +# 21| 5: [BlockStmt] { ... } +# 21| 0: [ReturnStmt] return ... +# 21| 0: [MethodAccess] testCompanionFunction$default(...) +# 21| -1: [TypeAccess] Companion +# 0| 0: [ThisAccess] this +# 0| 1: [VarAccess] a +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] c +# 1| 4: [FloatLiteral] 0.0 +# 0| 5: [VarAccess] e +# 1| 6: [IntegerLiteral] 21 +# 1| 7: [NullLiteral] null # 21| 5: [Method] testCompanionFunction$default # 21| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -691,27 +691,6 @@ test.kt: #-----| 4: (Parameters) # 24| 0: [Parameter] a # 24| 0: [TypeAccess] int -# 24| 1: [Parameter] c -# 24| 0: [TypeAccess] double -# 24| 2: [Parameter] e -# 24| 0: [TypeAccess] boolean -# 24| 5: [BlockStmt] { ... } -# 24| 0: [ReturnStmt] return ... -# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...) -# 24| -1: [TypeAccess] Companion -# 0| 0: [ThisAccess] this -# 0| 1: [VarAccess] a -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] c -# 1| 4: [FloatLiteral] 0.0 -# 0| 5: [VarAccess] e -# 1| 6: [IntegerLiteral] 21 -# 1| 7: [NullLiteral] null -# 24| 7: [Method] testStaticCompanionFunction -# 24| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 24| 0: [Parameter] a -# 24| 0: [TypeAccess] int # 24| 1: [Parameter] b # 24| 0: [TypeAccess] String # 24| 2: [Parameter] c @@ -730,7 +709,7 @@ test.kt: # 0| 5: [VarAccess] e # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null -# 24| 8: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction #-----| 1: (Annotations) # 23| 1: [Annotation] JvmOverloads # 23| 2: [Annotation] JvmStatic @@ -749,6 +728,27 @@ test.kt: # 24| 5: [BlockStmt] { ... } # 24| 0: [ReturnStmt] return ... # 24| 0: [VarAccess] a +# 24| 8: [Method] testStaticCompanionFunction +# 24| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 24| 0: [Parameter] a +# 24| 0: [TypeAccess] int +# 24| 1: [Parameter] c +# 24| 0: [TypeAccess] double +# 24| 2: [Parameter] e +# 24| 0: [TypeAccess] boolean +# 24| 5: [BlockStmt] { ... } +# 24| 0: [ReturnStmt] return ... +# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...) +# 24| -1: [TypeAccess] Companion +# 0| 0: [ThisAccess] this +# 0| 1: [VarAccess] a +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] c +# 1| 4: [FloatLiteral] 0.0 +# 0| 5: [VarAccess] e +# 1| 6: [IntegerLiteral] 21 +# 1| 7: [NullLiteral] null # 24| 9: [Method] testStaticCompanionFunction$default # 24| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -803,27 +803,6 @@ test.kt: #-----| 4: (Parameters) # 24| 0: [Parameter] a # 24| 0: [TypeAccess] int -# 24| 1: [Parameter] c -# 24| 0: [TypeAccess] double -# 24| 2: [Parameter] e -# 24| 0: [TypeAccess] boolean -# 24| 5: [BlockStmt] { ... } -# 24| 0: [ReturnStmt] return ... -# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...) -# 24| -1: [TypeAccess] Companion -# 0| 0: [ThisAccess] this -# 0| 1: [VarAccess] a -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] c -# 1| 4: [FloatLiteral] 0.0 -# 0| 5: [VarAccess] e -# 1| 6: [IntegerLiteral] 21 -# 1| 7: [NullLiteral] null -# 24| 7: [Method] testStaticCompanionFunction -# 24| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 24| 0: [Parameter] a -# 24| 0: [TypeAccess] int # 24| 1: [Parameter] b # 24| 0: [TypeAccess] String # 24| 2: [Parameter] c @@ -842,7 +821,7 @@ test.kt: # 0| 5: [VarAccess] e # 1| 6: [IntegerLiteral] 23 # 1| 7: [NullLiteral] null -# 24| 8: [Method] testStaticCompanionFunction +# 24| 7: [Method] testStaticCompanionFunction # 24| 3: [TypeAccess] int #-----| 4: (Parameters) # 24| 0: [Parameter] a @@ -865,6 +844,27 @@ test.kt: # 24| 2: [VarAccess] c # 24| 3: [VarAccess] d # 24| 4: [VarAccess] e +# 24| 8: [Method] testStaticCompanionFunction +# 24| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 24| 0: [Parameter] a +# 24| 0: [TypeAccess] int +# 24| 1: [Parameter] c +# 24| 0: [TypeAccess] double +# 24| 2: [Parameter] e +# 24| 0: [TypeAccess] boolean +# 24| 5: [BlockStmt] { ... } +# 24| 0: [ReturnStmt] return ... +# 24| 0: [MethodAccess] testStaticCompanionFunction$default(...) +# 24| -1: [TypeAccess] Companion +# 0| 0: [ThisAccess] this +# 0| 1: [VarAccess] a +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] c +# 1| 4: [FloatLiteral] 0.0 +# 0| 5: [VarAccess] e +# 1| 6: [IntegerLiteral] 21 +# 1| 7: [NullLiteral] null # 30| 4: [Class,GenericType,ParameterizedType] GenericTest #-----| -2: (Generic Parameters) # 30| 0: [TypeVariable] T @@ -884,37 +884,6 @@ test.kt: # 1| 5: [NullLiteral] null # 30| 2: [Constructor] GenericTest #-----| 4: (Parameters) -# 30| 0: [Parameter] a -# 30| 0: [TypeAccess] int -# 30| 1: [Parameter] b -# 30| 0: [TypeAccess] T -# 30| 2: [Parameter] d -# 30| 0: [TypeAccess] T -# 30| 5: [BlockStmt] { ... } -# 30| 0: [ThisConstructorInvocationStmt] this(...) -# 0| 0: [VarAccess] a -# 0| 1: [VarAccess] b -# 1| 2: [NullLiteral] null -# 0| 3: [VarAccess] d -# 1| 4: [IntegerLiteral] 11 -# 1| 5: [NullLiteral] null -# 30| 3: [Constructor] GenericTest -#-----| 1: (Annotations) -# 30| 1: [Annotation] JvmOverloads -#-----| 4: (Parameters) -# 30| 0: [Parameter] a -# 30| 0: [TypeAccess] int -# 30| 1: [Parameter] b -# 30| 0: [TypeAccess] T -# 30| 2: [Parameter] c -# 30| 0: [TypeAccess] String -# 30| 3: [Parameter] d -# 30| 0: [TypeAccess] T -# 30| 5: [BlockStmt] { ... } -# 30| 0: [SuperConstructorInvocationStmt] super(...) -# 30| 1: [BlockStmt] { ... } -# 30| 4: [Constructor] GenericTest -#-----| 4: (Parameters) # 30| 0: [Parameter] p0 # 30| 0: [TypeAccess] int # 30| 1: [Parameter] p1 @@ -953,6 +922,37 @@ test.kt: # 30| 1: [VarAccess] p1 # 30| 2: [VarAccess] p2 # 30| 3: [VarAccess] p3 +# 30| 3: [Constructor] GenericTest +#-----| 1: (Annotations) +# 30| 1: [Annotation] JvmOverloads +#-----| 4: (Parameters) +# 30| 0: [Parameter] a +# 30| 0: [TypeAccess] int +# 30| 1: [Parameter] b +# 30| 0: [TypeAccess] T +# 30| 2: [Parameter] c +# 30| 0: [TypeAccess] String +# 30| 3: [Parameter] d +# 30| 0: [TypeAccess] T +# 30| 5: [BlockStmt] { ... } +# 30| 0: [SuperConstructorInvocationStmt] super(...) +# 30| 1: [BlockStmt] { ... } +# 30| 4: [Constructor] GenericTest +#-----| 4: (Parameters) +# 30| 0: [Parameter] a +# 30| 0: [TypeAccess] int +# 30| 1: [Parameter] b +# 30| 0: [TypeAccess] T +# 30| 2: [Parameter] d +# 30| 0: [TypeAccess] T +# 30| 5: [BlockStmt] { ... } +# 30| 0: [ThisConstructorInvocationStmt] this(...) +# 0| 0: [VarAccess] a +# 0| 1: [VarAccess] b +# 1| 2: [NullLiteral] null +# 0| 3: [VarAccess] d +# 1| 4: [IntegerLiteral] 11 +# 1| 5: [NullLiteral] null # 33| 5: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) @@ -972,6 +972,22 @@ test.kt: # 1| 5: [IntegerLiteral] 10 # 1| 6: [NullLiteral] null # 33| 6: [Method] testMemberFunction +#-----| 1: (Annotations) +# 32| 1: [Annotation] JvmOverloads +# 33| 3: [TypeAccess] int +#-----| 4: (Parameters) +# 33| 0: [Parameter] a +# 33| 0: [TypeAccess] int +# 33| 1: [Parameter] b +# 33| 0: [TypeAccess] T +# 33| 2: [Parameter] c +# 33| 0: [TypeAccess] String +# 33| 3: [Parameter] d +# 33| 0: [TypeAccess] T +# 33| 5: [BlockStmt] { ... } +# 33| 0: [ReturnStmt] return ... +# 33| 0: [VarAccess] a +# 33| 7: [Method] testMemberFunction # 33| 3: [TypeAccess] int #-----| 4: (Parameters) # 33| 0: [Parameter] a @@ -991,22 +1007,6 @@ test.kt: # 0| 4: [VarAccess] d # 1| 5: [IntegerLiteral] 11 # 1| 6: [NullLiteral] null -# 33| 7: [Method] testMemberFunction -#-----| 1: (Annotations) -# 32| 1: [Annotation] JvmOverloads -# 33| 3: [TypeAccess] int -#-----| 4: (Parameters) -# 33| 0: [Parameter] a -# 33| 0: [TypeAccess] int -# 33| 1: [Parameter] b -# 33| 0: [TypeAccess] T -# 33| 2: [Parameter] c -# 33| 0: [TypeAccess] String -# 33| 3: [Parameter] d -# 33| 0: [TypeAccess] T -# 33| 5: [BlockStmt] { ... } -# 33| 0: [ReturnStmt] return ... -# 33| 0: [VarAccess] a # 33| 8: [Method] testMemberFunction$default # 33| 3: [TypeAccess] int #-----| 4: (Parameters) diff --git a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java index 790a1dd32e5..dfe89f2fdb7 100644 --- a/java/ql/test/library-tests/dataflow/callback-dispatch/A.java +++ b/java/ql/test/library-tests/dataflow/callback-dispatch/A.java @@ -182,4 +182,18 @@ public class A { public Object field1; public Object field2; + + void foo4() { + Producer1Consumer3 pc = new Producer1Consumer3() { + int cfield = 0; + @Override public Integer[] make() { + return new Integer[] { cfield }; + } + @Override public void eat(Integer[] xs) { + cfield = xs[0]; + } + }; + applyConsumer3(new Integer[] { (Integer)source(21) }, pc); + sink(applyProducer1(pc)[0]); // $ flow=21 + } } diff --git a/java/ql/test/library-tests/dataflow/collections/containerflow.ql b/java/ql/test/library-tests/dataflow/collections/containerflow.ql index df1f397f059..992971d6dc7 100644 --- a/java/ql/test/library-tests/dataflow/collections/containerflow.ql +++ b/java/ql/test/library-tests/dataflow/collections/containerflow.ql @@ -1,7 +1,3 @@ import java import semmle.code.java.dataflow.DataFlow import TestUtilities.InlineFlowTest - -class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { none() } -} diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/Test.java b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java index 5a0d3a44c2f..d776d85a5f6 100644 --- a/java/ql/test/library-tests/dataflow/fluent-methods/Test.java +++ b/java/ql/test/library-tests/dataflow/fluent-methods/Test.java @@ -42,31 +42,31 @@ public class Test { public static void test1() { Test t = new Test(); t.fluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasTaintFlow + sink(t.get()); // $hasValueFlow } public static void test2() { Test t = new Test(); Test.identity(t).fluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasTaintFlow + sink(t.get()); // $hasValueFlow } public static void test3() { Test t = new Test(); t.indirectlyFluentNoop().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasTaintFlow + sink(t.get()); // $hasValueFlow } public static void testModel1() { Test t = new Test(); t.indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasTaintFlow + sink(t.get()); // $hasValueFlow } public static void testModel2() { Test t = new Test(); Test.modelledIdentity(t).indirectlyFluentNoop().modelledFluentMethod().fluentSet(source()).fluentNoop(); - sink(t.get()); // $hasTaintFlow + sink(t.get()); // $hasValueFlow } } diff --git a/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql b/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql index dfdf41d7b98..4a9794ab351 100644 --- a/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql +++ b/java/ql/test/library-tests/dataflow/fluent-methods/flow.ql @@ -12,7 +12,3 @@ class IdentityModel extends ValuePreservingMethod { override predicate returnsValue(int arg) { arg = 0 } } - -class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } -} diff --git a/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql b/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql index 03c1290b172..a582f5b2456 100644 --- a/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql +++ b/java/ql/test/library-tests/dataflow/inoutbarriers/test.ql @@ -14,54 +14,46 @@ predicate sink0(Node n) { ) } -class Conf1 extends Configuration { - Conf1() { this = "inoutbarriers1" } +module Conf1 implements ConfigSig { + predicate isSource(Node n) { src0(n) } - override predicate isSource(Node n) { src0(n) } - - override predicate isSink(Node n) { sink0(n) } + predicate isSink(Node n) { sink0(n) } } -class Conf2 extends Configuration { - Conf2() { this = "inoutbarriers2" } +module Conf2 implements ConfigSig { + predicate isSource(Node n) { src0(n) } - override predicate isSource(Node n) { src0(n) } + predicate isSink(Node n) { sink0(n) } - override predicate isSink(Node n) { sink0(n) } - - override predicate isBarrierIn(Node n) { src0(n) } + predicate isBarrierIn(Node n) { src0(n) } } -class Conf3 extends Configuration { - Conf3() { this = "inoutbarriers3" } +module Conf3 implements ConfigSig { + predicate isSource(Node n) { src0(n) } - override predicate isSource(Node n) { src0(n) } + predicate isSink(Node n) { sink0(n) } - override predicate isSink(Node n) { sink0(n) } - - override predicate isBarrierOut(Node n) { sink0(n) } + predicate isBarrierOut(Node n) { sink0(n) } } -class Conf4 extends Configuration { - Conf4() { this = "inoutbarriers4" } +module Conf4 implements ConfigSig { + predicate isSource(Node n) { src0(n) } - override predicate isSource(Node n) { src0(n) } + predicate isSink(Node n) { sink0(n) } - override predicate isSink(Node n) { sink0(n) } + predicate isBarrierIn(Node n) { src0(n) } - override predicate isBarrierIn(Node n) { src0(n) } - - override predicate isBarrierOut(Node n) { sink0(n) } + predicate isBarrierOut(Node n) { sink0(n) } } predicate flow(Node src, Node sink, string s) { - any(Conf1 c).hasFlow(src, sink) and s = "nobarrier" + Make::hasFlow(src, sink) and s = "nobarrier" or - any(Conf2 c).hasFlow(src, sink) and s = "srcbarrier" + Make::hasFlow(src, sink) and s = "srcbarrier" or - any(Conf3 c).hasFlow(src, sink) and s = "sinkbarrier" + Make::hasFlow(src, sink) and s = "sinkbarrier" or - any(Conf4 c).hasFlow(src, sink) and s = "both" + Make::hasFlow(src, sink) and s = "both" } from Node src, Node sink, string s diff --git a/java/ql/test/library-tests/dataflow/partial/test.ql b/java/ql/test/library-tests/dataflow/partial/test.ql index 5aacbb25832..399a876e9a9 100644 --- a/java/ql/test/library-tests/dataflow/partial/test.ql +++ b/java/ql/test/library-tests/dataflow/partial/test.ql @@ -1,18 +1,19 @@ import java import semmle.code.java.dataflow.DataFlow import DataFlow -import PartialPathGraph -class Conf extends Configuration { - Conf() { this = "partial flow" } +module Config implements ConfigSig { + predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") } - override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") } - - override predicate isSink(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") } - - override int explorationLimit() { result = 10 } + predicate isSink(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") } } -from PartialPathNode n, int dist -where any(Conf c).hasPartialFlow(_, n, dist) +int explorationLimit() { result = 10 } + +module PartialFlow = Make::FlowExploration; + +import PartialFlow::PartialPathGraph + +from PartialFlow::PartialPathNode n, int dist +where PartialFlow::hasPartialFlow(_, n, dist) select dist, n diff --git a/java/ql/test/library-tests/dataflow/partial/testRev.ql b/java/ql/test/library-tests/dataflow/partial/testRev.ql index 9855b9bdcd1..c869cb4f915 100644 --- a/java/ql/test/library-tests/dataflow/partial/testRev.ql +++ b/java/ql/test/library-tests/dataflow/partial/testRev.ql @@ -1,18 +1,19 @@ import java import semmle.code.java.dataflow.DataFlow import DataFlow -import PartialPathGraph -class Conf extends Configuration { - Conf() { this = "partial flow" } +module Config implements ConfigSig { + predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") } - override predicate isSource(Node n) { n.asExpr().(MethodAccess).getMethod().hasName("src") } - - override predicate isSink(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") } - - override int explorationLimit() { result = 10 } + predicate isSink(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("sink") } } -from PartialPathNode n, int dist -where any(Conf c).hasPartialFlowRev(n, _, dist) +int explorationLimit() { result = 10 } + +module PartialFlow = Make::FlowExploration; + +import PartialFlow::PartialPathGraph + +from PartialFlow::PartialPathNode n, int dist +where PartialFlow::hasPartialFlowRev(n, _, dist) select dist, n diff --git a/java/ql/test/library-tests/dataflow/state/test.ql b/java/ql/test/library-tests/dataflow/state/test.ql index d80f017246e..afd7ed9a97e 100644 --- a/java/ql/test/library-tests/dataflow/state/test.ql +++ b/java/ql/test/library-tests/dataflow/state/test.ql @@ -39,22 +39,26 @@ predicate step(Node n1, Node n2, string s1, string s2) { predicate checkNode(Node n) { n.asExpr().(Argument).getCall().getCallee().hasName("check") } -class Conf extends TaintTracking::Configuration { - Conf() { this = "qltest:state" } +module Config implements DataFlow::StateConfigSig { + class FlowState = string; - override predicate isSource(Node n, FlowState s) { src(n, s) } + predicate isSource(Node n, FlowState s) { src(n, s) } - override predicate isSink(Node n, FlowState s) { sink(n, s) } + predicate isSink(Node n, FlowState s) { sink(n, s) } - override predicate isSanitizer(Node n, FlowState s) { bar(n, s) } + predicate isBarrier(Node n, FlowState s) { bar(n, s) } - override predicate isAdditionalTaintStep(Node n1, FlowState s1, Node n2, FlowState s2) { + predicate isAdditionalFlowStep(Node n1, FlowState s1, Node n2, FlowState s2) { step(n1, n2, s1, s2) } - - override int explorationLimit() { result = 0 } } +int explorationLimit() { result = 0 } + +module Flow = TaintTracking::MakeWithState; + +module PartialFlow = Flow::FlowExploration; + class HasFlowTest extends InlineExpectationsTest { HasFlowTest() { this = "HasFlowTest" } @@ -62,16 +66,16 @@ class HasFlowTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "flow" and - exists(PathNode src, PathNode sink, Conf conf | - conf.hasFlowPath(src, sink) and + exists(Flow::PathNode src, Flow::PathNode sink | + Flow::hasFlowPath(src, sink) and sink.getNode().getLocation() = location and element = sink.toString() and value = src.getState() ) or tag = "pFwd" and - exists(PartialPathNode src, PartialPathNode node, Conf conf | - conf.hasPartialFlow(src, node, _) and + exists(PartialFlow::PartialPathNode src, PartialFlow::PartialPathNode node | + PartialFlow::hasPartialFlow(src, node, _) and checkNode(node.getNode()) and node.getNode().getLocation() = location and element = node.toString() and @@ -79,8 +83,8 @@ class HasFlowTest extends InlineExpectationsTest { ) or tag = "pRev" and - exists(PartialPathNode node, PartialPathNode sink, Conf conf | - conf.hasPartialFlowRev(node, sink, _) and + exists(PartialFlow::PartialPathNode node, PartialFlow::PartialPathNode sink | + PartialFlow::hasPartialFlowRev(node, sink, _) and checkNode(node.getNode()) and node.getNode().getLocation() = location and element = node.toString() and diff --git a/java/ql/test/library-tests/dataflow/taint-format/A.java b/java/ql/test/library-tests/dataflow/taint-format/A.java index 6236451af38..073a31f3685 100644 --- a/java/ql/test/library-tests/dataflow/taint-format/A.java +++ b/java/ql/test/library-tests/dataflow/taint-format/A.java @@ -6,42 +6,44 @@ class A { return "tainted"; } + public static void sink(Object o) { } + public static void test1() { - String bad = source(); // $ hasTaintFlow + String bad = source(); String good = "hi"; - bad.formatted(good); // $ hasTaintFlow - good.formatted("a", bad, "b", good); // $ hasTaintFlow - String.format("%s%s", bad, good); // $ hasTaintFlow - String.format("%s", good); - String.format("%s %s %s %s %s %s %s %s %s %s ", "a", "a", "a", "a", "a", "a", "a", "a", "a", bad); // $ hasTaintFlow + sink(bad.formatted(good)); // $ hasTaintFlow + sink(good.formatted("a", bad, "b", good)); // $ hasTaintFlow + sink(String.format("%s%s", bad, good)); // $ hasTaintFlow + sink(String.format("%s", good)); + sink(String.format("%s %s %s %s %s %s %s %s %s %s ", "a", "a", "a", "a", "a", "a", "a", "a", "a", bad)); // $ hasTaintFlow } public static void test2() { - String bad = source(); // $ hasTaintFlow + String bad = source(); Formatter f = new Formatter(); - f.toString(); - f.format("%s", bad); // $ hasTaintFlow - f.toString(); // $ hasTaintFlow + sink(f.toString()); + sink(f.format("%s", bad)); // $ hasTaintFlow + sink(f.toString()); // $ hasTaintFlow } public static void test3() { - String bad = source(); // $ hasTaintFlow + String bad = source(); StringBuilder sb = new StringBuilder(); Formatter f = new Formatter(sb); - sb.toString(); // $ hasTaintFlow false positive - f.format("%s", bad); // $ hasTaintFlow - sb.toString(); // $ hasTaintFlow + sink(sb.toString()); // $ SPURIOUS: hasTaintFlow + sink(f.format("%s", bad)); // $ hasTaintFlow + sink(sb.toString()); // $ hasTaintFlow } public static void test4() { - String bad = source(); // $ hasTaintFlow + String bad = source(); StringBuilder sb = new StringBuilder(); - sb.append(bad); // $ hasTaintFlow + sink(sb.append(bad)); // $ hasTaintFlow - new Formatter(sb).format("ok").toString(); // $ hasTaintFlow + sink(new Formatter(sb).format("ok").toString()); // $ hasTaintFlow } -} \ No newline at end of file +} diff --git a/java/ql/test/library-tests/dataflow/taint-format/test.ql b/java/ql/test/library-tests/dataflow/taint-format/test.ql index 9456e0fbddc..5d91e4e8e26 100644 --- a/java/ql/test/library-tests/dataflow/taint-format/test.ql +++ b/java/ql/test/library-tests/dataflow/taint-format/test.ql @@ -1,8 +1,2 @@ import java -import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.TaintTracking import TestUtilities.InlineFlowTest - -class TaintFlowConf extends DefaultTaintFlowConf { - override predicate isSink(DataFlow::Node n) { n instanceof DataFlow::ExprNode } -} diff --git a/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.ql b/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.ql index c0c0bd11804..dcfe48d08bb 100644 --- a/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.ql +++ b/java/ql/test/library-tests/frameworks/JaxWs/JaxRsFlow.ql @@ -3,6 +3,10 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class TaintFlowConf extends DefaultTaintFlowConf { override predicate isSource(DataFlow::Node n) { super.isSource(n) diff --git a/java/ql/test/library-tests/frameworks/android/content-provider/test.ql b/java/ql/test/library-tests/frameworks/android/content-provider/test.ql index 05593052acf..a88702a206f 100644 --- a/java/ql/test/library-tests/frameworks/android/content-provider/test.ql +++ b/java/ql/test/library-tests/frameworks/android/content-provider/test.ql @@ -2,6 +2,10 @@ import java import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class ProviderTaintFlowConf extends DefaultTaintFlowConf { override predicate isSource(DataFlow::Node n) { n instanceof RemoteFlowSource } } diff --git a/java/ql/test/library-tests/frameworks/android/external-storage/test.ql b/java/ql/test/library-tests/frameworks/android/external-storage/test.ql index 03509c2d46d..e7d5ae7e44b 100644 --- a/java/ql/test/library-tests/frameworks/android/external-storage/test.ql +++ b/java/ql/test/library-tests/frameworks/android/external-storage/test.ql @@ -3,6 +3,10 @@ import semmle.code.java.dataflow.DataFlow import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class Conf extends TaintTracking::Configuration { Conf() { this = "test:AndroidExternalFlowConf" } diff --git a/java/ql/test/library-tests/frameworks/android/slice/test.ql b/java/ql/test/library-tests/frameworks/android/slice/test.ql index 6c328bc5a8b..5274c08ccdd 100644 --- a/java/ql/test/library-tests/frameworks/android/slice/test.ql +++ b/java/ql/test/library-tests/frameworks/android/slice/test.ql @@ -2,6 +2,10 @@ import java import TestUtilities.InlineFlowTest import semmle.code.java.dataflow.FlowSources +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class SliceValueFlowConf extends DefaultValueFlowConf { override predicate isSource(DataFlow::Node source) { super.isSource(source) or source instanceof RemoteFlowSource diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql index e8c498bebdf..682442b3dfc 100644 --- a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql +++ b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql @@ -2,6 +2,10 @@ import java import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class SourceValueFlowConf extends DefaultValueFlowConf { override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } } diff --git a/java/ql/test/library-tests/frameworks/apache-ant/Test.java b/java/ql/test/library-tests/frameworks/apache-ant/Test.java new file mode 100644 index 00000000000..13ba98041c5 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-ant/Test.java @@ -0,0 +1,26 @@ +package generatedtest; + +import org.apache.tools.zip.ZipEntry; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "org.apache.tools.zip;ZipEntry;true;ZipEntry;(String);;Argument[0];Argument[-1];taint;ai-generated" + ZipEntry out = null; + String in = (String) source(); + out = new ZipEntry(in); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/apache-ant/options b/java/ql/test/library-tests/frameworks/apache-ant/options new file mode 100644 index 00000000000..ded896502ed --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-ant/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-ant-1.10.13 \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/apache-ant/test.expected b/java/ql/test/library-tests/frameworks/apache-ant/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/apache-ant/test.ql b/java/ql/test/library-tests/frameworks/apache-ant/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-ant/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/apache-commons-compress/Test.java b/java/ql/test/library-tests/frameworks/apache-commons-compress/Test.java new file mode 100644 index 00000000000..9f1a83f51ba --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-commons-compress/Test.java @@ -0,0 +1,46 @@ +package generatedtest; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + { + // "org.apache.commons.compress.archivers.tar;TarArchiveEntry;true;TarArchiveEntry;(String);;Argument[0];Argument[-1];taint;ai-generated" + TarArchiveEntry out = null; + String in = (String) source(); + out = new TarArchiveEntry(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.compress.archivers.tar;TarArchiveEntry;true;TarArchiveEntry;(String,boolean);;Argument[0];Argument[-1];taint;ai-generated" + TarArchiveEntry out = null; + String in = (String) source(); + out = new TarArchiveEntry(in, false); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.compress.archivers.tar;TarArchiveEntry;true;TarArchiveEntry;(String,byte);;Argument[0];Argument[-1];taint;ai-generated" + TarArchiveEntry out = null; + String in = (String) source(); + out = new TarArchiveEntry(in, (byte) 0); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.commons.compress.archivers.tar;TarArchiveEntry;true;setLinkName;(String);;Argument[0];Argument[-1];taint;ai-generated" + TarArchiveEntry out = null; + String in = (String) source(); + out.setLinkName(in); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/apache-commons-compress/options b/java/ql/test/library-tests/frameworks/apache-commons-compress/options new file mode 100644 index 00000000000..0e1282300e0 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-commons-compress/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/apache-commons-compress diff --git a/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected b/java/ql/test/library-tests/frameworks/apache-commons-compress/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/apache-commons-compress/test.ql b/java/ql/test/library-tests/frameworks/apache-commons-compress/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-commons-compress/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/apache-http/Client.java b/java/ql/test/library-tests/frameworks/apache-http/Client.java new file mode 100644 index 00000000000..e5aab168f87 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/Client.java @@ -0,0 +1,80 @@ +package generatedtest; + +import java.net.URI; +import java.util.List; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.client.utils.URLEncodedUtils; + +// Test case generated by GenerateFlowTestCase.ql +public class Client { + + T getElement(Iterable it) { + return it.iterator().next(); + } + + Object getURIBuilder_pathDefault(Object container) { + return null; + } + + Object taint() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "org.apache.http.client.utils;URIBuilder;true;URIBuilder;(String);;Argument[0];Argument[-1];taint;ai-generated" + URIBuilder out = null; + String in = (String) taint(); + out = new URIBuilder(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URIBuilder;true;URIBuilder;(URI);;Argument[0];Argument[-1];taint;ai-generated" + URIBuilder out = null; + URI in = (URI) taint(); + out = new URIBuilder(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URIBuilder;true;setHost;(String);;Argument[0];Argument[-1];taint;ai-generated" + URIBuilder out = null; + String in = (String) taint(); + out.setHost(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URIBuilder;true;setHost;(String);;Argument[0];ReturnValue;taint;ai-generated" + URIBuilder out = null; + String in = (String) taint(); + URIBuilder instance = null; + out = instance.setHost(in); + sink(out); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URIBuilder;true;setPath;(String);;Argument[0];Argument[-1].SyntheticField[org.apache.http.client.utils.URIBuilder.path];taint;ai-generated" + URIBuilder out = null; + String in = (String) taint(); + out.setPath(in); + sink(getURIBuilder_pathDefault(out)); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URIBuilder;true;setPathSegments;(List);;Argument[0];Argument[-1].SyntheticField[org.apache.http.client.utils.URIBuilder.path];taint;ai-generated" + URIBuilder out = null; + List in = (List) taint(); + out.setPathSegments(in); + sink(getURIBuilder_pathDefault(out)); // $ hasTaintFlow + } + { + // "org.apache.http.client.utils;URLEncodedUtils;true;parse;(URI,String);;Argument[0];ReturnValue.Element;taint;ai-generated" + List out = null; + URI in = (URI) taint(); + out = URLEncodedUtils.parse(in, (String) null); + sink(getElement(out)); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/apache-http/flow.ext.yml b/java/ql/test/library-tests/frameworks/apache-http/flow.ext.yml new file mode 100644 index 00000000000..ff32ab78646 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/apache-http/flow.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Client", False, "getURIBuilder_pathDefault", "(Object)", "", "Argument[0].SyntheticField[org.apache.http.client.utils.URIBuilder.path]", "ReturnValue", "taint", "manual"] diff --git a/java/ql/test/library-tests/frameworks/apache-http/flow.ql b/java/ql/test/library-tests/frameworks/apache-http/flow.ql index 6a9c51f4b10..ac350ec6eb9 100644 --- a/java/ql/test/library-tests/frameworks/apache-http/flow.ql +++ b/java/ql/test/library-tests/frameworks/apache-http/flow.ql @@ -5,6 +5,10 @@ import semmle.code.java.security.XSS import semmle.code.java.security.UrlRedirect import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class Conf extends TaintTracking::Configuration { Conf() { this = "qltest:frameworks:apache-http" } diff --git a/java/ql/test/library-tests/frameworks/hudson/Test.java b/java/ql/test/library-tests/frameworks/hudson/Test.java new file mode 100644 index 00000000000..d8cf3280bc7 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/hudson/Test.java @@ -0,0 +1,28 @@ +package generatedtest; + +import hudson.remoting.URLDeserializationHelper; +import java.net.URL; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) { + } + + public void test() throws Exception { + + { + // "hudson.remoting;URLDeserializationHelper;true;wrapIfRequired;(URL);;Argument[0];ReturnValue;taint;ai-generated" + URL out = null; + URL in = (URL) source(); + out = URLDeserializationHelper.wrapIfRequired(in); + sink(out); // $ hasTaintFlow + } + + } + +} \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/hudson/options b/java/ql/test/library-tests/frameworks/hudson/options new file mode 100644 index 00000000000..203bbb4faa5 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/hudson/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/jenkins \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/hudson/test.expected b/java/ql/test/library-tests/frameworks/hudson/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/hudson/test.ql b/java/ql/test/library-tests/frameworks/hudson/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/hudson/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/jdk/java.io/Test.java b/java/ql/test/library-tests/frameworks/jdk/java.io/Test.java new file mode 100644 index 00000000000..19c85b0e09d --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.io/Test.java @@ -0,0 +1,792 @@ +package generatedtest; + +import java.io.BufferedInputStream; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.CharArrayReader; +import java.io.CharArrayWriter; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.File; +import java.io.FilterInputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.ObjectInput; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; +import java.net.URI; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; +import java.nio.file.Path; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object getThrowable_messageDefault(Object container) { + return null; + } + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "java.io;BufferedInputStream;false;BufferedInputStream;;;Argument[0];Argument[-1];taint;manual" + BufferedInputStream out = null; + InputStream in = (InputStream) source(); + out = new BufferedInputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;BufferedInputStream;false;BufferedInputStream;;;Argument[0];Argument[-1];taint;manual" + BufferedInputStream out = null; + InputStream in = (InputStream) source(); + out = new BufferedInputStream(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;BufferedReader;false;BufferedReader;;;Argument[0];Argument[-1];taint;manual" + BufferedReader out = null; + Reader in = (Reader) source(); + out = new BufferedReader(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;BufferedReader;false;BufferedReader;;;Argument[0];Argument[-1];taint;manual" + BufferedReader out = null; + Reader in = (Reader) source(); + out = new BufferedReader(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;BufferedReader;true;readLine;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + BufferedReader in = (BufferedReader) source(); + out = in.readLine(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteArrayInputStream out = null; + byte[] in = (byte[]) source(); + out = new ByteArrayInputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayInputStream;false;ByteArrayInputStream;;;Argument[0];Argument[-1];taint;manual" + ByteArrayInputStream out = null; + byte[] in = (byte[]) source(); + out = new ByteArrayInputStream(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;toByteArray;;;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + out = in.toByteArray(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + out = in.toString((Charset) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + out = in.toString((String) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + out = in.toString(0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ByteArrayOutputStream;false;writeTo;;;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + ByteArrayOutputStream in = (ByteArrayOutputStream) source(); + in.writeTo(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;CharArrayReader;false;CharArrayReader;;;Argument[0];Argument[-1];taint;manual" + CharArrayReader out = null; + char[] in = (char[]) source(); + out = new CharArrayReader(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;CharArrayReader;false;CharArrayReader;;;Argument[0];Argument[-1];taint;manual" + CharArrayReader out = null; + char[] in = (char[]) source(); + out = new CharArrayReader(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;CharArrayWriter;true;toCharArray;;;Argument[-1];ReturnValue;taint;manual" + char[] out = null; + CharArrayWriter in = (CharArrayWriter) source(); + out = in.toCharArray(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInput in = (DataInput) source(); + in.readFully(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInput in = (DataInput) source(); + in.readFully(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInputStream in = (DataInputStream) source(); + in.readFully(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInputStream in = (DataInputStream) source(); + in.readFully(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInputStream in = (ObjectInputStream) source(); + in.readFully(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readFully;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInputStream in = (ObjectInputStream) source(); + in.readFully(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readLine;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DataInput in = (DataInput) source(); + out = in.readLine(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readLine;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DataInputStream in = (DataInputStream) source(); + out = in.readLine(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readLine;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + ObjectInputStream in = (ObjectInputStream) source(); + out = in.readLine(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readUTF;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DataInput in = (DataInput) source(); + out = in.readUTF(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readUTF;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + DataInputStream in = (DataInputStream) source(); + out = in.readUTF(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInput;true;readUTF;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + ObjectInputStream in = (ObjectInputStream) source(); + out = in.readUTF(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;DataInputStream;false;DataInputStream;;;Argument[0];Argument[-1];taint;manual" + DataInputStream out = null; + InputStream in = (InputStream) source(); + out = new DataInputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[0];Argument[-1];taint;manual" + File out = null; + File in = (File) source(); + out = new File(in, (String) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[0];Argument[-1];taint;manual" + File out = null; + String in = (String) source(); + out = new File(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[0];Argument[-1];taint;manual" + File out = null; + String in = (String) source(); + out = new File(in, (String) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[0];Argument[-1];taint;manual" + File out = null; + URI in = (URI) source(); + out = new File(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[1];Argument[-1];taint;manual" + File out = null; + String in = (String) source(); + out = new File((File) null, in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;false;File;;;Argument[1];Argument[-1];taint;manual" + File out = null; + String in = (String) source(); + out = new File((String) null, in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;getAbsoluteFile;;;Argument[-1];ReturnValue;taint;manual" + File out = null; + File in = (File) source(); + out = in.getAbsoluteFile(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;getAbsolutePath;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + File in = (File) source(); + out = in.getAbsolutePath(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;getCanonicalFile;;;Argument[-1];ReturnValue;taint;manual" + File out = null; + File in = (File) source(); + out = in.getCanonicalFile(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;getCanonicalPath;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + File in = (File) source(); + out = in.getCanonicalPath(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;getName;();;Argument[-1];ReturnValue;taint;manual" + String out = null; + File in = (File) source(); + out = in.getName(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;toPath;;;Argument[-1];ReturnValue;taint;manual" + Path out = null; + File in = (File) source(); + out = in.toPath(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + File in = (File) source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;File;true;toURI;;;Argument[-1];ReturnValue;taint;manual" + URI out = null; + File in = (File) source(); + out = in.toURI(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;FilterOutputStream;true;FilterOutputStream;(OutputStream);;Argument[0];Argument[-1];taint;manual" + FilterOutputStream out = null; + OutputStream in = (OutputStream) source(); + out = new FilterOutputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;IOException;false;IOException;(String);;Argument[0];Argument[-1].SyntheticField[java.lang.Throwable.message];value;manual" + IOException out = null; + String in = (String) source(); + out = new IOException(in); + sink(getThrowable_messageDefault(out)); // $ hasValueFlow + } + { + // "java.io;InputStream;true;read;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInputStream in = (DataInputStream) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + FilterInputStream in = (FilterInputStream) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[]);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + InputStream in = (InputStream) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + BufferedInputStream in = (BufferedInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ByteArrayInputStream in = (ByteArrayInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + DataInputStream in = (DataInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + FilterInputStream in = (FilterInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + InputStream in = (InputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;read;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInputStream in = (ObjectInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;readAllBytes;;;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + ByteArrayInputStream in = (ByteArrayInputStream) source(); + out = in.readAllBytes(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;readAllBytes;;;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + InputStream in = (InputStream) source(); + out = in.readAllBytes(); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;readNBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ByteArrayInputStream in = (ByteArrayInputStream) source(); + in.readNBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;readNBytes;(byte[],int,int);;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + InputStream in = (InputStream) source(); + in.readNBytes(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;readNBytes;(int);;Argument[-1];ReturnValue;taint;manual" + byte[] out = null; + InputStream in = (InputStream) source(); + out = in.readNBytes(0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;transferTo;(OutputStream);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + ByteArrayInputStream in = (ByteArrayInputStream) source(); + in.transferTo(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStream;true;transferTo;(OutputStream);;Argument[-1];Argument[0];taint;manual" + OutputStream out = null; + InputStream in = (InputStream) source(); + in.transferTo(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStreamReader;false;InputStreamReader;;;Argument[0];Argument[-1];taint;manual" + InputStreamReader out = null; + InputStream in = (InputStream) source(); + out = new InputStreamReader(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStreamReader;false;InputStreamReader;;;Argument[0];Argument[-1];taint;manual" + InputStreamReader out = null; + InputStream in = (InputStream) source(); + out = new InputStreamReader(in, (Charset) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStreamReader;false;InputStreamReader;;;Argument[0];Argument[-1];taint;manual" + InputStreamReader out = null; + InputStream in = (InputStream) source(); + out = new InputStreamReader(in, (CharsetDecoder) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;InputStreamReader;false;InputStreamReader;;;Argument[0];Argument[-1];taint;manual" + InputStreamReader out = null; + InputStream in = (InputStream) source(); + out = new InputStreamReader(in, (String) null); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ObjectInput;true;read;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInput in = (ObjectInput) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ObjectInput;true;read;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInput in = (ObjectInput) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ObjectInput;true;read;;;Argument[-1];Argument[0];taint;manual" + byte[] out = null; + ObjectInputStream in = (ObjectInputStream) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;ObjectInputStream;false;ObjectInputStream;;;Argument[0];Argument[-1];taint;manual" + ObjectInputStream out = null; + InputStream in = (InputStream) source(); + out = new ObjectInputStream(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[]);;Argument[0];Argument[-1];taint;manual" + FilterOutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[]);;Argument[0];Argument[-1];taint;manual" + ObjectOutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[]);;Argument[0];Argument[-1];taint;manual" + OutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[]);;Argument[0];Argument[-1];taint;manual" + PrintStream out = null; + byte[] in = (byte[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + ByteArrayOutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + FilterOutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + ObjectOutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + OutputStream out = null; + byte[] in = (byte[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(byte[],int,int);;Argument[0];Argument[-1];taint;manual" + PrintStream out = null; + byte[] in = (byte[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(int);;Argument[0];Argument[-1];taint;manual" + ByteArrayOutputStream out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(int);;Argument[0];Argument[-1];taint;manual" + FilterOutputStream out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(int);;Argument[0];Argument[-1];taint;manual" + ObjectOutputStream out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(int);;Argument[0];Argument[-1];taint;manual" + OutputStream out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;OutputStream;true;write;(int);;Argument[0];Argument[-1];taint;manual" + PrintStream out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + CharBuffer out = null; + CharArrayReader in = (CharArrayReader) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + CharBuffer out = null; + InputStreamReader in = (InputStreamReader) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + CharBuffer out = null; + Reader in = (Reader) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + BufferedReader in = (BufferedReader) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + CharArrayReader in = (CharArrayReader) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + InputStreamReader in = (InputStreamReader) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + Reader in = (Reader) source(); + in.read(out); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + Reader in = (Reader) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Reader;true;read;;;Argument[-1];Argument[0];taint;manual" + char[] out = null; + StringReader in = (StringReader) source(); + in.read(out, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;StringReader;false;StringReader;;;Argument[0];Argument[-1];taint;manual" + StringReader out = null; + String in = (String) source(); + out = new StringReader(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + CharArrayWriter out = null; + String in = (String) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + CharArrayWriter out = null; + char[] in = (char[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + CharArrayWriter out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + PrintWriter out = null; + String in = (String) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + PrintWriter out = null; + String in = (String) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + PrintWriter out = null; + char[] in = (char[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + PrintWriter out = null; + char[] in = (char[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + PrintWriter out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + Writer out = null; + String in = (String) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + Writer out = null; + String in = (String) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + Writer out = null; + char[] in = (char[]) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + Writer out = null; + char[] in = (char[]) source(); + out.write(in, 0, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.io;Writer;true;write;;;Argument[0];Argument[-1];taint;manual" + Writer out = null; + int in = (int) source(); + out.write(in); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.io/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/jdk/java.io/test.ext.yml b/java/ql/test/library-tests/frameworks/jdk/java.io/test.ext.yml new file mode 100644 index 00000000000..35050f48ec0 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.io/test.ext.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-tests + extensible: summaryModel + data: + - ["generatedtest", "Test", False, "getThrowable_messageDefault", "(Object)", "", "Argument[0].SyntheticField[java.lang.Throwable.message]", "ReturnValue", "value", "manual"] diff --git a/java/ql/test/library-tests/frameworks/jdk/java.io/test.ql b/java/ql/test/library-tests/frameworks/jdk/java.io/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.io/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java b/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java index 866a6bd77d3..021549fba60 100644 --- a/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java +++ b/java/ql/test/library-tests/frameworks/jdk/java.net/Test.java @@ -1,5 +1,7 @@ package generatedtest; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.net.URLDecoder; @@ -16,6 +18,27 @@ public class Test { public void test() throws Exception { + { + // "java.net;InetAddress;true;getByName;(String);;Argument[0];ReturnValue;taint;ai-generated" + InetAddress out = null; + String in = (String) source(); + out = InetAddress.getByName(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;InetSocketAddress;true;InetSocketAddress;(String,int);;Argument[0];Argument[-1];taint;ai-generated" + InetSocketAddress out = null; + String in = (String) source(); + out = new InetSocketAddress(in, 0); + sink(out); // $ hasTaintFlow + } + { + // "java.net;InetSocketAddress;true;createUnresolved;(String,int);;Argument[0];ReturnValue;taint;ai-generated" + InetSocketAddress out = null; + String in = (String) source(); + out = InetSocketAddress.createUnresolved(in, 0); + sink(out); // $ hasTaintFlow + } { // "java.net;URI;false;URI;(String);;Argument[0];Argument[-1];taint;manual" URI out = null; @@ -30,6 +53,22 @@ public class Test { out = URI.create(in); sink(out); // $ hasTaintFlow } + { + // "java.net;URI;false;resolve;(String);;Argument[0];ReturnValue;taint;ai-generated" + URI out = null; + String in = (String) source(); + URI instance = null; + out = instance.resolve(in); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URI;false;resolve;(URI);;Argument[0];ReturnValue;taint;ai-generated" + URI out = null; + URI in = (URI) source(); + URI instance = null; + out = instance.resolve(in); + sink(out); // $ hasTaintFlow + } { // "java.net;URI;false;toASCIIString;;;Argument[-1];ReturnValue;taint;manual" String out = null; @@ -58,6 +97,20 @@ public class Test { out = new URL(in); sink(out); // $ hasTaintFlow } + { + // "java.net;URL;false;URL;(URL,String);;Argument[0];Argument[-1];taint;ai-generated" + URL out = null; + URL in = (URL) source(); + out = new URL(in, null); + sink(out); // $ hasTaintFlow + } + { + // "java.net;URL;false;URL;(URL,String);;Argument[1];Argument[-1];taint;ai-generated" + URL out = null; + String in = (String) source(); + out = new URL(null, in); + sink(out); // $ hasTaintFlow + } { // "java.net;URL;false;toExternalForm;;;Argument[-1];ReturnValue;taint;manual" String out = null; diff --git a/java/ql/test/library-tests/frameworks/jdk/java.nio.file/Test.java b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/Test.java new file mode 100644 index 00000000000..c474d68ed70 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/Test.java @@ -0,0 +1,124 @@ +package generatedtest; + +import java.io.File; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.Path; +import java.nio.file.Paths; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "java.nio.file;FileSystem;true;getPath;;;Argument[0];ReturnValue;taint;manual" + Path out = null; + String in = (String) source(); + FileSystem instance = null; + out = instance.getPath(in, (String[]) null); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;false;toFile;;;Argument[-1];ReturnValue;taint;manual" + File out = null; + Path in = (Path) source(); + out = in.toFile(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;getParent;;;Argument[-1];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + out = in.getParent(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;normalize;;;Argument[-1];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + out = in.normalize(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + Path instance = null; + out = instance.resolve(in); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + out = in.resolve((Path) null); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + out = in.resolve((String) null); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;resolve;;;Argument[-1..0];ReturnValue;taint;manual" + Path out = null; + String in = (String) source(); + Path instance = null; + out = instance.resolve(in); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;toAbsolutePath;;;Argument[-1];ReturnValue;taint;manual" + Path out = null; + Path in = (Path) source(); + out = in.toAbsolutePath(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;toString;;;Argument[-1];ReturnValue;taint;manual" + String out = null; + Path in = (Path) source(); + out = in.toString(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Path;true;toUri;;;Argument[-1];ReturnValue;taint;manual" + URI out = null; + Path in = (Path) source(); + out = in.toUri(); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Paths;true;get;;;Argument[0];ReturnValue;taint;manual" + Path out = null; + String in = (String) source(); + out = Paths.get(in, (String[]) null); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Paths;true;get;;;Argument[0];ReturnValue;taint;manual" + Path out = null; + URI in = (URI) source(); + out = Paths.get(in); + sink(out); // $ hasTaintFlow + } + { + // "java.nio.file;Paths;true;get;;;Argument[1].ArrayElement;ReturnValue;taint;manual" + Path out = null; + String[] in = (String[]) new String[] {(String) source()}; + out = Paths.get((String) null, in); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.ql b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/jdk/java.nio.file/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/netty/Test.java b/java/ql/test/library-tests/frameworks/netty/Test.java new file mode 100644 index 00000000000..938c9a9e468 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/Test.java @@ -0,0 +1,28 @@ +package generatedtest; + +import io.netty.resolver.SimpleNameResolver; +import io.netty.util.concurrent.Future; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "io.netty.resolver;SimpleNameResolver;false;resolve;(String);;Argument[0];ReturnValue;taint;ai-generated" + Future out = null; + String in = (String) source(); + SimpleNameResolver instance = null; + out = instance.resolve(in); + sink(out); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/netty/options b/java/ql/test/library-tests/frameworks/netty/options new file mode 100644 index 00000000000..84eb569be33 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/netty-4.1.x diff --git a/java/ql/test/library-tests/frameworks/netty/test.expected b/java/ql/test/library-tests/frameworks/netty/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/netty/test.ql b/java/ql/test/library-tests/frameworks/netty/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/netty/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/frameworks/okhttp/test.ql b/java/ql/test/library-tests/frameworks/okhttp/test.ql index e78af7d25bf..063f6dc4fe8 100644 --- a/java/ql/test/library-tests/frameworks/okhttp/test.ql +++ b/java/ql/test/library-tests/frameworks/okhttp/test.ql @@ -1,6 +1,10 @@ import java import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class FlowConf extends DefaultValueFlowConf { override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") } } diff --git a/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.ql b/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.ql index 9f7484028af..6e200ffa201 100644 --- a/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.ql +++ b/java/ql/test/library-tests/frameworks/rabbitmq/FlowTest.ql @@ -3,6 +3,10 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class Conf extends TaintTracking::Configuration { Conf() { this = "qltest:frameworks:rabbitmq" } diff --git a/java/ql/test/library-tests/frameworks/retrofit/test.ql b/java/ql/test/library-tests/frameworks/retrofit/test.ql index e78af7d25bf..063f6dc4fe8 100644 --- a/java/ql/test/library-tests/frameworks/retrofit/test.ql +++ b/java/ql/test/library-tests/frameworks/retrofit/test.ql @@ -1,6 +1,10 @@ import java import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class FlowConf extends DefaultValueFlowConf { override predicate isSink(DataFlow::Node n) { super.isSink(n) or sinkNode(n, "open-url") } } diff --git a/java/ql/test/library-tests/frameworks/spring/controller/test.ql b/java/ql/test/library-tests/frameworks/spring/controller/test.ql index fb180557a8c..bfd5384454b 100644 --- a/java/ql/test/library-tests/frameworks/spring/controller/test.ql +++ b/java/ql/test/library-tests/frameworks/spring/controller/test.ql @@ -2,6 +2,10 @@ import java import semmle.code.java.dataflow.FlowSources import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class ValueFlowConf extends DataFlow::Configuration { ValueFlowConf() { this = "ValueFlowConf" } diff --git a/java/ql/test/library-tests/frameworks/stapler/Test.java b/java/ql/test/library-tests/frameworks/stapler/Test.java new file mode 100644 index 00000000000..b034ec7ff40 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stapler/Test.java @@ -0,0 +1,26 @@ +package generatedtest; + +import org.kohsuke.stapler.framework.adjunct.AdjunctManager; + +// Test case generated by GenerateFlowTestCase.ql +public class Test { + + Object source() { + return null; + } + + void sink(Object o) {} + + public void test() throws Exception { + + { + // "org.kohsuke.stapler.framework.adjunct;AdjunctManager;true;AdjunctManager;(ServletContext,ClassLoader,String,long);;Argument[2];Argument[-1].Field[org.kohsuke.stapler.framework.adjunct.AdjunctManager.rootURL];taint;ai-generated" + AdjunctManager out = null; + String in = (String) source(); + out = new AdjunctManager(null, null, in, 0L); + sink(out.rootURL); // $ hasTaintFlow + } + + } + +} diff --git a/java/ql/test/library-tests/frameworks/stapler/options b/java/ql/test/library-tests/frameworks/stapler/options new file mode 100644 index 00000000000..5b75976846a --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stapler/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/apache-commons-lang:${testdir}/../../../stubs/jaxen-1.2.0 \ No newline at end of file diff --git a/java/ql/test/library-tests/frameworks/stapler/test.expected b/java/ql/test/library-tests/frameworks/stapler/test.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/library-tests/frameworks/stapler/test.ql b/java/ql/test/library-tests/frameworks/stapler/test.ql new file mode 100644 index 00000000000..5d91e4e8e26 --- /dev/null +++ b/java/ql/test/library-tests/frameworks/stapler/test.ql @@ -0,0 +1,2 @@ +import java +import TestUtilities.InlineFlowTest diff --git a/java/ql/test/library-tests/pathsanitizer/test.ql b/java/ql/test/library-tests/pathsanitizer/test.ql index c3b8ca70367..bea3af839a1 100644 --- a/java/ql/test/library-tests/pathsanitizer/test.ql +++ b/java/ql/test/library-tests/pathsanitizer/test.ql @@ -2,6 +2,10 @@ import java import semmle.code.java.security.PathSanitizer import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class PathSanitizerConf extends DefaultTaintFlowConf { override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof PathInjectionSanitizer diff --git a/java/ql/test/library-tests/printAst/A.java b/java/ql/test/library-tests/printAst/A.java index 38319c64706..4cf4e8699da 100644 --- a/java/ql/test/library-tests/printAst/A.java +++ b/java/ql/test/library-tests/printAst/A.java @@ -56,4 +56,18 @@ class A { return; } } + + enum E { + /** + * Javadoc for enum constant + */ + A, + B, + C; + } + + /** + * Javadoc for fields + */ + int i, j, k; } \ No newline at end of file diff --git a/java/ql/test/library-tests/printAst/PrintAst.expected b/java/ql/test/library-tests/printAst/PrintAst.expected index 6925a833e96..b03475b74fb 100644 --- a/java/ql/test/library-tests/printAst/PrintAst.expected +++ b/java/ql/test/library-tests/printAst/PrintAst.expected @@ -125,3 +125,30 @@ A.java: # 55| 1: [LocalVariableDeclExpr] rte # 55| 1: [BlockStmt] { ... } # 56| 0: [ReturnStmt] return ... +# 60| 10: [Class] E +# 64| 3: [FieldDeclaration] E A; +#-----| -3: (Javadoc) +# 61| 1: [Javadoc] /** Javadoc for enum constant */ +# 62| 0: [JavadocText] Javadoc for enum constant +# 64| -1: [TypeAccess] E +# 64| 0: [ClassInstanceExpr] new E(...) +# 64| -3: [TypeAccess] E +# 65| 4: [FieldDeclaration] E B; +#-----| -3: (Javadoc) +# 61| 1: [Javadoc] /** Javadoc for enum constant */ +# 62| 0: [JavadocText] Javadoc for enum constant +# 65| -1: [TypeAccess] E +# 65| 0: [ClassInstanceExpr] new E(...) +# 65| -3: [TypeAccess] E +# 66| 5: [FieldDeclaration] E C; +#-----| -3: (Javadoc) +# 61| 1: [Javadoc] /** Javadoc for enum constant */ +# 62| 0: [JavadocText] Javadoc for enum constant +# 66| -1: [TypeAccess] E +# 66| 0: [ClassInstanceExpr] new E(...) +# 66| -3: [TypeAccess] E +# 72| 11: [FieldDeclaration] int i, ...; +#-----| -3: (Javadoc) +# 69| 1: [Javadoc] /** Javadoc for fields */ +# 70| 0: [JavadocText] Javadoc for fields +# 72| -1: [TypeAccess] int diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected b/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected index e9262c2b035..456ec85f6cb 100644 --- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected +++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.expected @@ -14,7 +14,108 @@ edges | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) | | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) | | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) | -| Test.java:105:14:105:34 | getHostName(...) : String | Test.java:107:46:107:46 | t | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:61:33:68 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:41:35:48 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:56:37:63 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:46:39:53 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:38:41:45 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:36:43:43 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:31:45:38 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:33:47:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:27:49:34 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:27:50:34 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:34:51:41 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:40:53:47 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:48:54:55 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:47:55:54 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:40:57:47 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:38:59:45 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:33:61:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:33:63:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:41:65:48 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:42:67:49 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:37:69:44 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:29:71:36 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:37:73:44 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:28:75:35 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:33:77:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:40:79:47 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:40:81:47 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:40:82:47 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:38:84:45 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:28:86:35 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:28:87:35 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:28:88:35 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:34:90:41 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:34:91:41 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:33:93:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:42:95:49 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:50:97:57 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:54:99:61 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:37:104:44 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:74:106:81 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:68:108:75 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:68:110:75 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:30:112:37 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:30:117:37 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:33:122:40 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:27:124:34 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:28:126:35 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:29:128:36 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:27:133:34 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:26:135:33 | source(...) : String | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:29:140:36 | source(...) : String | +| mad/Test.java:33:61:33:68 | source(...) : String | mad/Test.java:33:52:33:68 | (...)... | +| mad/Test.java:35:41:35:48 | source(...) : String | mad/Test.java:35:32:35:48 | (...)... | +| mad/Test.java:37:56:37:63 | source(...) : String | mad/Test.java:37:47:37:63 | (...)... | +| mad/Test.java:39:46:39:53 | source(...) : String | mad/Test.java:39:39:39:53 | (...)... | +| mad/Test.java:41:38:41:45 | source(...) : String | mad/Test.java:41:31:41:45 | (...)... | +| mad/Test.java:43:36:43:43 | source(...) : String | mad/Test.java:43:29:43:43 | (...)... | +| mad/Test.java:45:31:45:38 | source(...) : String | mad/Test.java:45:24:45:38 | (...)... | +| mad/Test.java:47:33:47:40 | source(...) : String | mad/Test.java:47:24:47:40 | (...)... | +| mad/Test.java:49:27:49:34 | source(...) : String | mad/Test.java:49:20:49:34 | (...)... | +| mad/Test.java:50:27:50:34 | source(...) : String | mad/Test.java:50:20:50:34 | (...)... | +| mad/Test.java:51:34:51:41 | source(...) : String | mad/Test.java:51:20:51:41 | (...)... | +| mad/Test.java:53:40:53:47 | source(...) : String | mad/Test.java:53:33:53:47 | (...)... | +| mad/Test.java:54:48:54:55 | source(...) : String | mad/Test.java:54:33:54:55 | (...)... | +| mad/Test.java:55:47:55:54 | source(...) : String | mad/Test.java:55:40:55:54 | (...)... | +| mad/Test.java:57:40:57:47 | source(...) : String | mad/Test.java:57:33:57:47 | (...)... | +| mad/Test.java:59:38:59:45 | source(...) : String | mad/Test.java:59:31:59:45 | (...)... | +| mad/Test.java:61:33:61:40 | source(...) : String | mad/Test.java:61:26:61:40 | (...)... | +| mad/Test.java:63:33:63:40 | source(...) : String | mad/Test.java:63:26:63:40 | (...)... | +| mad/Test.java:65:41:65:48 | source(...) : String | mad/Test.java:65:34:65:48 | (...)... | +| mad/Test.java:67:42:67:49 | source(...) : String | mad/Test.java:67:35:67:49 | (...)... | +| mad/Test.java:69:37:69:44 | source(...) : String | mad/Test.java:69:30:69:44 | (...)... | +| mad/Test.java:71:29:71:36 | source(...) : String | mad/Test.java:71:22:71:36 | (...)... | +| mad/Test.java:73:37:73:44 | source(...) : String | mad/Test.java:73:30:73:44 | (...)... | +| mad/Test.java:75:28:75:35 | source(...) : String | mad/Test.java:75:21:75:35 | (...)... | +| mad/Test.java:77:33:77:40 | source(...) : String | mad/Test.java:77:26:77:40 | (...)... | +| mad/Test.java:79:40:79:47 | source(...) : String | mad/Test.java:79:33:79:47 | (...)... | +| mad/Test.java:81:40:81:47 | source(...) : String | mad/Test.java:81:33:81:47 | (...)... | +| mad/Test.java:82:40:82:47 | source(...) : String | mad/Test.java:82:33:82:47 | (...)... | +| mad/Test.java:84:38:84:45 | source(...) : String | mad/Test.java:84:31:84:45 | (...)... | +| mad/Test.java:86:28:86:35 | source(...) : String | mad/Test.java:86:21:86:35 | (...)... | +| mad/Test.java:87:28:87:35 | source(...) : String | mad/Test.java:87:21:87:35 | (...)... | +| mad/Test.java:88:28:88:35 | source(...) : String | mad/Test.java:88:21:88:35 | (...)... | +| mad/Test.java:90:34:90:41 | source(...) : String | mad/Test.java:90:27:90:41 | (...)... | +| mad/Test.java:91:34:91:41 | source(...) : String | mad/Test.java:91:27:91:41 | (...)... | +| mad/Test.java:93:33:93:40 | source(...) : String | mad/Test.java:93:26:93:40 | (...)... | +| mad/Test.java:95:42:95:49 | source(...) : String | mad/Test.java:95:35:95:49 | (...)... | +| mad/Test.java:97:50:97:57 | source(...) : String | mad/Test.java:97:41:97:57 | (...)... | +| mad/Test.java:99:54:99:61 | source(...) : String | mad/Test.java:99:45:99:61 | (...)... | +| mad/Test.java:104:37:104:44 | source(...) : String | mad/Test.java:104:30:104:44 | (...)... | +| mad/Test.java:106:74:106:81 | source(...) : String | mad/Test.java:106:40:106:81 | (...)... | +| mad/Test.java:108:68:108:75 | source(...) : String | mad/Test.java:108:34:108:75 | (...)... | +| mad/Test.java:110:68:110:75 | source(...) : String | mad/Test.java:110:34:110:75 | (...)... | +| mad/Test.java:112:30:112:37 | source(...) : String | mad/Test.java:112:23:112:37 | (...)... | +| mad/Test.java:117:30:117:37 | source(...) : String | mad/Test.java:117:23:117:37 | (...)... | +| mad/Test.java:122:33:122:40 | source(...) : String | mad/Test.java:122:23:122:40 | (...)... | +| mad/Test.java:124:27:124:34 | source(...) : String | mad/Test.java:124:20:124:34 | (...)... | +| mad/Test.java:126:28:126:35 | source(...) : String | mad/Test.java:126:21:126:35 | (...)... | +| mad/Test.java:128:29:128:36 | source(...) : String | mad/Test.java:128:22:128:36 | (...)... | +| mad/Test.java:133:27:133:34 | source(...) : String | mad/Test.java:133:20:133:34 | (...)... | +| mad/Test.java:135:26:135:33 | source(...) : String | mad/Test.java:135:19:135:33 | (...)... | +| mad/Test.java:140:29:140:36 | source(...) : String | mad/Test.java:140:20:140:36 | (...)... | nodes | Test.java:19:18:19:38 | getHostName(...) : String | semmle.label | getHostName(...) : String | | Test.java:24:20:24:23 | temp | semmle.label | temp | @@ -35,8 +136,109 @@ nodes | Test.java:99:12:99:33 | new URI(...) | semmle.label | new URI(...) | | Test.java:100:12:100:45 | new URI(...) | semmle.label | new URI(...) | | Test.java:101:12:101:54 | new URI(...) | semmle.label | new URI(...) | -| Test.java:105:14:105:34 | getHostName(...) : String | semmle.label | getHostName(...) : String | -| Test.java:107:46:107:46 | t | semmle.label | t | +| mad/Test.java:28:16:28:36 | getHostName(...) : String | semmle.label | getHostName(...) : String | +| mad/Test.java:33:52:33:68 | (...)... | semmle.label | (...)... | +| mad/Test.java:33:61:33:68 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:35:32:35:48 | (...)... | semmle.label | (...)... | +| mad/Test.java:35:41:35:48 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:37:47:37:63 | (...)... | semmle.label | (...)... | +| mad/Test.java:37:56:37:63 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:39:39:39:53 | (...)... | semmle.label | (...)... | +| mad/Test.java:39:46:39:53 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:41:31:41:45 | (...)... | semmle.label | (...)... | +| mad/Test.java:41:38:41:45 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:43:29:43:43 | (...)... | semmle.label | (...)... | +| mad/Test.java:43:36:43:43 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:45:24:45:38 | (...)... | semmle.label | (...)... | +| mad/Test.java:45:31:45:38 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:47:24:47:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:47:33:47:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:49:20:49:34 | (...)... | semmle.label | (...)... | +| mad/Test.java:49:27:49:34 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:50:20:50:34 | (...)... | semmle.label | (...)... | +| mad/Test.java:50:27:50:34 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:51:20:51:41 | (...)... | semmle.label | (...)... | +| mad/Test.java:51:34:51:41 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:53:33:53:47 | (...)... | semmle.label | (...)... | +| mad/Test.java:53:40:53:47 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:54:33:54:55 | (...)... | semmle.label | (...)... | +| mad/Test.java:54:48:54:55 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:55:40:55:54 | (...)... | semmle.label | (...)... | +| mad/Test.java:55:47:55:54 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:57:33:57:47 | (...)... | semmle.label | (...)... | +| mad/Test.java:57:40:57:47 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:59:31:59:45 | (...)... | semmle.label | (...)... | +| mad/Test.java:59:38:59:45 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:61:26:61:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:61:33:61:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:63:26:63:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:63:33:63:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:65:34:65:48 | (...)... | semmle.label | (...)... | +| mad/Test.java:65:41:65:48 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:67:35:67:49 | (...)... | semmle.label | (...)... | +| mad/Test.java:67:42:67:49 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:69:30:69:44 | (...)... | semmle.label | (...)... | +| mad/Test.java:69:37:69:44 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:71:22:71:36 | (...)... | semmle.label | (...)... | +| mad/Test.java:71:29:71:36 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:73:30:73:44 | (...)... | semmle.label | (...)... | +| mad/Test.java:73:37:73:44 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:75:21:75:35 | (...)... | semmle.label | (...)... | +| mad/Test.java:75:28:75:35 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:77:26:77:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:77:33:77:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:79:33:79:47 | (...)... | semmle.label | (...)... | +| mad/Test.java:79:40:79:47 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:81:33:81:47 | (...)... | semmle.label | (...)... | +| mad/Test.java:81:40:81:47 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:82:33:82:47 | (...)... | semmle.label | (...)... | +| mad/Test.java:82:40:82:47 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:84:31:84:45 | (...)... | semmle.label | (...)... | +| mad/Test.java:84:38:84:45 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:86:21:86:35 | (...)... | semmle.label | (...)... | +| mad/Test.java:86:28:86:35 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:87:21:87:35 | (...)... | semmle.label | (...)... | +| mad/Test.java:87:28:87:35 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:88:21:88:35 | (...)... | semmle.label | (...)... | +| mad/Test.java:88:28:88:35 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:90:27:90:41 | (...)... | semmle.label | (...)... | +| mad/Test.java:90:34:90:41 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:91:27:91:41 | (...)... | semmle.label | (...)... | +| mad/Test.java:91:34:91:41 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:93:26:93:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:93:33:93:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:95:35:95:49 | (...)... | semmle.label | (...)... | +| mad/Test.java:95:42:95:49 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:97:41:97:57 | (...)... | semmle.label | (...)... | +| mad/Test.java:97:50:97:57 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:99:45:99:61 | (...)... | semmle.label | (...)... | +| mad/Test.java:99:54:99:61 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:104:30:104:44 | (...)... | semmle.label | (...)... | +| mad/Test.java:104:37:104:44 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:106:40:106:81 | (...)... | semmle.label | (...)... | +| mad/Test.java:106:74:106:81 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:108:34:108:75 | (...)... | semmle.label | (...)... | +| mad/Test.java:108:68:108:75 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:110:34:110:75 | (...)... | semmle.label | (...)... | +| mad/Test.java:110:68:110:75 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:112:23:112:37 | (...)... | semmle.label | (...)... | +| mad/Test.java:112:30:112:37 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:117:23:117:37 | (...)... | semmle.label | (...)... | +| mad/Test.java:117:30:117:37 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:122:23:122:40 | (...)... | semmle.label | (...)... | +| mad/Test.java:122:33:122:40 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:124:20:124:34 | (...)... | semmle.label | (...)... | +| mad/Test.java:124:27:124:34 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:126:21:126:35 | (...)... | semmle.label | (...)... | +| mad/Test.java:126:28:126:35 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:128:22:128:36 | (...)... | semmle.label | (...)... | +| mad/Test.java:128:29:128:36 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:133:20:133:34 | (...)... | semmle.label | (...)... | +| mad/Test.java:133:27:133:34 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:135:19:135:33 | (...)... | semmle.label | (...)... | +| mad/Test.java:135:26:135:33 | source(...) : String | semmle.label | source(...) : String | +| mad/Test.java:140:20:140:36 | (...)... | semmle.label | (...)... | +| mad/Test.java:140:29:140:36 | source(...) : String | semmle.label | source(...) : String | subpaths #select | Test.java:24:11:24:24 | new File(...) | Test.java:19:18:19:38 | getHostName(...) : String | Test.java:24:20:24:23 | temp | This path depends on a $@. | Test.java:19:18:19:38 | getHostName(...) | user-provided value | @@ -50,4 +252,54 @@ subpaths | Test.java:99:3:99:34 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:99:12:99:33 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value | | Test.java:100:3:100:46 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:100:12:100:45 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value | | Test.java:101:3:101:55 | new File(...) | Test.java:95:14:95:34 | getHostName(...) : String | Test.java:101:12:101:54 | new URI(...) | This path depends on a $@. | Test.java:95:14:95:34 | getHostName(...) | user-provided value | -| Test.java:107:46:107:46 | t | Test.java:105:14:105:34 | getHostName(...) : String | Test.java:107:46:107:46 | t | This path depends on a $@. | Test.java:105:14:105:34 | getHostName(...) | user-provided value | +| mad/Test.java:33:52:33:68 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:33:52:33:68 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:35:32:35:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:35:32:35:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:37:47:37:63 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:37:47:37:63 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:39:39:39:53 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:39:39:39:53 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:41:31:41:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:41:31:41:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:43:29:43:43 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:43:29:43:43 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:45:24:45:38 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:45:24:45:38 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:47:9:47:41 | new FileReader(...) | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:47:24:47:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:49:20:49:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:49:20:49:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:50:20:50:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:50:20:50:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:51:20:51:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:51:20:51:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:53:33:53:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:53:33:53:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:54:33:54:55 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:54:33:54:55 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:55:40:55:54 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:55:40:55:54 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:57:33:57:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:57:33:57:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:59:31:59:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:59:31:59:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:61:26:61:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:61:26:61:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:63:26:63:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:63:26:63:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:65:34:65:48 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:65:34:65:48 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:67:35:67:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:67:35:67:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:69:30:69:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:69:30:69:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:71:22:71:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:71:22:71:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:73:30:73:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:73:30:73:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:75:21:75:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:75:21:75:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:77:26:77:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:77:26:77:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:79:33:79:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:79:33:79:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:81:33:81:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:81:33:81:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:82:33:82:47 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:82:33:82:47 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:84:31:84:45 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:84:31:84:45 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:86:21:86:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:86:21:86:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:87:21:87:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:87:21:87:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:88:21:88:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:88:21:88:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:90:27:90:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:90:27:90:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:91:27:91:41 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:91:27:91:41 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:93:26:93:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:93:26:93:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:95:35:95:49 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:95:35:95:49 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:97:41:97:57 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:97:41:97:57 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:99:45:99:61 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:99:45:99:61 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:104:30:104:44 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:104:30:104:44 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:106:40:106:81 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:106:40:106:81 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:108:34:108:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:108:34:108:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:110:34:110:75 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:110:34:110:75 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:112:23:112:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:112:23:112:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:117:23:117:37 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:117:23:117:37 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:122:23:122:40 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:122:23:122:40 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:124:20:124:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:124:20:124:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:126:21:126:35 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:126:21:126:35 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:128:22:128:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:128:22:128:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:133:20:133:34 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:133:20:133:34 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:135:19:135:33 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:135:19:135:33 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | +| mad/Test.java:140:20:140:36 | (...)... | mad/Test.java:28:16:28:36 | getHostName(...) : String | mad/Test.java:140:20:140:36 | (...)... | This path depends on a $@. | mad/Test.java:28:16:28:36 | getHostName(...) | user-provided value | diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java b/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java index 626851215e0..446c9b50a35 100644 --- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java +++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/Test.java @@ -101,9 +101,4 @@ class Test { new File(new URI(null, null, null, 0, t, null, null)); } - void doGet6(InetAddress address) throws IOException { - String t = address.getHostName(); - // BAD: accessing local resource with user input - getClass().getModule().getResourceAsStream(t); - } } diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java b/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java new file mode 100644 index 00000000000..43e5168b449 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/mad/Test.java @@ -0,0 +1,142 @@ +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import javax.xml.transform.stream.StreamResult; +import org.apache.commons.io.FileUtils; +import org.apache.tools.ant.AntClassLoader; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.taskdefs.Copy; +import org.apache.tools.ant.taskdefs.Expand; +import org.apache.tools.ant.types.FileSet; +import org.codehaus.cargo.container.installer.ZipURLInstaller; +import org.kohsuke.stapler.framework.io.LargeText; +import org.openjdk.jmh.runner.options.ChainedOptionsBuilder; + +public class Test { + + private InetAddress address; + + public Object source() { + return address.getHostName(); + } + + void test() throws IOException { + // "java.lang;Module;true;getResourceAsStream;(String);;Argument[0];read-file;ai-generated" + getClass().getModule().getResourceAsStream((String) source()); + // "java.lang;Class;false;getResource;(String);;Argument[0];read-file;ai-generated" + getClass().getResource((String) source()); + // "java.lang;ClassLoader;true;getSystemResourceAsStream;(String);;Argument[0];read-file;ai-generated" + ClassLoader.getSystemResourceAsStream((String) source()); + // "java.io;File;true;createTempFile;(String,String,File);;Argument[2];create-file;ai-generated" + File.createTempFile(";", ";", (File) source()); + // "java.io;File;true;renameTo;(File);;Argument[0];create-file;ai-generated" + new File("").renameTo((File) source()); + // "java.io;FileInputStream;true;FileInputStream;(File);;Argument[0];read-file;ai-generated" + new FileInputStream((File) source()); + // "java.io;FileReader;true;FileReader;(File);;Argument[0];read-file;ai-generated" + new FileReader((File) source()); + // "java.io;FileReader;true;FileReader;(String);;Argument[0];read-file;ai-generated" + new FileReader((String) source()); + // "java.nio.file;Files;false;copy;;;Argument[0];read-file;manual" + Files.copy((Path) source(), (Path) null); + Files.copy((Path) source(), (OutputStream) null); + Files.copy((InputStream) source(), null); + // "java.nio.file;Files;false;copy;;;Argument[1];create-file;manual" + Files.copy((Path) null, (Path) source()); + Files.copy((Path) null, (OutputStream) source()); + Files.copy((InputStream) null, (Path) source()); + // "java.nio.file;Files;false;createDirectories;;;Argument[0];create-file;manual" + Files.createDirectories((Path) source()); + // "java.nio.file;Files;false;createDirectory;;;Argument[0];create-file;manual" + Files.createDirectory((Path) source()); + // "java.nio.file;Files;false;createFile;;;Argument[0];create-file;manual" + Files.createFile((Path) source()); + // "java.nio.file;Files;false;createLink;;;Argument[0];create-file;manual" + Files.createLink((Path) source(), null); + // "java.nio.file;Files;false;createSymbolicLink;;;Argument[0];create-file;manual" + Files.createSymbolicLink((Path) source(), null); + // "java.nio.file;Files;false;createTempDirectory;(Path,String,FileAttribute[]);;Argument[0];create-file;manual" + Files.createTempDirectory((Path) source(), null); + // "java.nio.file;Files;false;createTempFile;(Path,String,String,FileAttribute[]);;Argument[0];create-file;manual" + Files.createTempFile((Path) source(), null, null); + // "java.nio.file;Files;false;delete;(Path);;Argument[0];delete-file;ai-generated" + Files.delete((Path) source()); + // "java.nio.file;Files;false;deleteIfExists;(Path);;Argument[0];delete-file;ai-generated" + Files.deleteIfExists((Path) source()); + // "java.nio.file;Files;false;lines;(Path,Charset);;Argument[0];read-file;ai-generated" + Files.lines((Path) source(), null); + // "java.nio.file;Files;false;move;;;Argument[1];create-file;manual" + Files.move(null, (Path) source()); + // "java.nio.file;Files;false;newBufferedReader;(Path,Charset);;Argument[0];read-file;ai-generated" + Files.newBufferedReader((Path) source(), null); + // "java.nio.file;Files;false;newBufferedWriter;;;Argument[0];create-file;manual" + Files.newBufferedWriter((Path) source()); + Files.newBufferedWriter((Path) source(), (Charset) null); + // "java.nio.file;Files;false;newOutputStream;;;Argument[0];create-file;manual" + Files.newOutputStream((Path) source()); + // "java.nio.file;Files;false;write;;;Argument[0];create-file;manual" + Files.write((Path) source(), (byte[]) null); + Files.write((Path) source(), (Iterable) null); + Files.write((Path) source(), (Iterable) null, (Charset) null); + // "java.nio.file;Files;false;writeString;;;Argument[0];create-file;manual" + Files.writeString((Path) source(), (CharSequence) null); + Files.writeString((Path) source(), (CharSequence) null, (Charset) null); + // "javax.xml.transform.stream;StreamResult";true;"StreamResult;(File);;Argument[0];create-file;ai-generated" + new StreamResult((File) source()); + // "org.apache.commons.io;FileUtils;true;openInputStream;(File);;Argument[0];read-file;ai-generated" + FileUtils.openInputStream((File) source()); + // "org.codehaus.cargo.container.installer;ZipURLInstaller;true;ZipURLInstaller;(URL,String,String);;Argument[1];create-file;ai-generated" + new ZipURLInstaller((URL) null, (String) source(), ""); + // "org.codehaus.cargo.container.installer;ZipURLInstaller;true;ZipURLInstaller;(URL,String,String);;Argument[2];create-file;ai-generated" + new ZipURLInstaller((URL) null, "", (String) source()); + } + + void test(AntClassLoader acl) { + // "org.apache.tools.ant;AntClassLoader;true;addPathComponent;(File);;Argument[0];read-file;ai-generated" + acl.addPathComponent((File) source()); + // "org.apache.tools.ant;AntClassLoader;true;AntClassLoader;(ClassLoader,Project,Path,boolean);;Argument[2];read-file;ai-generated" + new AntClassLoader(null, null, (org.apache.tools.ant.types.Path) source(), false); + // "org.apache.tools.ant;AntClassLoader;true;AntClassLoader;(Project,Path,boolean);;Argument[1];read-file;ai-generated" + new AntClassLoader(null, (org.apache.tools.ant.types.Path) source(), false); + // "org.apache.tools.ant;AntClassLoader;true;AntClassLoader;(Project,Path);;Argument[1];read-file;ai-generated" + new AntClassLoader(null, (org.apache.tools.ant.types.Path) source()); + // "org.kohsuke.stapler.framework.io;LargeText;true;LargeText;(File,Charset,boolean,boolean);;Argument[0];read-file;ai-generated" + new LargeText((File) source(), null, false, false); + } + + void test(DirectoryScanner ds) { + // "org.apache.tools.ant;DirectoryScanner;true;setBasedir;(File);;Argument[0];read-file;ai-generated" + ds.setBasedir((File) source()); + } + + void test(Copy cp) { + // "org.apache.tools.ant.taskdefs;Copy;true;addFileset;(FileSet);;Argument[0];read-file;ai-generated" + cp.addFileset((FileSet) source()); + // "org.apache.tools.ant.taskdefs;Copy;true;setFile;(File);;Argument[0];read-file;ai-generated" + cp.setFile((File) source()); + // "org.apache.tools.ant.taskdefs;Copy;true;setTodir;(File);;Argument[0];create-file;ai-generated" + cp.setTodir((File) source()); + // "org.apache.tools.ant.taskdefs;Copy;true;setTofile;(File);;Argument[0];create-file;ai-generated" + cp.setTofile((File) source()); + } + + void test(Expand ex) { + // "org.apache.tools.ant.taskdefs;Expand;true;setDest;(File);;Argument[0];create-file;ai-generated" + ex.setDest((File) source()); + // "org.apache.tools.ant.taskdefs;Expand;true;setSrc;(File);;Argument[0];read-file;ai-generated" + ex.setSrc((File) source()); + } + + void test(ChainedOptionsBuilder cob) { + // "org.openjdk.jmh.runner.options;ChainedOptionsBuilder;true;result;(String);;Argument[0];create-file;ai-generated" + cob.result((String) source()); + } +} diff --git a/java/ql/test/query-tests/security/CWE-022/semmle/tests/options b/java/ql/test/query-tests/security/CWE-022/semmle/tests/options index 6f216f46554..592aaf631f2 100644 --- a/java/ql/test/query-tests/security/CWE-022/semmle/tests/options +++ b/java/ql/test/query-tests/security/CWE-022/semmle/tests/options @@ -1 +1 @@ -// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6 +// semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/apache-commons-io-2.6:${testdir}/../../../../../stubs/cargo:${testdir}/../../../../../stubs/apache-ant-1.10.13:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0:${testdir}/../../../../../stubs/jmh-1.3.6 \ No newline at end of file diff --git a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql index b4009b55244..7f441e62d4e 100644 --- a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql +++ b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql @@ -2,6 +2,10 @@ import java import TestUtilities.InlineFlowTest import semmle.code.java.security.PartialPathTraversalQuery +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class TestRemoteSource extends RemoteFlowSource { TestRemoteSource() { this.asParameter().hasName(["dir", "path"]) } diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/Hive.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/Hive.java deleted file mode 100644 index 0adbd3e2c52..00000000000 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/Hive.java +++ /dev/null @@ -1,29 +0,0 @@ -import org.apache.hadoop.hive.metastore.api.ColumnStatistics; -import org.apache.hadoop.hive.metastore.api.DefaultConstraintsRequest; -import org.apache.hadoop.hive.metastore.ObjectStore; -import org.apache.hive.hcatalog.templeton.ColumnDesc; -import org.apache.hive.hcatalog.templeton.HcatDelegator; -import java.util.List; - -public class Hive { - - public static Object source() { - return null; - } - - public void test(ObjectStore objStore, HcatDelegator hcatDel) throws Exception { - { - String taint = (String) source(); - new DefaultConstraintsRequest("", taint, ""); // $ sqlInjection - } - { - ColumnStatistics taint = (ColumnStatistics) source(); - //objStore.updatePartitionColumnStatistics(taint, (List) null, (String) null, 0L); // $ sqlInjection - objStore.updatePartitionColumnStatistics(taint, (List) null); // $ sqlInjection - } - { - ColumnDesc taint = (ColumnDesc) source(); - hcatDel.addOneColumn(null, null, null, taint); // $ sqlInjection - } - } -} diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/controlledString.expected b/java/ql/test/query-tests/security/CWE-089/semmle/examples/controlledString.expected index 04494b9b570..cdb777f659e 100644 --- a/java/ql/test/query-tests/security/CWE-089/semmle/examples/controlledString.expected +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/controlledString.expected @@ -57,6 +57,7 @@ | good | 4 | Test.java:126:20:126:88 | "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=? ORDER BY PRICE" | | good | 5 | Test.java:127:62:127:67 | query2 | | good | 6 | Test.java:128:24:128:24 | 1 | +| source | 1 | mad/Test.java:11:16:11:19 | null | | tableNames | 4 | Test.java:187:32:187:56 | "SELECT ITEM,PRICE FROM " | | tableNames | 5 | Test.java:188:8:188:55 | " WHERE ITEM_CATEGORY='Biscuits' ORDER BY PRICE" | | tableNames | 10 | Test.java:193:33:193:57 | "SELECT ITEM,PRICE FROM " | @@ -97,6 +98,18 @@ | tainted | 58 | Test.java:87:8:87:15 | category | | tainted | 58 | Test.java:87:19:87:36 | "' ORDER BY PRICE" | | tainted | 59 | Test.java:88:47:88:52 | query1 | +| test | 3 | mad/Test.java:17:24:17:25 | "" | +| test | 3 | mad/Test.java:17:28:17:29 | "" | +| test | 3 | mad/Test.java:17:39:17:40 | "" | +| test | 4 | mad/Test.java:26:43:26:44 | "" | +| test | 4 | mad/Test.java:26:54:26:55 | "" | +| test | 5 | mad/Test.java:19:28:19:29 | "" | +| test | 5 | mad/Test.java:19:32:19:33 | "" | +| test | 13 | mad/Test.java:35:13:35:80 | updatePartitionColumnStatistics(...) | +| test | 13 | mad/Test.java:35:76:35:79 | null | +| test | 18 | mad/Test.java:40:34:40:37 | null | +| test | 18 | mad/Test.java:40:40:40:43 | null | +| test | 18 | mad/Test.java:40:46:40:49 | null | | unescaped | 4 | Test.java:96:28:96:81 | "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" | | unescaped | 5 | Test.java:97:23:97:40 | "' ORDER BY PRICE" | | unescaped | 11 | Test.java:103:19:103:72 | "SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" | diff --git a/java/ql/test/query-tests/security/CWE-089/semmle/examples/mad/Test.java b/java/ql/test/query-tests/security/CWE-089/semmle/examples/mad/Test.java new file mode 100644 index 00000000000..4a019c2b832 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-089/semmle/examples/mad/Test.java @@ -0,0 +1,43 @@ +import java.sql.DatabaseMetaData; +import java.util.List; +import org.apache.hadoop.hive.metastore.api.ColumnStatistics; +import org.apache.hadoop.hive.metastore.api.DefaultConstraintsRequest; +import org.apache.hadoop.hive.metastore.ObjectStore; +import org.apache.hive.hcatalog.templeton.HcatDelegator; +import org.apache.hive.hcatalog.templeton.ColumnDesc; + +public class Test { + public static Object source() { + return null; + } + + public void test(DatabaseMetaData dmd) throws Exception { + String taint = (String) source(); + // java.sql;DatabaseMetaData;true;getColumns;(String,String,String,String);;Argument[2];sql;ai-generated + dmd.getColumns("", "", taint, ""); // $ sqlInjection + // java.sql;DatabaseMetaData;true;getPrimaryKeys;(String,String,String);;Argument[2];sql;ai-generated + dmd.getPrimaryKeys("", "", taint); // $ sqlInjection + } + + public void test(ObjectStore objStore, HcatDelegator hcatDel) throws Exception { + { + String taint = (String) source(); + // "org.apache.hadoop.hive.metastore.api;DefaultConstraintsRequest;true;DefaultConstraintsRequest;(String,String,String);;Argument[1];sql;ai-generated" + new DefaultConstraintsRequest("", taint, ""); // $ sqlInjection + } + { + ColumnStatistics taint = (ColumnStatistics) source(); + // "org.apache.hadoop.hive.metastore;ObjectStore;true;updatePartitionColumnStatistics;(ColumnStatistics,List,String,long);;Argument[0];sql;ai-generated" + // @formatter:off + // objStore.updatePartitionColumnStatistics(taint, (List) null, (String) null, 0L); // $ sqlInjection + // @formatter:on + // "org.apache.hadoop.hive.metastore;ObjectStore;true;updatePartitionColumnStatistics;(ColumnStatistics,List);;Argument[0];sql;ai-generated" + objStore.updatePartitionColumnStatistics(taint, (List) null); // $ sqlInjection + } + { + ColumnDesc taint = (ColumnDesc) source(); + // "org.apache.hive.hcatalog.templeton;HcatDelegator;true;addOneColumn;(String,String,String,ColumnDesc);;Argument[3];sql;ai-generated" + hcatDel.addOneColumn(null, null, null, taint); // $ sqlInjection + } + } +} diff --git a/java/ql/test/query-tests/security/CWE-094/ApkInstallation.java b/java/ql/test/query-tests/security/CWE-094/ApkInstallation.java new file mode 100644 index 00000000000..680ad633083 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-094/ApkInstallation.java @@ -0,0 +1,58 @@ +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; + +import java.io.File; + +public class ApkInstallation extends Activity { + static final String APK_MIMETYPE = "application/vnd.android.package-archive"; + + public void installAPK(String path) { + // BAD: the path is not checked + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive"); // $ hasApkInstallation + startActivity(intent); + } + + public void installAPK3(String path) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setType(APK_MIMETYPE); + // BAD: the path is not checked + intent.setData(Uri.fromFile(new File(path))); // $ hasApkInstallation + startActivity(intent); + } + + public void installAPKFromExternalStorage(String path) { + // BAD: file is from external storage + File file = new File(Environment.getExternalStorageDirectory(), path); + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setDataAndType(Uri.fromFile(file), APK_MIMETYPE); // $ hasApkInstallation + startActivity(intent); + } + + public void installAPKFromExternalStorageWithActionInstallPackage(String path) { + // BAD: file is from external storage + File file = new File(Environment.getExternalStorageDirectory(), path); + Intent intent = new Intent(Intent.ACTION_INSTALL_PACKAGE); + intent.setData(Uri.fromFile(file)); // $ hasApkInstallation + startActivity(intent); + } + + public void installAPKInstallPackageLiteral(String path) { + File file = new File(Environment.getExternalStorageDirectory(), path); + Intent intent = new Intent("android.intent.action.INSTALL_PACKAGE"); + intent.setData(Uri.fromFile(file)); // $ hasApkInstallation + startActivity(intent); + } + + public void otherIntent(File file) { + Intent intent = new Intent(this, OtherActivity.class); + intent.setAction(Intent.ACTION_VIEW); + // BAD: the file is from unknown source + intent.setData(Uri.fromFile(file)); // $ hasApkInstallation + } +} + +class OtherActivity extends Activity { +} diff --git a/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.expected b/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.expected new file mode 100644 index 00000000000..e69de29bb2d diff --git a/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql b/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql new file mode 100644 index 00000000000..1e40c0a5d25 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-094/ApkInstallationTest.ql @@ -0,0 +1,19 @@ +import java +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.security.ArbitraryApkInstallationQuery +import TestUtilities.InlineExpectationsTest + +class HasApkInstallationTest extends InlineExpectationsTest { + HasApkInstallationTest() { this = "HasApkInstallationTest" } + + override string getARelevantTag() { result = "hasApkInstallation" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasApkInstallation" and + exists(DataFlow::Node sink | ApkInstallationFlow::hasFlowTo(sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) + } +} diff --git a/java/ql/test/query-tests/security/CWE-094/options b/java/ql/test/query-tests/security/CWE-094/options index 72dc22e6bd3..469e3df8ac0 100644 --- a/java/ql/test/query-tests/security/CWE-094/options +++ b/java/ql/test/query-tests/security/CWE-094/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api:${testdir}/../../../stubs/apache-freemarker-2.3.31:${testdir}/../../../stubs/jinjava-2.6.0:${testdir}/../../../stubs/pebble-3.1.5:${testdir}/../../../stubs/thymeleaf-3.0.14:${testdir}/../../../stubs/apache-velocity-2.3 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/validation-api-2.0.1.Final:${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/apache-commons-jexl-2.1.1:${testdir}/../../../stubs/apache-commons-jexl-3.1:${testdir}/../../../stubs/apache-commons-logging-1.2:${testdir}/../../../stubs/mvel2-2.4.7:${testdir}/../../../stubs/groovy-all-3.0.7:${testdir}/../../../stubs/servlet-api-2.4:${testdir}/../../../stubs/scriptengine:${testdir}/../../../stubs/jsr223-api:${testdir}/../../../stubs/apache-freemarker-2.3.31:${testdir}/../../../stubs/jinjava-2.6.0:${testdir}/../../../stubs/pebble-3.1.5:${testdir}/../../../stubs/thymeleaf-3.0.14:${testdir}/../../../stubs/apache-velocity-2.3:${testdir}/../../..//stubs/google-android-9.0.0 diff --git a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql index 93110ec2006..ba753b0d930 100644 --- a/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-117/LogInjectionTest.ql @@ -9,9 +9,9 @@ private class TestSource extends RemoteFlowSource { } private class LogInjectionTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override TaintTracking::Configuration getTaintFlowConfig() { - result instanceof LogInjectionConfiguration + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + LogInjectionFlow::hasFlow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql index 72b95d874d2..c434dbe413a 100644 --- a/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql +++ b/java/ql/test/query-tests/security/CWE-266/IntentUriPermissionManipulationTest.ql @@ -3,9 +3,9 @@ import TestUtilities.InlineFlowTest import semmle.code.java.security.IntentUriPermissionManipulationQuery class IntentUriPermissionManipulationTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override TaintTracking::Configuration getTaintFlowConfig() { - result instanceof IntentUriPermissionManipulationConf + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + IntentUriPermissionManipulationFlow::hasFlow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql index b2922d13d69..fb00ff33b34 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql @@ -2,6 +2,10 @@ import java import semmle.code.java.security.InsecureTrustManagerQuery import TestUtilities.InlineFlowTest +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class InsecureTrustManagerTest extends InlineFlowTest { override DataFlow::Configuration getValueFlowConfig() { result = any(InsecureTrustManagerConfiguration c) diff --git a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.expected b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.expected index 09ebc2d8b48..6c184d0516f 100644 --- a/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.expected +++ b/java/ql/test/query-tests/security/CWE-311/CWE-319/HttpsUrls.expected @@ -4,7 +4,10 @@ edges | HttpsUrlsTest.java:24:13:24:57 | new URL(...) : URL | HttpsUrlsTest.java:28:50:28:50 | u | | HttpsUrlsTest.java:24:21:24:56 | ... + ... : String | HttpsUrlsTest.java:24:13:24:57 | new URL(...) : URL | | HttpsUrlsTest.java:36:23:36:28 | "http" : String | HttpsUrlsTest.java:41:50:41:50 | u | +| HttpsUrlsTest.java:49:23:49:31 | "http://" : String | HttpsUrlsTest.java:51:64:51:98 | ... + ... : String | | HttpsUrlsTest.java:49:23:49:31 | "http://" : String | HttpsUrlsTest.java:55:50:55:50 | u | +| HttpsUrlsTest.java:51:13:51:99 | new URL(...) : URL | HttpsUrlsTest.java:55:50:55:50 | u | +| HttpsUrlsTest.java:51:64:51:98 | ... + ... : String | HttpsUrlsTest.java:51:13:51:99 | new URL(...) : URL | | HttpsUrlsTest.java:87:23:87:28 | "http" : String | HttpsUrlsTest.java:92:50:92:50 | u | nodes | HttpsUrlsTest.java:23:23:23:31 | "http://" : String | semmle.label | "http://" : String | @@ -14,6 +17,8 @@ nodes | HttpsUrlsTest.java:36:23:36:28 | "http" : String | semmle.label | "http" : String | | HttpsUrlsTest.java:41:50:41:50 | u | semmle.label | u | | HttpsUrlsTest.java:49:23:49:31 | "http://" : String | semmle.label | "http://" : String | +| HttpsUrlsTest.java:51:13:51:99 | new URL(...) : URL | semmle.label | new URL(...) : URL | +| HttpsUrlsTest.java:51:64:51:98 | ... + ... : String | semmle.label | ... + ... : String | | HttpsUrlsTest.java:55:50:55:50 | u | semmle.label | u | | HttpsUrlsTest.java:87:23:87:28 | "http" : String | semmle.label | "http" : String | | HttpsUrlsTest.java:92:50:92:50 | u | semmle.label | u | diff --git a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql index b087c0c1010..5e2046c6fbf 100644 --- a/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql +++ b/java/ql/test/query-tests/security/CWE-441/UnsafeContentUriResolutionTest.ql @@ -3,9 +3,9 @@ import TestUtilities.InlineFlowTest import semmle.code.java.security.UnsafeContentUriResolutionQuery class Test extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override TaintTracking::Configuration getTaintFlowConfig() { - result instanceof UnsafeContentResolutionConf + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + UnsafeContentResolutionFlow::hasFlow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql index 78a7cd96a33..22b02c818f5 100644 --- a/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql +++ b/java/ql/test/query-tests/security/CWE-470/FragmentInjectionTest.ql @@ -3,9 +3,9 @@ import semmle.code.java.security.FragmentInjectionQuery import TestUtilities.InlineFlowTest class Test extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override TaintTracking::Configuration getTaintFlowConfig() { - result instanceof FragmentInjectionTaintConf + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + FragmentInjectionTaintFlow::hasFlow(src, sink) } } diff --git a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql index 2d390a22d9f..aeceb941e09 100644 --- a/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql +++ b/java/ql/test/query-tests/security/CWE-489/webview-debugging/WebviewDebuggingEnabled.ql @@ -2,6 +2,10 @@ import java import TestUtilities.InlineFlowTest import semmle.code.java.security.WebviewDubuggingEnabledQuery +class EnableLegacy extends EnableLegacyConfiguration { + EnableLegacy() { exists(this) } +} + class HasFlowTest extends InlineFlowTest { override DataFlow::Configuration getTaintFlowConfig() { none() } diff --git a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql index aac128a263d..b868dcabf85 100644 --- a/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql +++ b/java/ql/test/query-tests/security/CWE-532/SensitiveLogInfo.ql @@ -3,9 +3,9 @@ import TestUtilities.InlineFlowTest import semmle.code.java.security.SensitiveLoggingQuery class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { - result instanceof SensitiveLoggerConfiguration + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + SensitiveLoggerFlow::hasFlow(src, sink) } - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } } diff --git a/java/ql/test/query-tests/security/CWE-601/semmle/tests/UrlRedirect.expected b/java/ql/test/query-tests/security/CWE-601/semmle/tests/UrlRedirect.expected index 6fa4d4a50c6..974005e801b 100644 --- a/java/ql/test/query-tests/security/CWE-601/semmle/tests/UrlRedirect.expected +++ b/java/ql/test/query-tests/security/CWE-601/semmle/tests/UrlRedirect.expected @@ -4,6 +4,8 @@ edges | UrlRedirect.java:36:58:36:89 | getParameter(...) : String | UrlRedirect.java:36:25:36:89 | ... + ... | | UrlRedirect.java:45:28:45:39 | input : String | UrlRedirect.java:46:10:46:14 | input : String | | UrlRedirect.java:46:10:46:14 | input : String | UrlRedirect.java:46:10:46:40 | replaceAll(...) : String | +| mad/Test.java:9:16:9:41 | getParameter(...) : String | mad/Test.java:14:31:14:38 | source(...) : String | +| mad/Test.java:14:31:14:38 | source(...) : String | mad/Test.java:14:22:14:38 | (...)... | nodes | UrlRedirect.java:23:25:23:54 | getParameter(...) | semmle.label | getParameter(...) | | UrlRedirect.java:32:25:32:67 | weakCleanup(...) | semmle.label | weakCleanup(...) | @@ -15,6 +17,9 @@ nodes | UrlRedirect.java:45:28:45:39 | input : String | semmle.label | input : String | | UrlRedirect.java:46:10:46:14 | input : String | semmle.label | input : String | | UrlRedirect.java:46:10:46:40 | replaceAll(...) : String | semmle.label | replaceAll(...) : String | +| mad/Test.java:9:16:9:41 | getParameter(...) : String | semmle.label | getParameter(...) : String | +| mad/Test.java:14:22:14:38 | (...)... | semmle.label | (...)... | +| mad/Test.java:14:31:14:38 | source(...) : String | semmle.label | source(...) : String | subpaths | UrlRedirect.java:32:37:32:66 | getParameter(...) : String | UrlRedirect.java:45:28:45:39 | input : String | UrlRedirect.java:46:10:46:40 | replaceAll(...) : String | UrlRedirect.java:32:25:32:67 | weakCleanup(...) | #select @@ -23,3 +28,4 @@ subpaths | UrlRedirect.java:36:25:36:89 | ... + ... | UrlRedirect.java:36:58:36:89 | getParameter(...) : String | UrlRedirect.java:36:25:36:89 | ... + ... | Untrusted URL redirection depends on a $@. | UrlRedirect.java:36:58:36:89 | getParameter(...) | user-provided value | | UrlRedirect.java:39:34:39:63 | getParameter(...) | UrlRedirect.java:39:34:39:63 | getParameter(...) | UrlRedirect.java:39:34:39:63 | getParameter(...) | Untrusted URL redirection depends on a $@. | UrlRedirect.java:39:34:39:63 | getParameter(...) | user-provided value | | UrlRedirect.java:42:43:42:72 | getParameter(...) | UrlRedirect.java:42:43:42:72 | getParameter(...) | UrlRedirect.java:42:43:42:72 | getParameter(...) | Untrusted URL redirection depends on a $@. | UrlRedirect.java:42:43:42:72 | getParameter(...) | user-provided value | +| mad/Test.java:14:22:14:38 | (...)... | mad/Test.java:9:16:9:41 | getParameter(...) : String | mad/Test.java:14:22:14:38 | (...)... | Untrusted URL redirection depends on a $@. | mad/Test.java:9:16:9:41 | getParameter(...) | user-provided value | diff --git a/java/ql/test/query-tests/security/CWE-601/semmle/tests/mad/Test.java b/java/ql/test/query-tests/security/CWE-601/semmle/tests/mad/Test.java new file mode 100644 index 00000000000..e222c3d9fbe --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-601/semmle/tests/mad/Test.java @@ -0,0 +1,16 @@ +import javax.servlet.http.HttpServletRequest; +import org.kohsuke.stapler.HttpResponses; + +public class Test { + + private static HttpServletRequest request; + + public static Object source() { + return request.getParameter(null); + } + + public void test(HttpResponses r) { + // "org.kohsuke.stapler;HttpResponses;true;redirectTo;(String);;Argument[0];open-url;ai-generated" + r.redirectTo((String) source()); + } +} diff --git a/java/ql/test/query-tests/security/CWE-601/semmle/tests/options b/java/ql/test/query-tests/security/CWE-601/semmle/tests/options index 668a863ac60..637c329a914 100644 --- a/java/ql/test/query-tests/security/CWE-601/semmle/tests/options +++ b/java/ql/test/query-tests/security/CWE-601/semmle/tests/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../../stubs/servlet-api-2.4:${testdir}/../../../../../stubs/stapler-1.263:${testdir}/../../../../../stubs/javax-servlet-2.5:${testdir}/../../../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../../../stubs/saxon-xqj-9.x:${testdir}/../../../../../stubs/apache-commons-beanutils:${testdir}/../../../../../stubs/dom4j-2.1.1:${testdir}/../../../../../stubs/apache-commons-lang:${testdir}/../../../../../stubs/jaxen-1.2.0 diff --git a/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql b/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql index 742781d2d58..e31d890d908 100644 --- a/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql +++ b/java/ql/test/query-tests/security/CWE-730/PolynomialReDoS.ql @@ -8,10 +8,10 @@ class HasPolyRedos extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasPolyRedos" and - exists(DataFlow::PathNode sink | - hasPolynomialReDoSResult(_, sink, _) and - location = sink.getNode().getLocation() and - element = sink.getNode().toString() and + exists(DataFlow::Node sink | + PolynomialRedosFlow::hasFlowTo(sink) and + location = sink.getLocation() and + element = sink.toString() and value = "" ) } diff --git a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql index bf8e8cbae21..cdfdaea621e 100644 --- a/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql +++ b/java/ql/test/query-tests/security/CWE-780/RsaWithoutOaepTest.ql @@ -4,7 +4,9 @@ import TestUtilities.InlineFlowTest import semmle.code.java.security.RsaWithoutOaepQuery class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { result instanceof RsaWithoutOaepConfig } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + RsaWithoutOaepFlow::hasFlow(src, sink) + } } diff --git a/java/ql/test/query-tests/security/CWE-918/JdbcUrlSSRF.java b/java/ql/test/query-tests/security/CWE-918/JdbcUrlSSRF.java index fa202ef0373..94704c3d862 100644 --- a/java/ql/test/query-tests/security/CWE-918/JdbcUrlSSRF.java +++ b/java/ql/test/query-tests/security/CWE-918/JdbcUrlSSRF.java @@ -20,7 +20,7 @@ public class JdbcUrlSSRF extends HttpServlet { String jdbcUrl = request.getParameter("jdbcUrl"); Driver driver = new org.postgresql.Driver(); - DataSourceBuilder dsBuilder = new DataSourceBuilder(); + DataSourceBuilder dsBuilder = DataSourceBuilder.create(); try { driver.connect(jdbcUrl, null); // $ SSRF diff --git a/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql b/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql index d7e481ce618..b27d81ee073 100644 --- a/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql +++ b/java/ql/test/query-tests/security/CWE-918/RequestForgery.ql @@ -9,7 +9,8 @@ class HasFlowTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "SSRF" and - exists(RequestForgeryConfiguration conf, DataFlow::Node sink | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | + RequestForgeryFlow::hasFlowTo(sink) and sink.getLocation() = location and element = sink.toString() and value = "" diff --git a/java/ql/test/query-tests/security/CWE-918/mad/Test.java b/java/ql/test/query-tests/security/CWE-918/mad/Test.java new file mode 100644 index 00000000000..64e81430c9c --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-918/mad/Test.java @@ -0,0 +1,77 @@ +import java.net.DatagramSocket; +import java.net.Proxy; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URL; +import java.net.URLClassLoader; +import javax.servlet.http.HttpServletRequest; +import javafx.scene.web.WebEngine; +import org.apache.commons.jelly.JellyContext; +import org.codehaus.cargo.container.installer.ZipURLInstaller; +import org.kohsuke.stapler.HttpResponses; + +public class Test { + + private static HttpServletRequest request; + + public static Object source() { + return request.getParameter(null); + } + + public void test(DatagramSocket socket) throws Exception { + // "java.net;DatagramSocket;true;connect;(SocketAddress);;Argument[0];open-url;ai-generated" + socket.connect((SocketAddress) source()); // $ SSRF + } + + public void test(URL url) throws Exception { + // "java.net;URL;false;openConnection;(Proxy);:Argument[-1]:open-url;manual" + ((URL) source()).openConnection(); // $ SSRF + // "java.net;URL;false;openConnection;(Proxy);:Argument[0]:open-url;ai-generated" + url.openConnection((Proxy) source()); // $ SSRF + // "java.net;URL;false;openStream;;:Argument[-1]:open-url;manual" + ((URL) source()).openStream(); // $ SSRF + } + + public void test(URLClassLoader cl) throws Exception { + // "java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader);;Argument[1];open-url;manual" + new URLClassLoader("", (URL[]) source(), null); // $ SSRF + // "java.net;URLClassLoader;false;URLClassLoader;(String,URL[],ClassLoader,URLStreamHandlerFactory);;Argument[1];open-url;manual" + new URLClassLoader("", (URL[]) source(), null, null); // $ SSRF + // "java.net;URLClassLoader;false;URLClassLoader;(URL[]);;Argument[0];open-url;manual" + new URLClassLoader((URL[]) source()); // $ SSRF + // "java.net;URLClassLoader;false;URLClassLoader;(URL[],ClassLoader);;Argument[0];open-url;manual" + new URLClassLoader((URL[]) source(), null); // $ SSRF + // "java.net;URLClassLoader;false;URLClassLoader;(URL[],ClassLoader,URLStreamHandlerFactory);;Argument[0];open-url;manual" + new URLClassLoader((URL[]) source(), null, null); // $ SSRF + // "java.net;URLClassLoader;false;newInstance;;;Argument[0];open-url;manual" + URLClassLoader.newInstance((URL[]) source()); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(JellyContext,URL,URL);;Argument[1];open-url;ai-generated" + new JellyContext(null, (URL) source(), null); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(JellyContext,URL,URL);;Argument[2];open-url;ai-generated" + new JellyContext(null, null, (URL) source()); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(JellyContext,URL);;Argument[1];open-url;ai-generated" + new JellyContext((JellyContext) null, (URL) source()); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(URL,URL);;Argument[0];open-url;ai-generated" + new JellyContext((URL) source(), null); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(URL,URL);;Argument[1];open-url;ai-generated" + new JellyContext((URL) null, (URL) source()); // $ SSRF + // "org.apache.commons.jelly;JellyContext;true;JellyContext;(URL);;Argument[0];open-url;ai-generated" + new JellyContext((URL) source()); // $ SSRF + } + + public void test(WebEngine webEngine) { + // "javafx.scene.web;WebEngine;false;load;(String);;Argument[0];open-url;ai-generated" + webEngine.load((String) source()); // $ SSRF + } + + public void test(ZipURLInstaller zui) { + // "org.codehaus.cargo.container.installer;ZipURLInstaller;true;ZipURLInstaller;(URL,String,String);;Argument[0];open-url:ai-generated" + new ZipURLInstaller((URL) source(), "", ""); // $ SSRF + } + + public void test(HttpResponses r) { + // "org.kohsuke.stapler;HttpResponses;true;staticResource;(URL);;Argument[0];open-url;ai-generated" + r.staticResource((URL) source()); // $ SSRF + } + +} diff --git a/java/ql/test/query-tests/security/CWE-918/options b/java/ql/test/query-tests/security/CWE-918/options index 5776b35fe9f..7a4e3251ca1 100644 --- a/java/ql/test/query-tests/security/CWE-918/options +++ b/java/ql/test/query-tests/security/CWE-918/options @@ -1,2 +1 @@ -//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/servlet-api-2.4/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/ - +//semmle-extractor-options: --javac-args -source 11 -target 11 -cp ${testdir}/../../../stubs/springframework-5.3.8:${testdir}/../../../stubs/javax-ws-rs-api-2.1.1:${testdir}/../../../stubs/javax-ws-rs-api-3.0.0:${testdir}/../../../stubs/apache-http-4.4.13/:${testdir}/../../../stubs/projectreactor-3.4.3/:${testdir}/../../../stubs/postgresql-42.3.3/:${testdir}/../../../stubs/HikariCP-3.4.5/:${testdir}/../../../stubs/spring-jdbc-5.3.8/:${testdir}/../../../stubs/jdbi3-core-3.27.2/:${testdir}/../../../stubs/cargo:${testdir}/../../../stubs/javafx-web:${testdir}/../../../stubs/apache-commons-jelly-1.0.1:${testdir}/../../../stubs/dom4j-2.1.1:${testdir}/../../../stubs/jaxen-1.2.0:${testdir}/../../../stubs/stapler-1.263:${testdir}/../../../stubs/javax-servlet-2.5:${testdir}/../../../stubs/apache-commons-fileupload-1.4:${testdir}/../../../stubs/saxon-xqj-9.x:${testdir}/../../../stubs/apache-commons-beanutils:${testdir}/../../../stubs/apache-commons-lang diff --git a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql index ae632646c96..c57c316310d 100644 --- a/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql +++ b/java/ql/test/query-tests/security/CWE-927/SensitiveCommunication.ql @@ -4,9 +4,9 @@ import TestUtilities.InlineExpectationsTest import TestUtilities.InlineFlowTest class HasFlowTest extends InlineFlowTest { - override DataFlow::Configuration getTaintFlowConfig() { - result = any(SensitiveCommunicationConfig c) - } + override predicate hasValueFlow(DataFlow::Node src, DataFlow::Node sink) { none() } - override DataFlow::Configuration getValueFlowConfig() { none() } + override predicate hasTaintFlow(DataFlow::Node src, DataFlow::Node sink) { + SensitiveCommunicationFlow::hasFlow(src, sink) + } } diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/AntClassLoader.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/AntClassLoader.java new file mode 100644 index 00000000000..94c1f368a87 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/AntClassLoader.java @@ -0,0 +1,70 @@ +// Generated automatically from org.apache.tools.ant.AntClassLoader for testing purposes + +package org.apache.tools.ant; + +import java.io.Closeable; +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.Enumeration; +import java.util.jar.Manifest; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.SubBuildListener; +import org.apache.tools.ant.types.Path; + +public class AntClassLoader extends ClassLoader implements Closeable, SubBuildListener +{ + protected Class defineClassFromData(File p0, byte[] p1, String p2){ return null; } + protected Class loadClass(String p0, boolean p1){ return null; } + protected Enumeration findResources(String p0){ return null; } + protected Enumeration findResources(String p0, boolean p1){ return null; } + protected URL findResource(String p0){ return null; } + protected URL getResourceURL(File p0, String p1){ return null; } + protected boolean isInPath(File p0){ return false; } + protected void addPathFile(File p0){} + protected void definePackage(File p0, String p1){} + protected void definePackage(File p0, String p1, Manifest p2){} + protected void log(String p0, int p1){} + public AntClassLoader(){} + public AntClassLoader(ClassLoader p0, Project p1, Path p2){} + public AntClassLoader(ClassLoader p0, Project p1, Path p2, boolean p3){} + public AntClassLoader(ClassLoader p0, boolean p1){} + public AntClassLoader(Project p0, Path p1){} + public AntClassLoader(Project p0, Path p1, boolean p2){} + public Class findClass(String p0){ return null; } + public Class forceLoadClass(String p0){ return null; } + public Class forceLoadSystemClass(String p0){ return null; } + public ClassLoader getConfiguredParent(){ return null; } + public Enumeration getNamedResources(String p0){ return null; } + public Enumeration getResources(String p0){ return null; } + public InputStream getResourceAsStream(String p0){ return null; } + public String getClasspath(){ return null; } + public String toString(){ return null; } + public URL getResource(String p0){ return null; } + public static AntClassLoader newAntClassLoader(ClassLoader p0, Project p1, Path p2, boolean p3){ return null; } + public static void initializeClass(Class p0){} + public void addJavaLibraries(){} + public void addLoaderPackageRoot(String p0){} + public void addPathComponent(File p0){} + public void addPathElement(String p0){} + public void addSystemPackageRoot(String p0){} + public void buildFinished(BuildEvent p0){} + public void buildStarted(BuildEvent p0){} + public void cleanup(){} + public void close(){} + public void messageLogged(BuildEvent p0){} + public void resetThreadContextLoader(){} + public void setClassPath(Path p0){} + public void setIsolated(boolean p0){} + public void setParent(ClassLoader p0){} + public void setParentFirst(boolean p0){} + public void setProject(Project p0){} + public void setThreadContextLoader(){} + public void subBuildFinished(BuildEvent p0){} + public void subBuildStarted(BuildEvent p0){} + public void targetFinished(BuildEvent p0){} + public void targetStarted(BuildEvent p0){} + public void taskFinished(BuildEvent p0){} + public void taskStarted(BuildEvent p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildEvent.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildEvent.java new file mode 100644 index 00000000000..e2308d35598 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildEvent.java @@ -0,0 +1,54 @@ +// Generated automatically from org.apache.tools.ant.BuildEvent for testing purposes + +package org.apache.tools.ant; + +import java.util.EventObject; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Target; +import org.apache.tools.ant.Task; + +public class BuildEvent extends EventObject { + protected BuildEvent() { + super(null); + } + + public BuildEvent(Project p0) { + super(null); + } + + public BuildEvent(Target p0) { + super(null); + } + + public BuildEvent(Task p0) { + super(null); + } + + public Project getProject() { + return null; + } + + public String getMessage() { + return null; + } + + public Target getTarget() { + return null; + } + + public Task getTask() { + return null; + } + + public Throwable getException() { + return null; + } + + public int getPriority() { + return 0; + } + + public void setException(Throwable p0) {} + + public void setMessage(String p0, int p1) {} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildException.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildException.java new file mode 100644 index 00000000000..d0293aedaa8 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildException.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.tools.ant.BuildException for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.Location; + +public class BuildException extends RuntimeException +{ + public BuildException(){} + public BuildException(String p0){} + public BuildException(String p0, Location p1){} + public BuildException(String p0, Object... p1){} + public BuildException(String p0, Throwable p1){} + public BuildException(String p0, Throwable p1, Location p2){} + public BuildException(Throwable p0){} + public BuildException(Throwable p0, Location p1){} + public Location getLocation(){ return null; } + public String toString(){ return null; } + public Throwable getException(){ return null; } + public static BuildException of(Throwable p0){ return null; } + public void setLocation(Location p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildListener.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildListener.java new file mode 100644 index 00000000000..52e425ec8c4 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/BuildListener.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.BuildListener for testing purposes + +package org.apache.tools.ant; + +import java.util.EventListener; +import org.apache.tools.ant.BuildEvent; + +public interface BuildListener extends EventListener +{ + void buildFinished(BuildEvent p0); + void buildStarted(BuildEvent p0); + void messageLogged(BuildEvent p0); + void targetFinished(BuildEvent p0); + void targetStarted(BuildEvent p0); + void taskFinished(BuildEvent p0); + void taskStarted(BuildEvent p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/DirectoryScanner.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/DirectoryScanner.java new file mode 100644 index 00000000000..9775d1e0679 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/DirectoryScanner.java @@ -0,0 +1,80 @@ +// Generated automatically from org.apache.tools.ant.DirectoryScanner for testing purposes + +package org.apache.tools.ant; + +import java.io.File; +import java.util.Vector; +import org.apache.tools.ant.FileScanner; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceFactory; +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.SelectorScanner; + +public class DirectoryScanner implements FileScanner, ResourceFactory, SelectorScanner +{ + protected File basedir = null; + protected FileSelector[] selectors = null; + protected String[] excludes = null; + protected String[] includes = null; + protected Vector dirsDeselected = null; + protected Vector dirsExcluded = null; + protected Vector dirsIncluded = null; + protected Vector dirsNotIncluded = null; + protected Vector filesDeselected = null; + protected Vector filesExcluded = null; + protected Vector filesIncluded = null; + protected Vector filesNotIncluded = null; + protected boolean couldHoldIncluded(String p0){ return false; } + protected boolean errorOnMissingDir = false; + protected boolean everythingIncluded = false; + protected boolean haveSlowResults = false; + protected boolean isCaseSensitive = false; + protected boolean isExcluded(String p0){ return false; } + protected boolean isIncluded(String p0){ return false; } + protected boolean isSelected(String p0, File p1){ return false; } + protected static String[] DEFAULTEXCLUDES = null; + protected static boolean match(String p0, String p1, boolean p2){ return false; } + protected static boolean matchPath(String p0, String p1){ return false; } + protected static boolean matchPath(String p0, String p1, boolean p2){ return false; } + protected static boolean matchPatternStart(String p0, String p1){ return false; } + protected static boolean matchPatternStart(String p0, String p1, boolean p2){ return false; } + protected void clearResults(){} + protected void scandir(File p0, String p1, boolean p2){} + protected void slowScan(){} + public DirectoryScanner(){} + public File getBasedir(){ return null; } + public Resource getResource(String p0){ return null; } + public String[] getDeselectedDirectories(){ return null; } + public String[] getDeselectedFiles(){ return null; } + public String[] getExcludedDirectories(){ return null; } + public String[] getExcludedFiles(){ return null; } + public String[] getIncludedDirectories(){ return null; } + public String[] getIncludedFiles(){ return null; } + public String[] getNotFollowedSymlinks(){ return null; } + public String[] getNotIncludedDirectories(){ return null; } + public String[] getNotIncludedFiles(){ return null; } + public boolean isCaseSensitive(){ return false; } + public boolean isEverythingIncluded(){ return false; } + public boolean isFollowSymlinks(){ return false; } + public int getIncludedDirsCount(){ return 0; } + public int getIncludedFilesCount(){ return 0; } + public static String DOES_NOT_EXIST_POSTFIX = null; + public static String[] getDefaultExcludes(){ return null; } + public static boolean addDefaultExclude(String p0){ return false; } + public static boolean match(String p0, String p1){ return false; } + public static boolean removeDefaultExclude(String p0){ return false; } + public static int MAX_LEVELS_OF_SYMLINKS = 0; + public static void resetDefaultExcludes(){} + public void addDefaultExcludes(){} + public void addExcludes(String[] p0){} + public void scan(){} + public void setBasedir(File p0){} + public void setBasedir(String p0){} + public void setCaseSensitive(boolean p0){} + public void setErrorOnMissingDir(boolean p0){} + public void setExcludes(String[] p0){} + public void setFollowSymlinks(boolean p0){} + public void setIncludes(String[] p0){} + public void setMaxLevelsOfSymlinks(int p0){} + public void setSelectors(FileSelector[] p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Executor.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Executor.java new file mode 100644 index 00000000000..90bdf1256c3 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Executor.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.tools.ant.Executor for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.Project; + +public interface Executor +{ + Executor getSubProjectExecutor(); + void executeTargets(Project p0, String[] p1); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/FileScanner.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/FileScanner.java new file mode 100644 index 00000000000..f764842ca2b --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/FileScanner.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.tools.ant.FileScanner for testing purposes + +package org.apache.tools.ant; + +import java.io.File; + +public interface FileScanner +{ + File getBasedir(); + String[] getExcludedDirectories(); + String[] getExcludedFiles(); + String[] getIncludedDirectories(); + String[] getIncludedFiles(); + String[] getNotIncludedDirectories(); + String[] getNotIncludedFiles(); + void addDefaultExcludes(); + void scan(); + void setBasedir(File p0); + void setBasedir(String p0); + void setCaseSensitive(boolean p0); + void setExcludes(String[] p0); + void setIncludes(String[] p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Location.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Location.java new file mode 100644 index 00000000000..f0b35714f17 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Location.java @@ -0,0 +1,21 @@ +// Generated automatically from org.apache.tools.ant.Location for testing purposes + +package org.apache.tools.ant; + +import java.io.Serializable; +import org.xml.sax.Locator; + +public class Location implements Serializable +{ + protected Location() {} + public Location(Locator p0){} + public Location(String p0){} + public Location(String p0, int p1, int p2){} + public String getFileName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getColumnNumber(){ return 0; } + public int getLineNumber(){ return 0; } + public int hashCode(){ return 0; } + public static Location UNKNOWN_LOCATION = null; +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Project.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Project.java new file mode 100644 index 00000000000..0ffd2a51930 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Project.java @@ -0,0 +1,157 @@ +// Generated automatically from org.apache.tools.ant.Project for testing purposes + +package org.apache.tools.ant; + +import java.io.File; +import java.io.InputStream; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; +import java.util.Vector; +import org.apache.tools.ant.AntClassLoader; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.Executor; +import org.apache.tools.ant.Target; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.input.InputHandler; +import org.apache.tools.ant.types.FilterSet; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceFactory; + +public class Project implements ResourceFactory +{ + protected void fireMessageLogged(Project p0, String p1, Throwable p2, int p3){} + protected void fireMessageLogged(Project p0, String p1, int p2){} + protected void fireMessageLogged(Target p0, String p1, Throwable p2, int p3){} + protected void fireMessageLogged(Target p0, String p1, int p2){} + protected void fireMessageLogged(Task p0, String p1, Throwable p2, int p3){} + protected void fireMessageLogged(Task p0, String p1, int p2){} + protected void fireTargetFinished(Target p0, Throwable p1){} + protected void fireTargetStarted(Target p0){} + protected void fireTaskFinished(Task p0, Throwable p1){} + protected void fireTaskStarted(Task p0){} + public T getReference(String p0){ return null; } + public AntClassLoader createClassLoader(ClassLoader p0, Path p1){ return null; } + public AntClassLoader createClassLoader(Path p0){ return null; } + public ClassLoader getCoreLoader(){ return null; } + public Executor getExecutor(){ return null; } + public File getBaseDir(){ return null; } + public File resolveFile(String p0){ return null; } + public File resolveFile(String p0, File p1){ return null; } + public FilterSet getGlobalFilterSet(){ return null; } + public Hashtable> getDataTypeDefinitions(){ return null; } + public Hashtable> getTaskDefinitions(){ return null; } + public Hashtable getInheritedProperties(){ return null; } + public Hashtable getProperties(){ return null; } + public Hashtable getReferences(){ return null; } + public Hashtable getUserProperties(){ return null; } + public Hashtable getFilters(){ return null; } + public Hashtable getTargets(){ return null; } + public InputHandler getInputHandler(){ return null; } + public InputStream getDefaultInputStream(){ return null; } + public Map> getCopyOfDataTypeDefinitions(){ return null; } + public Map> getCopyOfTaskDefinitions(){ return null; } + public Map getCopyOfReferences(){ return null; } + public Map getCopyOfTargets(){ return null; } + public Object createDataType(String p0){ return null; } + public Project createSubProject(){ return null; } + public Project(){} + public Resource getResource(String p0){ return null; } + public Set getPropertyNames(){ return null; } + public String getDefaultTarget(){ return null; } + public String getDescription(){ return null; } + public String getElementName(Object p0){ return null; } + public String getName(){ return null; } + public String getProperty(String p0){ return null; } + public String getUserProperty(String p0){ return null; } + public String replaceProperties(String p0){ return null; } + public Task createTask(String p0){ return null; } + public Task getThreadTask(Thread p0){ return null; } + public Vector getBuildListeners(){ return null; } + public boolean hasReference(String p0){ return false; } + public boolean isKeepGoingMode(){ return false; } + public final Vector topoSort(String p0, Hashtable p1){ return null; } + public final Vector topoSort(String p0, Hashtable p1, boolean p2){ return null; } + public final Vector topoSort(String[] p0, Hashtable p1, boolean p2){ return null; } + public final void setProjectReference(Object p0){} + public int defaultInput(byte[] p0, int p1, int p2){ return 0; } + public int demuxInput(byte[] p0, int p1, int p2){ return 0; } + public static Project getProject(Object p0){ return null; } + public static String JAVA_1_0 = null; + public static String JAVA_1_1 = null; + public static String JAVA_1_2 = null; + public static String JAVA_1_3 = null; + public static String JAVA_1_4 = null; + public static String TOKEN_END = null; + public static String TOKEN_START = null; + public static String getJavaVersion(){ return null; } + public static String translatePath(String p0){ return null; } + public static boolean toBoolean(String p0){ return false; } + public static int MSG_DEBUG = 0; + public static int MSG_ERR = 0; + public static int MSG_INFO = 0; + public static int MSG_VERBOSE = 0; + public static int MSG_WARN = 0; + public void addBuildListener(BuildListener p0){} + public void addDataTypeDefinition(String p0, Class p1){} + public void addFilter(String p0, String p1){} + public void addIdReference(String p0, Object p1){} + public void addOrReplaceTarget(String p0, Target p1){} + public void addOrReplaceTarget(Target p0){} + public void addReference(String p0, Object p1){} + public void addTarget(String p0, Target p1){} + public void addTarget(Target p0){} + public void addTaskDefinition(String p0, Class p1){} + public void checkTaskClass(Class p0){} + public void copyFile(File p0, File p1){} + public void copyFile(File p0, File p1, boolean p2){} + public void copyFile(File p0, File p1, boolean p2, boolean p3){} + public void copyFile(File p0, File p1, boolean p2, boolean p3, boolean p4){} + public void copyFile(String p0, String p1){} + public void copyFile(String p0, String p1, boolean p2){} + public void copyFile(String p0, String p1, boolean p2, boolean p3){} + public void copyFile(String p0, String p1, boolean p2, boolean p3, boolean p4){} + public void copyInheritedProperties(Project p0){} + public void copyUserProperties(Project p0){} + public void demuxFlush(String p0, boolean p1){} + public void demuxOutput(String p0, boolean p1){} + public void executeSortedTargets(Vector p0){} + public void executeTarget(String p0){} + public void executeTargets(Vector p0){} + public void fireBuildFinished(Throwable p0){} + public void fireBuildStarted(){} + public void fireSubBuildFinished(Throwable p0){} + public void fireSubBuildStarted(){} + public void inheritIDReferences(Project p0){} + public void init(){} + public void initProperties(){} + public void initSubProject(Project p0){} + public void log(String p0){} + public void log(String p0, Throwable p1, int p2){} + public void log(String p0, int p1){} + public void log(Target p0, String p1, Throwable p2, int p3){} + public void log(Target p0, String p1, int p2){} + public void log(Task p0, String p1, Throwable p2, int p3){} + public void log(Task p0, String p1, int p2){} + public void registerThreadTask(Thread p0, Task p1){} + public void removeBuildListener(BuildListener p0){} + public void setBaseDir(File p0){} + public void setBasedir(String p0){} + public void setCoreLoader(ClassLoader p0){} + public void setDefault(String p0){} + public void setDefaultInputStream(InputStream p0){} + public void setDefaultTarget(String p0){} + public void setDescription(String p0){} + public void setExecutor(Executor p0){} + public void setFileLastModified(File p0, long p1){} + public void setInheritedProperty(String p0, String p1){} + public void setInputHandler(InputHandler p0){} + public void setJavaVersionProperty(){} + public void setKeepGoingMode(boolean p0){} + public void setName(String p0){} + public void setNewProperty(String p0, String p1){} + public void setProperty(String p0, String p1){} + public void setSystemProperties(){} + public void setUserProperty(String p0, String p1){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/ProjectComponent.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/ProjectComponent.java new file mode 100644 index 00000000000..f2797ca8cac --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/ProjectComponent.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.tools.ant.ProjectComponent for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.Location; +import org.apache.tools.ant.Project; + +abstract public class ProjectComponent implements Cloneable +{ + protected Location location = null; + protected Project project = null; + protected String description = null; + public Location getLocation(){ return null; } + public Object clone(){ return null; } + public Project getProject(){ return null; } + public ProjectComponent(){} + public String getDescription(){ return null; } + public void log(String p0){} + public void log(String p0, int p1){} + public void setDescription(String p0){} + public void setLocation(Location p0){} + public void setProject(Project p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/RuntimeConfigurable.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/RuntimeConfigurable.java new file mode 100644 index 00000000000..f4e7d8e9df3 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/RuntimeConfigurable.java @@ -0,0 +1,39 @@ +// Generated automatically from org.apache.tools.ant.RuntimeConfigurable for testing purposes + +package org.apache.tools.ant; + +import java.io.Serializable; +import java.util.Enumeration; +import java.util.Hashtable; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.UnknownElement; +import org.xml.sax.AttributeList; + +public class RuntimeConfigurable implements Serializable +{ + protected RuntimeConfigurable() {} + public AttributeList getAttributes(){ return null; } + public Enumeration getChildren(){ return null; } + public Hashtable getAttributeMap(){ return null; } + public Object getProxy(){ return null; } + public RuntimeConfigurable(Object p0, String p1){} + public String getElementTag(){ return null; } + public String getId(){ return null; } + public String getPolyType(){ return null; } + public StringBuffer getText(){ return null; } + public boolean isEnabled(UnknownElement p0){ return false; } + public void addChild(RuntimeConfigurable p0){} + public void addText(String p0){} + public void addText(char[] p0, int p1, int p2){} + public void applyPreSet(RuntimeConfigurable p0){} + public void maybeConfigure(Project p0){} + public void maybeConfigure(Project p0, boolean p1){} + public void reconfigure(Project p0){} + public void removeAttribute(String p0){} + public void setAttribute(String p0, Object p1){} + public void setAttribute(String p0, String p1){} + public void setAttributes(AttributeList p0){} + public void setElementTag(String p0){} + public void setPolyType(String p0){} + public void setProxy(Object p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/SubBuildListener.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/SubBuildListener.java new file mode 100644 index 00000000000..fcf6781411b --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/SubBuildListener.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.SubBuildListener for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildListener; + +public interface SubBuildListener extends BuildListener +{ + void subBuildFinished(BuildEvent p0); + void subBuildStarted(BuildEvent p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Target.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Target.java new file mode 100644 index 00000000000..66cc237d150 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Target.java @@ -0,0 +1,43 @@ +// Generated automatically from org.apache.tools.ant.Target for testing purposes + +package org.apache.tools.ant; + +import java.util.Enumeration; +import java.util.List; +import org.apache.tools.ant.Location; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.RuntimeConfigurable; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.TaskContainer; +import org.apache.tools.ant.taskdefs.condition.Condition; + +public class Target implements TaskContainer +{ + public Enumeration getDependencies(){ return null; } + public Location getLocation(){ return null; } + public Project getProject(){ return null; } + public String getDescription(){ return null; } + public String getIf(){ return null; } + public String getName(){ return null; } + public String getUnless(){ return null; } + public String toString(){ return null; } + public Target(){} + public Target(Target p0){} + public Task[] getTasks(){ return null; } + public boolean dependsOn(String p0){ return false; } + public final void performTasks(){} + public static List parseDepends(String p0, String p1, String p2){ return null; } + public void addDataType(RuntimeConfigurable p0){} + public void addDependency(String p0){} + public void addTask(Task p0){} + public void execute(){} + public void setDepends(String p0){} + public void setDescription(String p0){} + public void setIf(Condition p0){} + public void setIf(String p0){} + public void setLocation(Location p0){} + public void setName(String p0){} + public void setProject(Project p0){} + public void setUnless(Condition p0){} + public void setUnless(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Task.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Task.java new file mode 100644 index 00000000000..89ec1160c28 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/Task.java @@ -0,0 +1,41 @@ +// Generated automatically from org.apache.tools.ant.Task for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.RuntimeConfigurable; +import org.apache.tools.ant.Target; + +abstract public class Task extends ProjectComponent +{ + protected RuntimeConfigurable getWrapper(){ return null; } + protected RuntimeConfigurable wrapper = null; + protected String taskName = null; + protected String taskType = null; + protected Target target = null; + protected final boolean isInvalid(){ return false; } + protected int handleInput(byte[] p0, int p1, int p2){ return 0; } + protected void handleErrorFlush(String p0){} + protected void handleErrorOutput(String p0){} + protected void handleFlush(String p0){} + protected void handleOutput(String p0){} + public RuntimeConfigurable getRuntimeConfigurableWrapper(){ return null; } + public String getTaskName(){ return null; } + public String getTaskType(){ return null; } + public Target getOwningTarget(){ return null; } + public Task(){} + public final void bindToOwner(Task p0){} + public final void perform(){} + public void execute(){} + public void init(){} + public void log(String p0){} + public void log(String p0, Throwable p1, int p2){} + public void log(String p0, int p1){} + public void log(Throwable p0, int p1){} + public void maybeConfigure(){} + public void reconfigure(){} + public void setOwningTarget(Target p0){} + public void setRuntimeConfigurableWrapper(RuntimeConfigurable p0){} + public void setTaskName(String p0){} + public void setTaskType(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/TaskContainer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/TaskContainer.java new file mode 100644 index 00000000000..891d87078a8 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/TaskContainer.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.TaskContainer for testing purposes + +package org.apache.tools.ant; + +import org.apache.tools.ant.Task; + +public interface TaskContainer +{ + void addTask(Task p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/UnknownElement.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/UnknownElement.java new file mode 100644 index 00000000000..6775244c857 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/UnknownElement.java @@ -0,0 +1,43 @@ +// Generated automatically from org.apache.tools.ant.UnknownElement for testing purposes + +package org.apache.tools.ant; + +import java.util.List; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.RuntimeConfigurable; +import org.apache.tools.ant.Task; + +public class UnknownElement extends Task +{ + protected UnknownElement() {} + protected BuildException getNotFoundException(String p0, String p1){ return null; } + protected Object makeObject(UnknownElement p0, RuntimeConfigurable p1){ return null; } + protected String getComponentName(){ return null; } + protected Task makeTask(UnknownElement p0, RuntimeConfigurable p1){ return null; } + protected int handleInput(byte[] p0, int p1, int p2){ return 0; } + protected void handleChildren(Object p0, RuntimeConfigurable p1){} + protected void handleErrorFlush(String p0){} + protected void handleErrorOutput(String p0){} + protected void handleFlush(String p0){} + protected void handleOutput(String p0){} + public List getChildren(){ return null; } + public Object getRealThing(){ return null; } + public RuntimeConfigurable getWrapper(){ return null; } + public String getNamespace(){ return null; } + public String getQName(){ return null; } + public String getTag(){ return null; } + public String getTaskName(){ return null; } + public Task getTask(){ return null; } + public UnknownElement copy(Project p0){ return null; } + public UnknownElement(String p0){} + public boolean similar(Object p0){ return false; } + public void addChild(UnknownElement p0){} + public void applyPreSet(UnknownElement p0){} + public void configure(Object p0){} + public void execute(){} + public void maybeConfigure(){} + public void setNamespace(String p0){} + public void setQName(String p0){} + public void setRealThing(Object p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseFilterReader.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseFilterReader.java new file mode 100644 index 00000000000..a11e4870f35 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseFilterReader.java @@ -0,0 +1,45 @@ +// Generated automatically from org.apache.tools.ant.filters.BaseFilterReader for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.FilterReader; +import java.io.Reader; +import org.apache.tools.ant.Project; + +abstract public class BaseFilterReader extends FilterReader { + protected final Project getProject() { + return null; + } + + protected final String readFully() { + return null; + } + + protected final String readLine() { + return null; + } + + protected final boolean getInitialized() { + return false; + } + + protected final void setInitialized(boolean p0) {} + + public BaseFilterReader() { + super(null); + } + + public BaseFilterReader(Reader p0) { + super(null); + } + + public final int read(char[] p0, int p1, int p2) { + return 0; + } + + public final long skip(long p0) { + return 0; + } + + public final void setProject(Project p0) {} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseParamFilterReader.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseParamFilterReader.java new file mode 100644 index 00000000000..bde1ac20333 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/BaseParamFilterReader.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.filters.BaseParamFilterReader for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Parameterizable; + +abstract public class BaseParamFilterReader extends BaseFilterReader implements Parameterizable +{ + protected final Parameter[] getParameters(){ return null; } + public BaseParamFilterReader(){} + public BaseParamFilterReader(Reader p0){} + public final void setParameters(Parameter... p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ChainableReader.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ChainableReader.java new file mode 100644 index 00000000000..124918a519a --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ChainableReader.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.filters.ChainableReader for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; + +public interface ChainableReader +{ + Reader chain(Reader p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ClassConstants.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ClassConstants.java new file mode 100644 index 00000000000..8c4e0caef48 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ClassConstants.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.ant.filters.ClassConstants for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class ClassConstants extends BaseFilterReader implements ChainableReader +{ + public ClassConstants(){} + public ClassConstants(Reader p0){} + public Reader chain(Reader p0){ return null; } + public int read(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/EscapeUnicode.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/EscapeUnicode.java new file mode 100644 index 00000000000..6b3b0536434 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/EscapeUnicode.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.ant.filters.EscapeUnicode for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class EscapeUnicode extends BaseParamFilterReader implements ChainableReader +{ + public EscapeUnicode(){} + public EscapeUnicode(Reader p0){} + public final Reader chain(Reader p0){ return null; } + public final int read(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ExpandProperties.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ExpandProperties.java new file mode 100644 index 00000000000..39b02d641b3 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ExpandProperties.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.filters.ExpandProperties for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.types.PropertySet; + +public class ExpandProperties extends BaseFilterReader implements ChainableReader +{ + public ExpandProperties(){} + public ExpandProperties(Reader p0){} + public Reader chain(Reader p0){ return null; } + public int read(){ return 0; } + public void add(PropertySet p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/HeadFilter.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/HeadFilter.java new file mode 100644 index 00000000000..c26685b2ff9 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/HeadFilter.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.filters.HeadFilter for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class HeadFilter extends BaseParamFilterReader implements ChainableReader +{ + public HeadFilter(){} + public HeadFilter(Reader p0){} + public Reader chain(Reader p0){ return null; } + public int read(){ return 0; } + public void setLines(long p0){} + public void setSkip(long p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContains.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContains.java new file mode 100644 index 00000000000..18da8e830f4 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContains.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.tools.ant.filters.LineContains for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class LineContains extends BaseParamFilterReader implements ChainableReader +{ + public LineContains(){} + public LineContains(Reader p0){} + public Reader chain(Reader p0){ return null; } + public boolean isMatchAny(){ return false; } + public boolean isNegated(){ return false; } + public int read(){ return 0; } + public void addConfiguredContains(LineContains.Contains p0){} + public void setMatchAny(boolean p0){} + public void setNegate(boolean p0){} + static public class Contains + { + public Contains(){} + public final String getValue(){ return null; } + public final void setValue(String p0){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContainsRegExp.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContainsRegExp.java new file mode 100644 index 00000000000..69caa9a580d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/LineContainsRegExp.java @@ -0,0 +1,21 @@ +// Generated automatically from org.apache.tools.ant.filters.LineContainsRegExp for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.types.RegularExpression; + +public class LineContainsRegExp extends BaseParamFilterReader implements ChainableReader +{ + public LineContainsRegExp(){} + public LineContainsRegExp(Reader p0){} + public Reader chain(Reader p0){ return null; } + public boolean isNegated(){ return false; } + public int read(){ return 0; } + public void addConfiguredRegexp(RegularExpression p0){} + public void setCaseSensitive(boolean p0){} + public void setNegate(boolean p0){} + public void setRegexp(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/PrefixLines.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/PrefixLines.java new file mode 100644 index 00000000000..5f976632eab --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/PrefixLines.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.filters.PrefixLines for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class PrefixLines extends BaseParamFilterReader implements ChainableReader +{ + public PrefixLines(){} + public PrefixLines(Reader p0){} + public Reader chain(Reader p0){ return null; } + public int read(){ return 0; } + public void setPrefix(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ReplaceTokens.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ReplaceTokens.java new file mode 100644 index 00000000000..d467024f676 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/ReplaceTokens.java @@ -0,0 +1,28 @@ +// Generated automatically from org.apache.tools.ant.filters.ReplaceTokens for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.types.Resource; + +public class ReplaceTokens extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public ReplaceTokens(){} + public ReplaceTokens(Reader p0){} + public int read(){ return 0; } + public void addConfiguredToken(ReplaceTokens.Token p0){} + public void setBeginToken(String p0){} + public void setEndToken(String p0){} + public void setPropertiesResource(Resource p0){} + static public class Token + { + public Token(){} + public final String getKey(){ return null; } + public final String getValue(){ return null; } + public final void setKey(String p0){} + public final void setValue(String p0){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripJavaComments.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripJavaComments.java new file mode 100644 index 00000000000..6ed04cb1ea8 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripJavaComments.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.ant.filters.StripJavaComments for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class StripJavaComments extends BaseFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public StripJavaComments(){} + public StripJavaComments(Reader p0){} + public int read(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineBreaks.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineBreaks.java new file mode 100644 index 00000000000..f82f45979f4 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineBreaks.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.filters.StripLineBreaks for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class StripLineBreaks extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public StripLineBreaks(){} + public StripLineBreaks(Reader p0){} + public int read(){ return 0; } + public void setLineBreaks(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineComments.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineComments.java new file mode 100644 index 00000000000..f2f6bbc2535 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/StripLineComments.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.tools.ant.filters.StripLineComments for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class StripLineComments extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public StripLineComments(){} + public StripLineComments(Reader p0){} + public int read(){ return 0; } + public void addConfiguredComment(StripLineComments.Comment p0){} + static public class Comment + { + public Comment(){} + public final String getValue(){ return null; } + public final void setValue(String p0){} + public void addText(String p0){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/SuffixLines.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/SuffixLines.java new file mode 100644 index 00000000000..bed26cc32e7 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/SuffixLines.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.filters.SuffixLines for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class SuffixLines extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public SuffixLines(){} + public SuffixLines(Reader p0){} + public int read(){ return 0; } + public void setSuffix(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TabsToSpaces.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TabsToSpaces.java new file mode 100644 index 00000000000..1ba4a1f41d5 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TabsToSpaces.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.filters.TabsToSpaces for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class TabsToSpaces extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public TabsToSpaces(){} + public TabsToSpaces(Reader p0){} + public int read(){ return 0; } + public void setTablength(int p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TailFilter.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TailFilter.java new file mode 100644 index 00000000000..48311a48b50 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TailFilter.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.filters.TailFilter for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.filters.BaseParamFilterReader; +import org.apache.tools.ant.filters.ChainableReader; + +public class TailFilter extends BaseParamFilterReader implements ChainableReader +{ + public Reader chain(Reader p0){ return null; } + public TailFilter(){} + public TailFilter(Reader p0){} + public int read(){ return 0; } + public void setLines(long p0){} + public void setSkip(long p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TokenFilter.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TokenFilter.java new file mode 100644 index 00000000000..4321d0646b6 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/filters/TokenFilter.java @@ -0,0 +1,97 @@ +// Generated automatically from org.apache.tools.ant.filters.TokenFilter for testing purposes + +package org.apache.tools.ant.filters; + +import java.io.Reader; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.filters.BaseFilterReader; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.util.LineTokenizer; +import org.apache.tools.ant.util.Tokenizer; + +public class TokenFilter extends BaseFilterReader implements ChainableReader +{ + abstract static public class ChainableReaderFilter extends ProjectComponent implements ChainableReader, TokenFilter.Filter + { + public ChainableReaderFilter(){} + public Reader chain(Reader p0){ return null; } + public void setByLine(boolean p0){} + } + public TokenFilter(){} + public TokenFilter(Reader p0){} + public final Reader chain(Reader p0){ return null; } + public int read(){ return 0; } + public static String resolveBackSlash(String p0){ return null; } + public static int convertRegexOptions(String p0){ return 0; } + public void add(TokenFilter.Filter p0){} + public void add(Tokenizer p0){} + public void addContainsRegex(TokenFilter.ContainsRegex p0){} + public void addContainsString(TokenFilter.ContainsString p0){} + public void addDeleteCharacters(TokenFilter.DeleteCharacters p0){} + public void addFileTokenizer(TokenFilter.FileTokenizer p0){} + public void addIgnoreBlank(TokenFilter.IgnoreBlank p0){} + public void addLineTokenizer(LineTokenizer p0){} + public void addReplaceRegex(TokenFilter.ReplaceRegex p0){} + public void addReplaceString(TokenFilter.ReplaceString p0){} + public void addStringTokenizer(TokenFilter.StringTokenizer p0){} + public void addTrim(TokenFilter.Trim p0){} + public void setDelimOutput(String p0){} + static public class ContainsRegex extends TokenFilter.ChainableReaderFilter + { + public ContainsRegex(){} + public String filter(String p0){ return null; } + public void setFlags(String p0){} + public void setPattern(String p0){} + public void setReplace(String p0){} + } + static public class ContainsString extends ProjectComponent implements TokenFilter.Filter + { + public ContainsString(){} + public String filter(String p0){ return null; } + public void setContains(String p0){} + } + static public class DeleteCharacters extends ProjectComponent implements ChainableReader, TokenFilter.Filter + { + public DeleteCharacters(){} + public Reader chain(Reader p0){ return null; } + public String filter(String p0){ return null; } + public void setChars(String p0){} + } + static public class FileTokenizer extends org.apache.tools.ant.util.FileTokenizer + { + public FileTokenizer(){} + } + static public class IgnoreBlank extends TokenFilter.ChainableReaderFilter + { + public IgnoreBlank(){} + public String filter(String p0){ return null; } + } + static public class ReplaceRegex extends TokenFilter.ChainableReaderFilter + { + public ReplaceRegex(){} + public String filter(String p0){ return null; } + public void setFlags(String p0){} + public void setPattern(String p0){} + public void setReplace(String p0){} + } + static public class ReplaceString extends TokenFilter.ChainableReaderFilter + { + public ReplaceString(){} + public String filter(String p0){ return null; } + public void setFrom(String p0){} + public void setTo(String p0){} + } + static public class StringTokenizer extends org.apache.tools.ant.util.StringTokenizer + { + public StringTokenizer(){} + } + static public class Trim extends TokenFilter.ChainableReaderFilter + { + public String filter(String p0){ return null; } + public Trim(){} + } + static public interface Filter + { + String filter(String p0); + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputHandler.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputHandler.java new file mode 100644 index 00000000000..ace9bd44eae --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputHandler.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.input.InputHandler for testing purposes + +package org.apache.tools.ant.input; + +import org.apache.tools.ant.input.InputRequest; + +public interface InputHandler +{ + void handleInput(InputRequest p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputRequest.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputRequest.java new file mode 100644 index 00000000000..7aec15ca58a --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/input/InputRequest.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.input.InputRequest for testing purposes + +package org.apache.tools.ant.input; + + +public class InputRequest +{ + protected InputRequest() {} + public InputRequest(String p0){} + public String getDefaultValue(){ return null; } + public String getInput(){ return null; } + public String getPrompt(){ return null; } + public boolean isInputValid(){ return false; } + public void setDefaultValue(String p0){} + public void setInput(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Copy.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Copy.java new file mode 100644 index 00000000000..4b183f6403f --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Copy.java @@ -0,0 +1,79 @@ +// Generated automatically from org.apache.tools.ant.taskdefs.Copy for testing purposes + +package org.apache.tools.ant.taskdefs; + +import java.io.File; +import java.util.Hashtable; +import java.util.Map; +import java.util.Vector; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.FilterChain; +import org.apache.tools.ant.types.FilterSet; +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.util.FileNameMapper; +import org.apache.tools.ant.util.FileUtils; + +public class Copy extends Task +{ + protected File destDir = null; + protected File destFile = null; + protected File file = null; + protected FileUtils fileUtils = null; + protected FileUtils getFileUtils(){ return null; } + protected Hashtable completeDirMap = null; + protected Hashtable dirCopyMap = null; + protected Hashtable fileCopyMap = null; + protected Map buildMap(Resource[] p0, File p1, FileNameMapper p2){ return null; } + protected Map scan(Resource[] p0, File p1){ return null; } + protected Mapper mapperElement = null; + protected Vector getFilterChains(){ return null; } + protected Vector getFilterSets(){ return null; } + protected Vector filesets = null; + protected Vector rcs = null; + protected boolean failonerror = false; + protected boolean filtering = false; + protected boolean flatten = false; + protected boolean forceOverwrite = false; + protected boolean includeEmpty = false; + protected boolean preserveLastModified = false; + protected boolean supportsNonFileResources(){ return false; } + protected int verbosity = 0; + protected void buildMap(File p0, File p1, String[] p2, FileNameMapper p3, Hashtable p4){} + protected void doFileOperations(){} + protected void doResourceOperations(Map p0){} + protected void scan(File p0, File p1, String[] p2, String[] p3){} + protected void validateAttributes(){} + public Copy(){} + public FilterChain createFilterChain(){ return null; } + public FilterSet createFilterSet(){ return null; } + public Mapper createMapper(){ return null; } + public String getEncoding(){ return null; } + public String getOutputEncoding(){ return null; } + public boolean getForce(){ return false; } + public boolean getPreserveLastModified(){ return false; } + public boolean isEnableMultipleMapping(){ return false; } + public void add(FileNameMapper p0){} + public void add(ResourceCollection p0){} + public void addFileset(FileSet p0){} + public void execute(){} + public void setEnableMultipleMappings(boolean p0){} + public void setEncoding(String p0){} + public void setFailOnError(boolean p0){} + public void setFile(File p0){} + public void setFiltering(boolean p0){} + public void setFlatten(boolean p0){} + public void setForce(boolean p0){} + public void setGranularity(long p0){} + public void setIncludeEmptyDirs(boolean p0){} + public void setOutputEncoding(String p0){} + public void setOverwrite(boolean p0){} + public void setPreserveLastModified(String p0){} + public void setPreserveLastModified(boolean p0){} + public void setQuiet(boolean p0){} + public void setTodir(File p0){} + public void setTofile(File p0){} + public void setVerbose(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Expand.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Expand.java new file mode 100644 index 00000000000..6ed748dba40 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/Expand.java @@ -0,0 +1,47 @@ +// Generated automatically from org.apache.tools.ant.taskdefs.Expand for testing purposes + +package org.apache.tools.ant.taskdefs; + +import java.io.File; +import java.io.InputStream; +import java.util.Date; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.PatternSet; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.util.FileNameMapper; +import org.apache.tools.ant.util.FileUtils; + +public class Expand extends Task +{ + protected Expand(String p0){} + protected FileNameMapper getMapper(){ return null; } + protected void expandFile(FileUtils p0, File p1, File p2){} + protected void expandResource(Resource p0, File p1){} + protected void extractFile(FileUtils p0, File p1, File p2, InputStream p3, String p4, Date p5, boolean p6, FileNameMapper p7){} + protected void internalSetEncoding(String p0){} + protected void internalSetScanForUnicodeExtraFields(boolean p0){} + public Boolean getAllowFilesToEscapeDest(){ return null; } + public Expand(){} + public Mapper createMapper(){ return null; } + public String getEncoding(){ return null; } + public boolean getFailOnEmptyArchive(){ return false; } + public boolean getScanForUnicodeExtraFields(){ return false; } + public static String ERROR_MULTIPLE_MAPPERS = null; + public static String NATIVE_ENCODING = null; + public void add(FileNameMapper p0){} + public void add(ResourceCollection p0){} + public void addFileset(FileSet p0){} + public void addPatternset(PatternSet p0){} + public void execute(){} + public void setAllowFilesToEscapeDest(boolean p0){} + public void setDest(File p0){} + public void setEncoding(String p0){} + public void setFailOnEmptyArchive(boolean p0){} + public void setOverwrite(boolean p0){} + public void setScanForUnicodeExtraFields(boolean p0){} + public void setSrc(File p0){} + public void setStripAbsolutePathSpec(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/condition/Condition.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/condition/Condition.java new file mode 100644 index 00000000000..787680f3269 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/taskdefs/condition/Condition.java @@ -0,0 +1,9 @@ +// Generated automatically from org.apache.tools.ant.taskdefs.condition.Condition for testing purposes + +package org.apache.tools.ant.taskdefs.condition; + + +public interface Condition +{ + boolean eval(); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AbstractFileSet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AbstractFileSet.java new file mode 100644 index 00000000000..22c815d7501 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AbstractFileSet.java @@ -0,0 +1,115 @@ +// Generated automatically from org.apache.tools.ant.types.AbstractFileSet for testing purposes + +package org.apache.tools.ant.types; + +import java.io.File; +import java.util.Enumeration; +import java.util.Stack; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.FileScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.PatternSet; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.selectors.AndSelector; +import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; +import org.apache.tools.ant.types.selectors.ContainsSelector; +import org.apache.tools.ant.types.selectors.DateSelector; +import org.apache.tools.ant.types.selectors.DependSelector; +import org.apache.tools.ant.types.selectors.DepthSelector; +import org.apache.tools.ant.types.selectors.DifferentSelector; +import org.apache.tools.ant.types.selectors.ExecutableSelector; +import org.apache.tools.ant.types.selectors.ExtendSelector; +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.apache.tools.ant.types.selectors.MajoritySelector; +import org.apache.tools.ant.types.selectors.NoneSelector; +import org.apache.tools.ant.types.selectors.NotSelector; +import org.apache.tools.ant.types.selectors.OrSelector; +import org.apache.tools.ant.types.selectors.OwnedBySelector; +import org.apache.tools.ant.types.selectors.PosixGroupSelector; +import org.apache.tools.ant.types.selectors.PosixPermissionsSelector; +import org.apache.tools.ant.types.selectors.PresentSelector; +import org.apache.tools.ant.types.selectors.ReadableSelector; +import org.apache.tools.ant.types.selectors.SelectSelector; +import org.apache.tools.ant.types.selectors.SelectorContainer; +import org.apache.tools.ant.types.selectors.SizeSelector; +import org.apache.tools.ant.types.selectors.SymlinkSelector; +import org.apache.tools.ant.types.selectors.TypeSelector; +import org.apache.tools.ant.types.selectors.WritableSelector; +import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; + +abstract public class AbstractFileSet extends DataType implements Cloneable, SelectorContainer +{ + protected AbstractFileSet getRef(Project p0){ return null; } + protected AbstractFileSet(AbstractFileSet p0){} + protected void dieOnCircularReference(Stack p0, Project p1){} + public AbstractFileSet(){} + public DirectoryScanner getDirectoryScanner(){ return null; } + public DirectoryScanner getDirectoryScanner(Project p0){ return null; } + public Enumeration selectorElements(){ return null; } + public File getDir(){ return null; } + public File getDir(Project p0){ return null; } + public FileSelector[] getSelectors(Project p0){ return null; } + public Object clone(){ return null; } + public PatternSet createPatternSet(){ return null; } + public PatternSet mergePatterns(Project p0){ return null; } + public PatternSet.NameEntry createExclude(){ return null; } + public PatternSet.NameEntry createExcludesFile(){ return null; } + public PatternSet.NameEntry createInclude(){ return null; } + public PatternSet.NameEntry createIncludesFile(){ return null; } + public String toString(){ return null; } + public String[] mergeExcludes(Project p0){ return null; } + public String[] mergeIncludes(Project p0){ return null; } + public boolean getDefaultexcludes(){ return false; } + public boolean getErrorOnMissingDir(){ return false; } + public boolean hasPatterns(){ return false; } + public boolean hasSelectors(){ return false; } + public boolean isCaseSensitive(){ return false; } + public boolean isFollowSymlinks(){ return false; } + public int getMaxLevelsOfSymlinks(){ return 0; } + public int selectorCount(){ return 0; } + public void add(FileSelector p0){} + public void addAnd(AndSelector p0){} + public void addContains(ContainsSelector p0){} + public void addContainsRegexp(ContainsRegexpSelector p0){} + public void addCustom(ExtendSelector p0){} + public void addDate(DateSelector p0){} + public void addDepend(DependSelector p0){} + public void addDepth(DepthSelector p0){} + public void addDifferent(DifferentSelector p0){} + public void addExecutable(ExecutableSelector p0){} + public void addFilename(FilenameSelector p0){} + public void addMajority(MajoritySelector p0){} + public void addModified(ModifiedSelector p0){} + public void addNone(NoneSelector p0){} + public void addNot(NotSelector p0){} + public void addOr(OrSelector p0){} + public void addOwnedBy(OwnedBySelector p0){} + public void addPosixGroup(PosixGroupSelector p0){} + public void addPosixPermissions(PosixPermissionsSelector p0){} + public void addPresent(PresentSelector p0){} + public void addReadable(ReadableSelector p0){} + public void addSelector(SelectSelector p0){} + public void addSize(SizeSelector p0){} + public void addSymlink(SymlinkSelector p0){} + public void addType(TypeSelector p0){} + public void addWritable(WritableSelector p0){} + public void appendExcludes(String[] p0){} + public void appendIncludes(String[] p0){} + public void appendSelector(FileSelector p0){} + public void setCaseSensitive(boolean p0){} + public void setDefaultexcludes(boolean p0){} + public void setDir(File p0){} + public void setErrorOnMissingDir(boolean p0){} + public void setExcludes(String p0){} + public void setExcludesfile(File p0){} + public void setFile(File p0){} + public void setFollowSymlinks(boolean p0){} + public void setIncludes(String p0){} + public void setIncludesfile(File p0){} + public void setMaxLevelsOfSymlinks(int p0){} + public void setRefid(Reference p0){} + public void setupDirectoryScanner(FileScanner p0){} + public void setupDirectoryScanner(FileScanner p0, Project p1){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AntFilterReader.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AntFilterReader.java new file mode 100644 index 00000000000..5ade0fb53a2 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/AntFilterReader.java @@ -0,0 +1,25 @@ +// Generated automatically from org.apache.tools.ant.types.AntFilterReader for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Stack; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Reference; + +public class AntFilterReader extends DataType +{ + protected void dieOnCircularReference(Stack p0, Project p1){} + public AntFilterReader(){} + public Parameter[] getParams(){ return null; } + public Path createClasspath(){ return null; } + public Path getClasspath(){ return null; } + public String getClassName(){ return null; } + public void addParam(Parameter p0){} + public void setClassName(String p0){} + public void setClasspath(Path p0){} + public void setClasspathRef(Reference p0){} + public void setRefid(Reference p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Comparison.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Comparison.java new file mode 100644 index 00000000000..4b1677c1595 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Comparison.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.tools.ant.types.Comparison for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +public class Comparison extends EnumeratedAttribute +{ + public Comparison(){} + public Comparison(String p0){} + public String[] getValues(){ return null; } + public boolean evaluate(int p0){ return false; } + public static Comparison EQUAL = null; + public static Comparison GREATER = null; + public static Comparison GREATER_EQUAL = null; + public static Comparison LESS = null; + public static Comparison LESS_EQUAL = null; + public static Comparison NOT_EQUAL = null; +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DataType.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DataType.java new file mode 100644 index 00000000000..776fd802e23 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DataType.java @@ -0,0 +1,39 @@ +// Generated automatically from org.apache.tools.ant.types.DataType for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Stack; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.types.Reference; + +abstract public class DataType extends ProjectComponent implements Cloneable +{ + protected T getCheckedRef(){ return null; } + protected T getCheckedRef(Project p0){ return null; } + protected T getCheckedRef(java.lang.Class p0){ return null; } + protected T getCheckedRef(java.lang.Class p0, String p1){ return null; } + protected T getCheckedRef(java.lang.Class p0, String p1, Project p2){ return null; } + protected BuildException circularReference(){ return null; } + protected BuildException noChildrenAllowed(){ return null; } + protected BuildException tooManyAttributes(){ return null; } + protected Reference ref = null; + protected String getDataTypeName(){ return null; } + protected boolean checked = false; + protected boolean isChecked(){ return false; } + protected void checkAttributesAllowed(){} + protected void checkChildrenAllowed(){} + protected void dieOnCircularReference(){} + protected void dieOnCircularReference(Project p0){} + protected void dieOnCircularReference(Stack p0, Project p1){} + protected void setChecked(boolean p0){} + public DataType(){} + public Object clone(){ return null; } + public Reference getRefid(){ return null; } + public String toString(){ return null; } + public boolean isReference(){ return false; } + public static void invokeCircularReferenceCheck(DataType p0, Stack p1, Project p2){} + public static void pushAndInvokeCircularReferenceCheck(DataType p0, Stack p1, Project p2){} + public void setRefid(Reference p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DirSet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DirSet.java new file mode 100644 index 00000000000..5ba17ab1bd2 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/DirSet.java @@ -0,0 +1,21 @@ +// Generated automatically from org.apache.tools.ant.types.DirSet for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Iterator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.AbstractFileSet; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; + +public class DirSet extends AbstractFileSet implements ResourceCollection +{ + protected AbstractFileSet getRef(Project p0){ return null; } + protected DirSet(DirSet p0){} + public DirSet(){} + public Iterator iterator(){ return null; } + public Object clone(){ return null; } + public String toString(){ return null; } + public boolean isFilesystemOnly(){ return false; } + public int size(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/EnumeratedAttribute.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/EnumeratedAttribute.java new file mode 100644 index 00000000000..9421f733c5f --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/EnumeratedAttribute.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.tools.ant.types.EnumeratedAttribute for testing purposes + +package org.apache.tools.ant.types; + + +abstract public class EnumeratedAttribute +{ + protected EnumeratedAttribute(){} + protected String value = null; + public String toString(){ return null; } + public abstract String[] getValues(); + public final String getValue(){ return null; } + public final boolean containsValue(String p0){ return false; } + public final int getIndex(){ return 0; } + public final int indexOfValue(String p0){ return 0; } + public static EnumeratedAttribute getInstance(Class p0, String p1){ return null; } + public void setValue(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileList.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileList.java new file mode 100644 index 00000000000..aef6825757c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileList.java @@ -0,0 +1,32 @@ +// Generated automatically from org.apache.tools.ant.types.FileList for testing purposes + +package org.apache.tools.ant.types; + +import java.io.File; +import java.util.Iterator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; + +public class FileList extends DataType implements ResourceCollection +{ + protected FileList(FileList p0){} + public File getDir(Project p0){ return null; } + public FileList(){} + public Iterator iterator(){ return null; } + public String[] getFiles(Project p0){ return null; } + public boolean isFilesystemOnly(){ return false; } + public int size(){ return 0; } + public void addConfiguredFile(FileList.FileName p0){} + public void setDir(File p0){} + public void setFiles(String p0){} + public void setRefid(Reference p0){} + static public class FileName + { + public FileName(){} + public String getName(){ return null; } + public void setName(String p0){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileSet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileSet.java new file mode 100644 index 00000000000..9010c0f8a84 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FileSet.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.tools.ant.types.FileSet for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Iterator; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.AbstractFileSet; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; + +public class FileSet extends AbstractFileSet implements ResourceCollection +{ + protected AbstractFileSet getRef(Project p0){ return null; } + protected FileSet(FileSet p0){} + public FileSet(){} + public Iterator iterator(){ return null; } + public Object clone(){ return null; } + public boolean isFilesystemOnly(){ return false; } + public int size(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterChain.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterChain.java new file mode 100644 index 00000000000..804331f1198 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterChain.java @@ -0,0 +1,57 @@ +// Generated automatically from org.apache.tools.ant.types.FilterChain for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Stack; +import java.util.Vector; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.filters.ChainableReader; +import org.apache.tools.ant.filters.ClassConstants; +import org.apache.tools.ant.filters.EscapeUnicode; +import org.apache.tools.ant.filters.ExpandProperties; +import org.apache.tools.ant.filters.HeadFilter; +import org.apache.tools.ant.filters.LineContains; +import org.apache.tools.ant.filters.LineContainsRegExp; +import org.apache.tools.ant.filters.PrefixLines; +import org.apache.tools.ant.filters.ReplaceTokens; +import org.apache.tools.ant.filters.StripJavaComments; +import org.apache.tools.ant.filters.StripLineBreaks; +import org.apache.tools.ant.filters.StripLineComments; +import org.apache.tools.ant.filters.SuffixLines; +import org.apache.tools.ant.filters.TabsToSpaces; +import org.apache.tools.ant.filters.TailFilter; +import org.apache.tools.ant.filters.TokenFilter; +import org.apache.tools.ant.types.AntFilterReader; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; + +public class FilterChain extends DataType +{ + protected void dieOnCircularReference(Stack p0, Project p1){} + public FilterChain(){} + public Vector getFilterReaders(){ return null; } + public void add(ChainableReader p0){} + public void addClassConstants(ClassConstants p0){} + public void addContainsRegex(TokenFilter.ContainsRegex p0){} + public void addDeleteCharacters(TokenFilter.DeleteCharacters p0){} + public void addEscapeUnicode(EscapeUnicode p0){} + public void addExpandProperties(ExpandProperties p0){} + public void addFilterReader(AntFilterReader p0){} + public void addHeadFilter(HeadFilter p0){} + public void addIgnoreBlank(TokenFilter.IgnoreBlank p0){} + public void addLineContains(LineContains p0){} + public void addLineContainsRegExp(LineContainsRegExp p0){} + public void addPrefixLines(PrefixLines p0){} + public void addReplaceRegex(TokenFilter.ReplaceRegex p0){} + public void addReplaceString(TokenFilter.ReplaceString p0){} + public void addReplaceTokens(ReplaceTokens p0){} + public void addStripJavaComments(StripJavaComments p0){} + public void addStripLineBreaks(StripLineBreaks p0){} + public void addStripLineComments(StripLineComments p0){} + public void addSuffixLines(SuffixLines p0){} + public void addTabsToSpaces(TabsToSpaces p0){} + public void addTailFilter(TailFilter p0){} + public void addTokenFilter(TokenFilter p0){} + public void addTrim(TokenFilter.Trim p0){} + public void setRefid(Reference p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSet.java new file mode 100644 index 00000000000..3d84e30ddde --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSet.java @@ -0,0 +1,62 @@ +// Generated automatically from org.apache.tools.ant.types.FilterSet for testing purposes + +package org.apache.tools.ant.types; + +import java.io.File; +import java.util.Hashtable; +import java.util.Vector; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.PropertySet; + +public class FilterSet extends DataType implements Cloneable +{ + protected FilterSet getRef(){ return null; } + protected FilterSet(FilterSet p0){} + protected Vector getFilters(){ return null; } + public FilterSet(){} + public FilterSet.FiltersFile createFiltersfile(){ return null; } + public FilterSet.OnMissing getOnMissingFiltersFile(){ return null; } + public Hashtable getFilterHash(){ return null; } + public Object clone(){ return null; } + public String getBeginToken(){ return null; } + public String getEndToken(){ return null; } + public String replaceTokens(String p0){ return null; } + public boolean hasFilters(){ return false; } + public boolean isRecurse(){ return false; } + public class FiltersFile + { + public FiltersFile(){} + public void setFile(File p0){} + } + public static String DEFAULT_TOKEN_END = null; + public static String DEFAULT_TOKEN_START = null; + public void addConfiguredFilterSet(FilterSet p0){} + public void addConfiguredPropertySet(PropertySet p0){} + public void addFilter(FilterSet.Filter p0){} + public void addFilter(String p0, String p1){} + public void readFiltersFromFile(File p0){} + public void setBeginToken(String p0){} + public void setEndToken(String p0){} + public void setFiltersfile(File p0){} + public void setOnMissingFiltersFile(FilterSet.OnMissing p0){} + public void setRecurse(boolean p0){} + static public class Filter + { + public Filter(){} + public Filter(String p0, String p1){} + public String getToken(){ return null; } + public String getValue(){ return null; } + public void setToken(String p0){} + public void setValue(String p0){} + } + static public class OnMissing extends EnumeratedAttribute + { + public OnMissing(){} + public OnMissing(String p0){} + public String[] getValues(){ return null; } + public static FilterSet.OnMissing FAIL = null; + public static FilterSet.OnMissing IGNORE = null; + public static FilterSet.OnMissing WARN = null; + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSetCollection.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSetCollection.java new file mode 100644 index 00000000000..e20a5fc2c51 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/FilterSetCollection.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.FilterSetCollection for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.types.FilterSet; + +public class FilterSetCollection +{ + public FilterSetCollection(){} + public FilterSetCollection(FilterSet p0){} + public String replaceTokens(String p0){ return null; } + public boolean hasFilters(){ return false; } + public void addFilterSet(FilterSet p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Mapper.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Mapper.java new file mode 100644 index 00000000000..a559790a20e --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Mapper.java @@ -0,0 +1,41 @@ +// Generated automatically from org.apache.tools.ant.types.Mapper for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.util.FileNameMapper; + +public class Mapper extends DataType +{ + protected Mapper() {} + protected Class getImplementationClass(){ return null; } + protected Mapper getRef(){ return null; } + protected Mapper.MapperType type = null; + protected Path classpath = null; + protected String classname = null; + protected String from = null; + protected String to = null; + public FileNameMapper getImplementation(){ return null; } + public Mapper(Project p0){} + public Path createClasspath(){ return null; } + public void add(FileNameMapper p0){} + public void addConfigured(FileNameMapper p0){} + public void addConfiguredMapper(Mapper p0){} + public void setClassname(String p0){} + public void setClasspath(Path p0){} + public void setClasspathRef(Reference p0){} + public void setFrom(String p0){} + public void setRefid(Reference p0){} + public void setTo(String p0){} + public void setType(Mapper.MapperType p0){} + static public class MapperType extends EnumeratedAttribute + { + public MapperType(){} + public String getImplementation(){ return null; } + public String[] getValues(){ return null; } + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameter.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameter.java new file mode 100644 index 00000000000..27693307028 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameter.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.ant.types.Parameter for testing purposes + +package org.apache.tools.ant.types; + + +public class Parameter +{ + public Parameter(){} + public String getName(){ return null; } + public String getType(){ return null; } + public String getValue(){ return null; } + public void setName(String p0){} + public void setType(String p0){} + public void setValue(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameterizable.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameterizable.java new file mode 100644 index 00000000000..250c7d45ad9 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Parameterizable.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.types.Parameterizable for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.types.Parameter; + +public interface Parameterizable +{ + void setParameters(Parameter... p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Path.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Path.java new file mode 100644 index 00000000000..a01ebe7c3f6 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Path.java @@ -0,0 +1,65 @@ +// Generated automatically from org.apache.tools.ant.types.Path for testing purposes + +package org.apache.tools.ant.types; + +import java.io.File; +import java.util.Iterator; +import java.util.Stack; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.DirSet; +import org.apache.tools.ant.types.FileList; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; + +public class Path extends DataType implements Cloneable, ResourceCollection +{ + protected Path() {} + protected ResourceCollection assertFilesystemOnly(ResourceCollection p0){ return null; } + protected boolean delegateIteratorToList(){ return false; } + protected static boolean translateFileSep(StringBuffer p0, int p1){ return false; } + protected void dieOnCircularReference(Stack p0, Project p1){} + public Object clone(){ return null; } + public Path concatSystemBootClasspath(String p0){ return null; } + public Path concatSystemClasspath(){ return null; } + public Path concatSystemClasspath(String p0){ return null; } + public Path createPath(){ return null; } + public Path(Project p0){} + public Path(Project p0, String p1){} + public Path.PathElement createPathElement(){ return null; } + public String toString(){ return null; } + public String[] list(){ return null; } + public boolean isFilesystemOnly(){ return false; } + public class PathElement implements ResourceCollection + { + public Iterator iterator(){ return null; } + public PathElement(){} + public String[] getParts(){ return null; } + public boolean isFilesystemOnly(){ return false; } + public int size(){ return 0; } + public void setLocation(File p0){} + public void setPath(String p0){} + } + public final Iterator iterator(){ return null; } + public int size(){ return 0; } + public static Path systemBootClasspath = null; + public static Path systemClasspath = null; + public static String translateFile(String p0){ return null; } + public static String[] translatePath(Project p0, String p1){ return null; } + public void add(Path p0){} + public void add(ResourceCollection p0){} + public void addDirset(DirSet p0){} + public void addExisting(Path p0){} + public void addExisting(Path p0, boolean p1){} + public void addExtdirs(Path p0){} + public void addFilelist(FileList p0){} + public void addFileset(FileSet p0){} + public void addJavaRuntime(){} + public void append(Path p0){} + public void setCache(boolean p0){} + public void setLocation(File p0){} + public void setPath(String p0){} + public void setRefid(Reference p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PatternSet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PatternSet.java new file mode 100644 index 00000000000..897f11033cc --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PatternSet.java @@ -0,0 +1,42 @@ +// Generated automatically from org.apache.tools.ant.types.PatternSet for testing purposes + +package org.apache.tools.ant.types; + +import java.io.File; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; + +public class PatternSet extends DataType implements Cloneable +{ + public Object clone(){ return null; } + public PatternSet(){} + public PatternSet.NameEntry createExclude(){ return null; } + public PatternSet.NameEntry createExcludesFile(){ return null; } + public PatternSet.NameEntry createInclude(){ return null; } + public PatternSet.NameEntry createIncludesFile(){ return null; } + public String toString(){ return null; } + public String[] getExcludePatterns(Project p0){ return null; } + public String[] getIncludePatterns(Project p0){ return null; } + public boolean hasPatterns(Project p0){ return false; } + public class NameEntry + { + public NameEntry(){} + public String evalName(Project p0){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public void setIf(Object p0){} + public void setIf(String p0){} + public void setName(String p0){} + public void setUnless(Object p0){} + public void setUnless(String p0){} + } + public void addConfiguredInvert(PatternSet p0){} + public void addConfiguredPatternset(PatternSet p0){} + public void append(PatternSet p0, Project p1){} + public void setExcludes(String p0){} + public void setExcludesfile(File p0){} + public void setIncludes(String p0){} + public void setIncludesfile(File p0){} + public void setRefid(Reference p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PropertySet.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PropertySet.java new file mode 100644 index 00000000000..fd4ea437f36 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/PropertySet.java @@ -0,0 +1,56 @@ +// Generated automatically from org.apache.tools.ant.types.PropertySet for testing purposes + +package org.apache.tools.ant.types; + +import java.util.Iterator; +import java.util.Properties; +import java.util.Stack; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.ResourceCollection; +import org.apache.tools.ant.util.FileNameMapper; + +public class PropertySet extends DataType implements ResourceCollection +{ + protected PropertySet getRef(){ return null; } + protected final void assertNotReference(){} + protected void dieOnCircularReference(Stack p0, Project p1){} + public Iterator iterator(){ return null; } + public Mapper createMapper(){ return null; } + public Mapper getMapper(){ return null; } + public Properties getProperties(){ return null; } + public PropertySet(){} + public String toString(){ return null; } + public boolean getDynamic(){ return false; } + public boolean isFilesystemOnly(){ return false; } + public final void setRefid(Reference p0){} + public int size(){ return 0; } + public void add(FileNameMapper p0){} + public void addPropertyref(PropertySet.PropertyRef p0){} + public void addPropertyset(PropertySet p0){} + public void appendBuiltin(PropertySet.BuiltinPropertySetName p0){} + public void appendName(String p0){} + public void appendPrefix(String p0){} + public void appendRegex(String p0){} + public void setDynamic(boolean p0){} + public void setMapper(String p0, String p1, String p2){} + public void setNegate(boolean p0){} + static public class BuiltinPropertySetName extends EnumeratedAttribute + { + public BuiltinPropertySetName(){} + public String[] getValues(){ return null; } + } + static public class PropertyRef + { + public PropertyRef(){} + public String toString(){ return null; } + public void setBuiltin(PropertySet.BuiltinPropertySetName p0){} + public void setName(String p0){} + public void setPrefix(String p0){} + public void setRegex(String p0){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Reference.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Reference.java new file mode 100644 index 00000000000..3d0f7f4d8c0 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Reference.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.tools.ant.types.Reference for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.Project; + +public class Reference +{ + public T getReferencedObject(){ return null; } + public T getReferencedObject(Project p0){ return null; } + public Project getProject(){ return null; } + public Reference(){} + public Reference(Project p0, String p1){} + public Reference(String p0){} + public String getRefId(){ return null; } + public void setProject(Project p0){} + public void setRefId(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/RegularExpression.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/RegularExpression.java new file mode 100644 index 00000000000..310b58c058b --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/RegularExpression.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.types.RegularExpression for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.util.regexp.Regexp; + +public class RegularExpression extends DataType +{ + public Regexp getRegexp(Project p0){ return null; } + public RegularExpression getRef(Project p0){ return null; } + public RegularExpression(){} + public String getPattern(Project p0){ return null; } + public static String DATA_TYPE_NAME = null; + public void setPattern(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Resource.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Resource.java new file mode 100644 index 00000000000..dfa6d1e9c39 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/Resource.java @@ -0,0 +1,49 @@ +// Generated automatically from org.apache.tools.ant.types.Resource for testing purposes + +package org.apache.tools.ant.types; + +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Iterator; +import java.util.Optional; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.ResourceCollection; + +public class Resource extends DataType implements Comparable, ResourceCollection +{ + protected Resource getRef(){ return null; } + protected static int MAGIC = 0; + protected static int getMagicNumber(byte[] p0){ return 0; } + public T as(java.lang.Class p0){ return null; } + public java.util.Optional asOptional(java.lang.Class p0){ return null; } + public InputStream getInputStream(){ return null; } + public Iterator iterator(){ return null; } + public Object clone(){ return null; } + public OutputStream getOutputStream(){ return null; } + public Resource(){} + public Resource(String p0){} + public Resource(String p0, boolean p1, long p2){} + public Resource(String p0, boolean p1, long p2, boolean p3){} + public Resource(String p0, boolean p1, long p2, boolean p3, long p4){} + public String getName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isDirectory(){ return false; } + public boolean isExists(){ return false; } + public boolean isFilesystemOnly(){ return false; } + public final String toLongString(){ return null; } + public int compareTo(Resource p0){ return 0; } + public int hashCode(){ return 0; } + public int size(){ return 0; } + public long getLastModified(){ return 0; } + public long getSize(){ return 0; } + public static long UNKNOWN_DATETIME = 0; + public static long UNKNOWN_SIZE = 0; + public void setDirectory(boolean p0){} + public void setExists(boolean p0){} + public void setLastModified(long p0){} + public void setName(String p0){} + public void setRefid(Reference p0){} + public void setSize(long p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceCollection.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceCollection.java new file mode 100644 index 00000000000..3647204ba73 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceCollection.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.ResourceCollection for testing purposes + +package org.apache.tools.ant.types; + +import java.util.stream.Stream; +import org.apache.tools.ant.types.Resource; + +public interface ResourceCollection extends Iterable +{ + boolean isFilesystemOnly(); + default Stream stream(){ return null; } + default boolean isEmpty(){ return false; } + int size(); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceFactory.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceFactory.java new file mode 100644 index 00000000000..08a4f823f0c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/ResourceFactory.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.types.ResourceFactory for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.types.Resource; + +public interface ResourceFactory +{ + Resource getResource(String p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/TimeComparison.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/TimeComparison.java new file mode 100644 index 00000000000..b6da23dd480 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/TimeComparison.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.tools.ant.types.TimeComparison for testing purposes + +package org.apache.tools.ant.types; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +public class TimeComparison extends EnumeratedAttribute +{ + public String[] getValues(){ return null; } + public TimeComparison(){} + public TimeComparison(String p0){} + public boolean evaluate(long p0, long p1){ return false; } + public boolean evaluate(long p0, long p1, long p2){ return false; } + public static TimeComparison AFTER = null; + public static TimeComparison BEFORE = null; + public static TimeComparison EQUAL = null; + public static int compare(long p0, long p1){ return 0; } + public static int compare(long p0, long p1, long p2){ return 0; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java new file mode 100644 index 00000000000..401fa3a69d2 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/resources/selectors/ResourceSelector.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.types.resources.selectors.ResourceSelector for testing purposes + +package org.apache.tools.ant.types.resources.selectors; + +import org.apache.tools.ant.types.Resource; + +public interface ResourceSelector +{ + boolean isSelected(Resource p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/AndSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/AndSelector.java new file mode 100644 index 00000000000..894ad55c240 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/AndSelector.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.AndSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.BaseSelectorContainer; + +public class AndSelector extends BaseSelectorContainer +{ + public AndSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseExtendSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseExtendSelector.java new file mode 100644 index 00000000000..d47425773ce --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseExtendSelector.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.BaseExtendSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.selectors.BaseSelector; +import org.apache.tools.ant.types.selectors.ExtendFileSelector; + +abstract public class BaseExtendSelector extends BaseSelector implements ExtendFileSelector +{ + protected Parameter[] getParameters(){ return null; } + protected Parameter[] parameters = null; + public BaseExtendSelector(){} + public abstract boolean isSelected(File p0, String p1, File p2); + public void setParameters(Parameter... p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelector.java new file mode 100644 index 00000000000..214776df2a1 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelector.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.BaseSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.selectors.FileSelector; + +abstract public class BaseSelector extends DataType implements FileSelector +{ + public BaseSelector(){} + public String getError(){ return null; } + public abstract boolean isSelected(File p0, String p1, File p2); + public void setError(String p0){} + public void setError(String p0, Throwable p1){} + public void validate(){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java new file mode 100644 index 00000000000..d1b8ffcc43b --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java @@ -0,0 +1,76 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.BaseSelectorContainer for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import java.util.Enumeration; +import java.util.Stack; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.selectors.AndSelector; +import org.apache.tools.ant.types.selectors.BaseSelector; +import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; +import org.apache.tools.ant.types.selectors.ContainsSelector; +import org.apache.tools.ant.types.selectors.DateSelector; +import org.apache.tools.ant.types.selectors.DependSelector; +import org.apache.tools.ant.types.selectors.DepthSelector; +import org.apache.tools.ant.types.selectors.DifferentSelector; +import org.apache.tools.ant.types.selectors.ExecutableSelector; +import org.apache.tools.ant.types.selectors.ExtendSelector; +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.apache.tools.ant.types.selectors.MajoritySelector; +import org.apache.tools.ant.types.selectors.NoneSelector; +import org.apache.tools.ant.types.selectors.NotSelector; +import org.apache.tools.ant.types.selectors.OrSelector; +import org.apache.tools.ant.types.selectors.OwnedBySelector; +import org.apache.tools.ant.types.selectors.PosixGroupSelector; +import org.apache.tools.ant.types.selectors.PosixPermissionsSelector; +import org.apache.tools.ant.types.selectors.PresentSelector; +import org.apache.tools.ant.types.selectors.ReadableSelector; +import org.apache.tools.ant.types.selectors.SelectSelector; +import org.apache.tools.ant.types.selectors.SelectorContainer; +import org.apache.tools.ant.types.selectors.SizeSelector; +import org.apache.tools.ant.types.selectors.SymlinkSelector; +import org.apache.tools.ant.types.selectors.TypeSelector; +import org.apache.tools.ant.types.selectors.WritableSelector; +import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; + +abstract public class BaseSelectorContainer extends BaseSelector implements SelectorContainer +{ + protected void dieOnCircularReference(Stack p0, Project p1){} + public BaseSelectorContainer(){} + public Enumeration selectorElements(){ return null; } + public FileSelector[] getSelectors(Project p0){ return null; } + public String toString(){ return null; } + public abstract boolean isSelected(File p0, String p1, File p2); + public boolean hasSelectors(){ return false; } + public int selectorCount(){ return 0; } + public void add(FileSelector p0){} + public void addAnd(AndSelector p0){} + public void addContains(ContainsSelector p0){} + public void addContainsRegexp(ContainsRegexpSelector p0){} + public void addCustom(ExtendSelector p0){} + public void addDate(DateSelector p0){} + public void addDepend(DependSelector p0){} + public void addDepth(DepthSelector p0){} + public void addDifferent(DifferentSelector p0){} + public void addExecutable(ExecutableSelector p0){} + public void addFilename(FilenameSelector p0){} + public void addMajority(MajoritySelector p0){} + public void addModified(ModifiedSelector p0){} + public void addNone(NoneSelector p0){} + public void addNot(NotSelector p0){} + public void addOr(OrSelector p0){} + public void addOwnedBy(OwnedBySelector p0){} + public void addPosixGroup(PosixGroupSelector p0){} + public void addPosixPermissions(PosixPermissionsSelector p0){} + public void addPresent(PresentSelector p0){} + public void addReadable(ReadableSelector p0){} + public void addSelector(SelectSelector p0){} + public void addSize(SizeSelector p0){} + public void addSymlink(SymlinkSelector p0){} + public void addType(TypeSelector p0){} + public void addWritable(WritableSelector p0){} + public void appendSelector(FileSelector p0){} + public void validate(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java new file mode 100644 index 00000000000..561f52ca723 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsRegexpSelector.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ContainsRegexpSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.selectors.ResourceSelector; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class ContainsRegexpSelector extends BaseExtendSelector implements ResourceSelector +{ + public ContainsRegexpSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public boolean isSelected(Resource p0){ return false; } + public static String EXPRESSION_KEY = null; + public void setCaseSensitive(boolean p0){} + public void setExpression(String p0){} + public void setMultiLine(boolean p0){} + public void setParameters(Parameter... p0){} + public void setSingleLine(boolean p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsSelector.java new file mode 100644 index 00000000000..dbcfc3c1719 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ContainsSelector.java @@ -0,0 +1,27 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ContainsSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.selectors.ResourceSelector; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class ContainsSelector extends BaseExtendSelector implements ResourceSelector +{ + public ContainsSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public boolean isSelected(Resource p0){ return false; } + public static String CASE_KEY = null; + public static String CONTAINS_KEY = null; + public static String EXPRESSION_KEY = null; + public static String WHITESPACE_KEY = null; + public void setCasesensitive(boolean p0){} + public void setEncoding(String p0){} + public void setIgnorewhitespace(boolean p0){} + public void setParameters(Parameter... p0){} + public void setText(String p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DateSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DateSelector.java new file mode 100644 index 00000000000..c9f32e3e2dd --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DateSelector.java @@ -0,0 +1,35 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.DateSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.TimeComparison; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class DateSelector extends BaseExtendSelector +{ + public DateSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public long getMillis(){ return 0; } + public static String CHECKDIRS_KEY = null; + public static String DATETIME_KEY = null; + public static String GRANULARITY_KEY = null; + public static String MILLIS_KEY = null; + public static String PATTERN_KEY = null; + public static String WHEN_KEY = null; + public void setCheckdirs(boolean p0){} + public void setDatetime(String p0){} + public void setGranularity(int p0){} + public void setMillis(long p0){} + public void setParameters(Parameter... p0){} + public void setPattern(String p0){} + public void setWhen(DateSelector.TimeComparisons p0){} + public void setWhen(TimeComparison p0){} + public void verifySettings(){} + static public class TimeComparisons extends TimeComparison + { + public TimeComparisons(){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DependSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DependSelector.java new file mode 100644 index 00000000000..09ae1ebfda3 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DependSelector.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.DependSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.MappingSelector; + +public class DependSelector extends MappingSelector +{ + public DependSelector(){} + public String toString(){ return null; } + public boolean selectionTest(File p0, File p1){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DepthSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DepthSelector.java new file mode 100644 index 00000000000..626b32be726 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DepthSelector.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.DepthSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class DepthSelector extends BaseExtendSelector +{ + public DepthSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public int max = 0; + public int min = 0; + public static String MAX_KEY = null; + public static String MIN_KEY = null; + public void setMax(int p0){} + public void setMin(int p0){} + public void setParameters(Parameter... p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DifferentSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DifferentSelector.java new file mode 100644 index 00000000000..3cf7174847d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/DifferentSelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.DifferentSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.MappingSelector; + +public class DifferentSelector extends MappingSelector +{ + protected boolean selectionTest(File p0, File p1){ return false; } + public DifferentSelector(){} + public void setIgnoreContents(boolean p0){} + public void setIgnoreFileTimes(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExecutableSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExecutableSelector.java new file mode 100644 index 00000000000..c2e6fdae37b --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExecutableSelector.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ExecutableSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class ExecutableSelector implements FileSelector +{ + public ExecutableSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendFileSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendFileSelector.java new file mode 100644 index 00000000000..c38d4e8413c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendFileSelector.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ExtendFileSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import org.apache.tools.ant.types.Parameterizable; +import org.apache.tools.ant.types.selectors.FileSelector; + +public interface ExtendFileSelector extends FileSelector, Parameterizable +{ +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendSelector.java new file mode 100644 index 00000000000..0b8815f162c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ExtendSelector.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ExtendSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Reference; +import org.apache.tools.ant.types.selectors.BaseSelector; + +public class ExtendSelector extends BaseSelector +{ + public ExtendSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public final Path createClasspath(){ return null; } + public final Path getClasspath(){ return null; } + public final void setClasspath(Path p0){} + public void addParam(Parameter p0){} + public void selectorCreate(){} + public void setClassname(String p0){} + public void setClasspathref(Reference p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FileSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FileSelector.java new file mode 100644 index 00000000000..f97b8640cf0 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FileSelector.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.FileSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.selectors.ResourceSelector; + +public interface FileSelector extends ResourceSelector +{ + boolean isSelected(File p0, String p1, File p2); + default boolean isSelected(Resource p0){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FilenameSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FilenameSelector.java new file mode 100644 index 00000000000..60f85f6ce16 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/FilenameSelector.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.FilenameSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class FilenameSelector extends BaseExtendSelector +{ + public FilenameSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public static String CASE_KEY = null; + public static String NAME_KEY = null; + public static String NEGATE_KEY = null; + public static String REGEX_KEY = null; + public void setCasesensitive(boolean p0){} + public void setName(String p0){} + public void setNegate(boolean p0){} + public void setParameters(Parameter... p0){} + public void setRegex(String p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MajoritySelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MajoritySelector.java new file mode 100644 index 00000000000..d0405f52904 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MajoritySelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.MajoritySelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.BaseSelectorContainer; + +public class MajoritySelector extends BaseSelectorContainer +{ + public MajoritySelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void setAllowtie(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MappingSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MappingSelector.java new file mode 100644 index 00000000000..9a6a3b243ad --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/MappingSelector.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.MappingSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.selectors.BaseSelector; +import org.apache.tools.ant.util.FileNameMapper; + +abstract public class MappingSelector extends BaseSelector +{ + protected File targetdir = null; + protected FileNameMapper map = null; + protected Mapper mapperElement = null; + protected abstract boolean selectionTest(File p0, File p1); + protected int granularity = 0; + public Mapper createMapper(){ return null; } + public MappingSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void addConfigured(FileNameMapper p0){} + public void setGranularity(int p0){} + public void setTargetdir(File p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NoneSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NoneSelector.java new file mode 100644 index 00000000000..f0c187d3345 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NoneSelector.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.NoneSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.BaseSelectorContainer; + +public class NoneSelector extends BaseSelectorContainer +{ + public NoneSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NotSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NotSelector.java new file mode 100644 index 00000000000..23f4d19b153 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/NotSelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.NotSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.NoneSelector; + +public class NotSelector extends NoneSelector +{ + public NotSelector(){} + public NotSelector(FileSelector p0){} + public String toString(){ return null; } + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OrSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OrSelector.java new file mode 100644 index 00000000000..2e5e846bad7 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OrSelector.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.OrSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.BaseSelectorContainer; + +public class OrSelector extends BaseSelectorContainer +{ + public OrSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OwnedBySelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OwnedBySelector.java new file mode 100644 index 00000000000..9aecd3fd556 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/OwnedBySelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.OwnedBySelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class OwnedBySelector implements FileSelector +{ + public OwnedBySelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void setFollowSymlinks(boolean p0){} + public void setOwner(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixGroupSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixGroupSelector.java new file mode 100644 index 00000000000..a32cb5d2e84 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixGroupSelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.PosixGroupSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class PosixGroupSelector implements FileSelector +{ + public PosixGroupSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void setFollowSymlinks(boolean p0){} + public void setGroup(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java new file mode 100644 index 00000000000..fa9af45e2b8 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PosixPermissionsSelector.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.PosixPermissionsSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class PosixPermissionsSelector implements FileSelector +{ + public PosixPermissionsSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void setFollowSymlinks(boolean p0){} + public void setPermissions(String p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PresentSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PresentSelector.java new file mode 100644 index 00000000000..3596b4937e7 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/PresentSelector.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.PresentSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Mapper; +import org.apache.tools.ant.types.selectors.BaseSelector; +import org.apache.tools.ant.util.FileNameMapper; + +public class PresentSelector extends BaseSelector +{ + public Mapper createMapper(){ return null; } + public PresentSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public void addConfigured(FileNameMapper p0){} + public void setPresent(PresentSelector.FilePresence p0){} + public void setTargetdir(File p0){} + public void verifySettings(){} + static public class FilePresence extends EnumeratedAttribute + { + public FilePresence(){} + public String[] getValues(){ return null; } + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ReadableSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ReadableSelector.java new file mode 100644 index 00000000000..a47e31f9f04 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/ReadableSelector.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.ReadableSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class ReadableSelector implements FileSelector +{ + public ReadableSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectSelector.java new file mode 100644 index 00000000000..ba5e2cdbfe7 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectSelector.java @@ -0,0 +1,27 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.SelectSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import java.util.Enumeration; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.selectors.BaseSelectorContainer; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class SelectSelector extends BaseSelectorContainer +{ + public Enumeration selectorElements(){ return null; } + public FileSelector[] getSelectors(Project p0){ return null; } + public SelectSelector(){} + public String toString(){ return null; } + public boolean hasSelectors(){ return false; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public boolean passesConditions(){ return false; } + public int selectorCount(){ return 0; } + public void appendSelector(FileSelector p0){} + public void setIf(Object p0){} + public void setIf(String p0){} + public void setUnless(Object p0){} + public void setUnless(String p0){} + public void verifySettings(){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorContainer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorContainer.java new file mode 100644 index 00000000000..84d65cdf86f --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorContainer.java @@ -0,0 +1,53 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.SelectorContainer for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.util.Enumeration; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.selectors.AndSelector; +import org.apache.tools.ant.types.selectors.ContainsRegexpSelector; +import org.apache.tools.ant.types.selectors.ContainsSelector; +import org.apache.tools.ant.types.selectors.DateSelector; +import org.apache.tools.ant.types.selectors.DependSelector; +import org.apache.tools.ant.types.selectors.DepthSelector; +import org.apache.tools.ant.types.selectors.DifferentSelector; +import org.apache.tools.ant.types.selectors.ExtendSelector; +import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.FilenameSelector; +import org.apache.tools.ant.types.selectors.MajoritySelector; +import org.apache.tools.ant.types.selectors.NoneSelector; +import org.apache.tools.ant.types.selectors.NotSelector; +import org.apache.tools.ant.types.selectors.OrSelector; +import org.apache.tools.ant.types.selectors.PresentSelector; +import org.apache.tools.ant.types.selectors.SelectSelector; +import org.apache.tools.ant.types.selectors.SizeSelector; +import org.apache.tools.ant.types.selectors.TypeSelector; +import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector; + +public interface SelectorContainer +{ + Enumeration selectorElements(); + FileSelector[] getSelectors(Project p0); + boolean hasSelectors(); + int selectorCount(); + void add(FileSelector p0); + void addAnd(AndSelector p0); + void addContains(ContainsSelector p0); + void addContainsRegexp(ContainsRegexpSelector p0); + void addCustom(ExtendSelector p0); + void addDate(DateSelector p0); + void addDepend(DependSelector p0); + void addDepth(DepthSelector p0); + void addDifferent(DifferentSelector p0); + void addFilename(FilenameSelector p0); + void addMajority(MajoritySelector p0); + void addModified(ModifiedSelector p0); + void addNone(NoneSelector p0); + void addNot(NotSelector p0); + void addOr(OrSelector p0); + void addPresent(PresentSelector p0); + void addSelector(SelectSelector p0); + void addSize(SizeSelector p0); + void addType(TypeSelector p0); + void appendSelector(FileSelector p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorScanner.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorScanner.java new file mode 100644 index 00000000000..97634f4c35c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SelectorScanner.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.SelectorScanner for testing purposes + +package org.apache.tools.ant.types.selectors; + +import org.apache.tools.ant.types.selectors.FileSelector; + +public interface SelectorScanner +{ + String[] getDeselectedDirectories(); + String[] getDeselectedFiles(); + void setSelectors(FileSelector[] p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SizeSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SizeSelector.java new file mode 100644 index 00000000000..cd408c7961d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SizeSelector.java @@ -0,0 +1,33 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.SizeSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.Comparison; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class SizeSelector extends BaseExtendSelector +{ + public SizeSelector(){} + public String toString(){ return null; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public static String SIZE_KEY = null; + public static String UNITS_KEY = null; + public static String WHEN_KEY = null; + public void setParameters(Parameter... p0){} + public void setUnits(SizeSelector.ByteUnits p0){} + public void setValue(long p0){} + public void setWhen(SizeSelector.SizeComparisons p0){} + public void verifySettings(){} + static public class ByteUnits extends EnumeratedAttribute + { + public ByteUnits(){} + public String[] getValues(){ return null; } + } + static public class SizeComparisons extends Comparison + { + public SizeComparisons(){} + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SymlinkSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SymlinkSelector.java new file mode 100644 index 00000000000..948606a9a86 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/SymlinkSelector.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.SymlinkSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class SymlinkSelector implements FileSelector +{ + public SymlinkSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/TypeSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/TypeSelector.java new file mode 100644 index 00000000000..c9b99f5ed8c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/TypeSelector.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.TypeSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; + +public class TypeSelector extends BaseExtendSelector +{ + public String toString(){ return null; } + public TypeSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } + public static String TYPE_KEY = null; + public void setParameters(Parameter... p0){} + public void setType(TypeSelector.FileType p0){} + public void verifySettings(){} + static public class FileType extends EnumeratedAttribute + { + public FileType(){} + public String[] getValues(){ return null; } + public static String DIR = null; + public static String FILE = null; + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/WritableSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/WritableSelector.java new file mode 100644 index 00000000000..40eae71eafe --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/WritableSelector.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.WritableSelector for testing purposes + +package org.apache.tools.ant.types.selectors; + +import java.io.File; +import org.apache.tools.ant.types.selectors.FileSelector; + +public class WritableSelector implements FileSelector +{ + public WritableSelector(){} + public boolean isSelected(File p0, String p1, File p2){ return false; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java new file mode 100644 index 00000000000..99e5309212f --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Algorithm.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.modifiedselector.Algorithm for testing purposes + +package org.apache.tools.ant.types.selectors.modifiedselector; + +import java.io.File; + +public interface Algorithm +{ + String getValue(File p0); + boolean isValid(); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java new file mode 100644 index 00000000000..20109f72f5d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/Cache.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.modifiedselector.Cache for testing purposes + +package org.apache.tools.ant.types.selectors.modifiedselector; + +import java.util.Iterator; + +public interface Cache +{ + Iterator iterator(); + Object get(Object p0); + boolean isValid(); + void delete(); + void load(); + void put(Object p0, Object p1); + void save(); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java new file mode 100644 index 00000000000..ec466d03be1 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/types/selectors/modifiedselector/ModifiedSelector.java @@ -0,0 +1,74 @@ +// Generated automatically from org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector for testing purposes + +package org.apache.tools.ant.types.selectors.modifiedselector; + +import java.io.File; +import java.util.Comparator; +import org.apache.tools.ant.BuildEvent; +import org.apache.tools.ant.BuildListener; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.Parameter; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.types.Resource; +import org.apache.tools.ant.types.resources.selectors.ResourceSelector; +import org.apache.tools.ant.types.selectors.BaseExtendSelector; +import org.apache.tools.ant.types.selectors.modifiedselector.Algorithm; +import org.apache.tools.ant.types.selectors.modifiedselector.Cache; + +public class ModifiedSelector extends BaseExtendSelector implements BuildListener, ResourceSelector +{ + protected T loadClass(String p0, String p1, java.lang.Class p2){ return null; } + protected void saveCache(){} + protected void tryToSetAParameter(Object p0, String p1, String p2){} + public Algorithm getAlgorithm(){ return null; } + public Cache getCache(){ return null; } + public ClassLoader getClassLoader(){ return null; } + public Comparator getComparator(){ return null; } + public ModifiedSelector(){} + public String toString(){ return null; } + public boolean getDelayUpdate(){ return false; } + public boolean isSelected(File p0, String p1, File p2){ return false; } + public boolean isSelected(Resource p0){ return false; } + public int getModified(){ return 0; } + public void addClasspath(Path p0){} + public void addParam(Parameter p0){} + public void addParam(String p0, Object p1){} + public void buildFinished(BuildEvent p0){} + public void buildStarted(BuildEvent p0){} + public void configure(){} + public void messageLogged(BuildEvent p0){} + public void setAlgorithm(ModifiedSelector.AlgorithmName p0){} + public void setAlgorithmClass(String p0){} + public void setCache(ModifiedSelector.CacheName p0){} + public void setCacheClass(String p0){} + public void setClassLoader(ClassLoader p0){} + public void setComparator(ModifiedSelector.ComparatorName p0){} + public void setComparatorClass(String p0){} + public void setDelayUpdate(boolean p0){} + public void setModified(int p0){} + public void setParameters(Parameter... p0){} + public void setSeldirs(boolean p0){} + public void setSelres(boolean p0){} + public void setUpdate(boolean p0){} + public void targetFinished(BuildEvent p0){} + public void targetStarted(BuildEvent p0){} + public void taskFinished(BuildEvent p0){} + public void taskStarted(BuildEvent p0){} + public void useParameter(Parameter p0){} + public void verifySettings(){} + static public class AlgorithmName extends EnumeratedAttribute + { + public AlgorithmName(){} + public String[] getValues(){ return null; } + } + static public class CacheName extends EnumeratedAttribute + { + public CacheName(){} + public String[] getValues(){ return null; } + } + static public class ComparatorName extends EnumeratedAttribute + { + public ComparatorName(){} + public String[] getValues(){ return null; } + } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileNameMapper.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileNameMapper.java new file mode 100644 index 00000000000..acfb318da43 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileNameMapper.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.tools.ant.util.FileNameMapper for testing purposes + +package org.apache.tools.ant.util; + + +public interface FileNameMapper +{ + String[] mapFileName(String p0); + void setFrom(String p0); + void setTo(String p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileTokenizer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileTokenizer.java new file mode 100644 index 00000000000..f993b4628fd --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileTokenizer.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.tools.ant.util.FileTokenizer for testing purposes + +package org.apache.tools.ant.util; + +import java.io.Reader; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.util.Tokenizer; + +public class FileTokenizer extends ProjectComponent implements Tokenizer +{ + public FileTokenizer(){} + public String getPostToken(){ return null; } + public String getToken(Reader p0){ return null; } +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileUtils.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileUtils.java new file mode 100644 index 00000000000..df9449407c3 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/FileUtils.java @@ -0,0 +1,98 @@ +// Generated automatically from org.apache.tools.ant.util.FileUtils for testing purposes + +package org.apache.tools.ant.util; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URL; +import java.net.URLConnection; +import java.nio.channels.Channel; +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.Vector; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.FilterChain; +import org.apache.tools.ant.types.FilterSetCollection; + +public class FileUtils +{ + protected FileUtils(){} + public File createTempFile(Project p0, String p1, String p2, File p3, boolean p4, boolean p5){ return null; } + public File createTempFile(String p0, String p1, File p2){ return null; } + public File createTempFile(String p0, String p1, File p2, boolean p3){ return null; } + public File createTempFile(String p0, String p1, File p2, boolean p3, boolean p4){ return null; } + public File getParentFile(File p0){ return null; } + public File normalize(String p0){ return null; } + public File resolveFile(File p0, String p1){ return null; } + public String fromURI(String p0){ return null; } + public String getDefaultEncoding(){ return null; } + public String removeLeadingPath(File p0, File p1){ return null; } + public String toURI(String p0){ return null; } + public String toVMSPath(File p0){ return null; } + public String[] dissect(String p0){ return null; } + public URL getFileURL(File p0){ return null; } + public boolean areSame(File p0, File p1){ return false; } + public boolean contentEquals(File p0, File p1){ return false; } + public boolean contentEquals(File p0, File p1, boolean p2){ return false; } + public boolean createNewFile(File p0){ return false; } + public boolean createNewFile(File p0, boolean p1){ return false; } + public boolean fileNameEquals(File p0, File p1){ return false; } + public boolean hasErrorInCase(File p0){ return false; } + public boolean isLeadingPath(File p0, File p1){ return false; } + public boolean isLeadingPath(File p0, File p1, boolean p2){ return false; } + public boolean isSymbolicLink(File p0, String p1){ return false; } + public boolean isUpToDate(File p0, File p1){ return false; } + public boolean isUpToDate(File p0, File p1, long p2){ return false; } + public boolean isUpToDate(long p0, long p1){ return false; } + public boolean isUpToDate(long p0, long p1, long p2){ return false; } + public boolean tryHardToDelete(File p0){ return false; } + public boolean tryHardToDelete(File p0, boolean p1){ return false; } + public long getFileTimestampGranularity(){ return 0; } + public static FileUtils getFileUtils(){ return null; } + public static FileUtils newFileUtils(){ return null; } + public static Optional isCaseSensitiveFileSystem(Path p0){ return null; } + public static OutputStream newOutputStream(Path p0, boolean p1){ return null; } + public static String getPath(List p0){ return null; } + public static String getPath(List p0, char p1){ return null; } + public static String getRelativePath(File p0, File p1){ return null; } + public static String readFully(Reader p0){ return null; } + public static String readFully(Reader p0, int p1){ return null; } + public static String safeReadFully(Reader p0){ return null; } + public static String translatePath(String p0){ return null; } + public static String[] getPathStack(String p0){ return null; } + public static boolean isAbsolutePath(String p0){ return false; } + public static boolean isContextRelativePath(String p0){ return false; } + public static long FAT_FILE_TIMESTAMP_GRANULARITY = 0; + public static long NTFS_FILE_TIMESTAMP_GRANULARITY = 0; + public static long UNIX_FILE_TIMESTAMP_GRANULARITY = 0; + public static void close(AutoCloseable p0){} + public static void close(Channel p0){} + public static void close(InputStream p0){} + public static void close(OutputStream p0){} + public static void close(Reader p0){} + public static void close(URLConnection p0){} + public static void close(Writer p0){} + public static void delete(File p0){} + public void copyFile(File p0, File p1){} + public void copyFile(File p0, File p1, FilterSetCollection p2){} + public void copyFile(File p0, File p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, String p6, Project p7){} + public void copyFile(File p0, File p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, String p6, String p7, Project p8){} + public void copyFile(File p0, File p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, boolean p6, String p7, String p8, Project p9){} + public void copyFile(File p0, File p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, boolean p6, String p7, String p8, Project p9, boolean p10){} + public void copyFile(File p0, File p1, FilterSetCollection p2, boolean p3){} + public void copyFile(File p0, File p1, FilterSetCollection p2, boolean p3, boolean p4){} + public void copyFile(File p0, File p1, FilterSetCollection p2, boolean p3, boolean p4, String p5){} + public void copyFile(String p0, String p1){} + public void copyFile(String p0, String p1, FilterSetCollection p2){} + public void copyFile(String p0, String p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, String p6, Project p7){} + public void copyFile(String p0, String p1, FilterSetCollection p2, Vector p3, boolean p4, boolean p5, String p6, String p7, Project p8){} + public void copyFile(String p0, String p1, FilterSetCollection p2, boolean p3){} + public void copyFile(String p0, String p1, FilterSetCollection p2, boolean p3, boolean p4){} + public void copyFile(String p0, String p1, FilterSetCollection p2, boolean p3, boolean p4, String p5){} + public void rename(File p0, File p1){} + public void setFileLastModified(File p0, long p1){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/LineTokenizer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/LineTokenizer.java new file mode 100644 index 00000000000..84643aea199 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/LineTokenizer.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.ant.util.LineTokenizer for testing purposes + +package org.apache.tools.ant.util; + +import java.io.Reader; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.util.Tokenizer; + +public class LineTokenizer extends ProjectComponent implements Tokenizer +{ + public LineTokenizer(){} + public String getPostToken(){ return null; } + public String getToken(Reader p0){ return null; } + public void setIncludeDelims(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/StringTokenizer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/StringTokenizer.java new file mode 100644 index 00000000000..22a567cb474 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/StringTokenizer.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.tools.ant.util.StringTokenizer for testing purposes + +package org.apache.tools.ant.util; + +import java.io.Reader; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.util.Tokenizer; + +public class StringTokenizer extends ProjectComponent implements Tokenizer +{ + public String getPostToken(){ return null; } + public String getToken(Reader p0){ return null; } + public StringTokenizer(){} + public void setDelims(String p0){} + public void setDelimsAreTokens(boolean p0){} + public void setIncludeDelims(boolean p0){} + public void setSuppressDelims(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/Tokenizer.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/Tokenizer.java new file mode 100644 index 00000000000..1277448a253 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/Tokenizer.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.tools.ant.util.Tokenizer for testing purposes + +package org.apache.tools.ant.util; + +import java.io.Reader; + +public interface Tokenizer +{ + String getPostToken(); + String getToken(Reader p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/Regexp.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/Regexp.java new file mode 100644 index 00000000000..020a9af164c --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/Regexp.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.tools.ant.util.regexp.Regexp for testing purposes + +package org.apache.tools.ant.util.regexp; + +import org.apache.tools.ant.util.regexp.RegexpMatcher; + +public interface Regexp extends RegexpMatcher +{ + String substitute(String p0, String p1, int p2); + static int REPLACE_ALL = 0; + static int REPLACE_FIRST = 0; +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/RegexpMatcher.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/RegexpMatcher.java new file mode 100644 index 00000000000..857014c4498 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/ant/util/regexp/RegexpMatcher.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.tools.ant.util.regexp.RegexpMatcher for testing purposes + +package org.apache.tools.ant.util.regexp; + +import java.util.Vector; + +public interface RegexpMatcher +{ + String getPattern(); + Vector getGroups(String p0); + Vector getGroups(String p0, int p1); + boolean matches(String p0); + boolean matches(String p0, int p1); + static int MATCH_CASE_INSENSITIVE = 0; + static int MATCH_DEFAULT = 0; + static int MATCH_MULTILINE = 0; + static int MATCH_SINGLELINE = 0; + void setPattern(String p0); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java new file mode 100644 index 00000000000..6fcf116aa25 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/CentralDirectoryParsingZipExtraField.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.tools.zip.CentralDirectoryParsingZipExtraField for testing purposes + +package org.apache.tools.zip; + +import org.apache.tools.zip.ZipExtraField; + +public interface CentralDirectoryParsingZipExtraField extends ZipExtraField +{ + void parseFromCentralDirectoryData(byte[] p0, int p1, int p2); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/GeneralPurposeBit.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/GeneralPurposeBit.java new file mode 100644 index 00000000000..16beb77481d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/GeneralPurposeBit.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.tools.zip.GeneralPurposeBit for testing purposes + +package org.apache.tools.zip; + + +public class GeneralPurposeBit implements Cloneable +{ + public GeneralPurposeBit(){} + public Object clone(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean usesDataDescriptor(){ return false; } + public boolean usesEncryption(){ return false; } + public boolean usesStrongEncryption(){ return false; } + public boolean usesUTF8ForNames(){ return false; } + public byte[] encode(){ return null; } + public int hashCode(){ return 0; } + public static GeneralPurposeBit parse(byte[] p0, int p1){ return null; } + public static int UFT8_NAMES_FLAG = 0; + public void encode(byte[] p0, int p1){} + public void useDataDescriptor(boolean p0){} + public void useEncryption(boolean p0){} + public void useStrongEncryption(boolean p0){} + public void useUTF8ForNames(boolean p0){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/UnparseableExtraFieldData.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/UnparseableExtraFieldData.java new file mode 100644 index 00000000000..df24aad1a79 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/UnparseableExtraFieldData.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.tools.zip.UnparseableExtraFieldData for testing purposes + +package org.apache.tools.zip; + +import org.apache.tools.zip.CentralDirectoryParsingZipExtraField; +import org.apache.tools.zip.ZipShort; + +public class UnparseableExtraFieldData implements CentralDirectoryParsingZipExtraField +{ + public UnparseableExtraFieldData(){} + public ZipShort getCentralDirectoryLength(){ return null; } + public ZipShort getHeaderId(){ return null; } + public ZipShort getLocalFileDataLength(){ return null; } + public byte[] getCentralDirectoryData(){ return null; } + public byte[] getLocalFileDataData(){ return null; } + public void parseFromCentralDirectoryData(byte[] p0, int p1, int p2){} + public void parseFromLocalFileData(byte[] p0, int p1, int p2){} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipEntry.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipEntry.java new file mode 100644 index 00000000000..83ab406142d --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipEntry.java @@ -0,0 +1,152 @@ +// Generated automatically from org.apache.tools.zip.ZipEntry for testing purposes + +package org.apache.tools.zip; + +import java.io.File; +import java.util.Date; +import org.apache.tools.zip.GeneralPurposeBit; +import org.apache.tools.zip.UnparseableExtraFieldData; +import org.apache.tools.zip.ZipExtraField; +import org.apache.tools.zip.ZipShort; + +public class ZipEntry extends java.util.zip.ZipEntry implements Cloneable { + protected ZipEntry() { + super(""); + } + + protected void setExtra() {} + + protected void setName(String p0) {} + + protected void setName(String p0, byte[] p1) {} + + protected void setPlatform(int p0) {} + + public Date getLastModifiedDate() { + return null; + } + + public GeneralPurposeBit getGeneralPurposeBit() { + return null; + } + + public Object clone() { + return null; + } + + public String getName() { + return null; + } + + public UnparseableExtraFieldData getUnparseableExtraFieldData() { + return null; + } + + public ZipEntry(File p0, String p1) { + super(""); + } + + public ZipEntry(String p0) { + super(""); + } + + public ZipEntry(java.util.zip.ZipEntry p0) { + super(""); + } + + public ZipEntry(org.apache.tools.zip.ZipEntry p0) { + super(""); + } + + public ZipExtraField getExtraField(ZipShort p0) { + return null; + } + + public ZipExtraField[] getExtraFields() { + return null; + } + + public ZipExtraField[] getExtraFields(boolean p0) { + return null; + } + + public boolean equals(Object p0) { + return false; + } + + public boolean isDirectory() { + return false; + } + + public byte[] getCentralDirectoryExtra() { + return null; + } + + public byte[] getLocalFileDataExtra() { + return null; + } + + public byte[] getRawName() { + return null; + } + + public int getInternalAttributes() { + return 0; + } + + public int getMethod() { + return 0; + } + + public int getPlatform() { + return 0; + } + + public int getUnixMode() { + return 0; + } + + public int hashCode() { + return 0; + } + + public long getExternalAttributes() { + return 0; + } + + public long getSize() { + return 0; + } + + public static int CRC_UNKNOWN = 0; + public static int PLATFORM_FAT = 0; + public static int PLATFORM_UNIX = 0; + + public void addAsFirstExtraField(ZipExtraField p0) {} + + public void addExtraField(ZipExtraField p0) {} + + public void removeExtraField(ZipShort p0) {} + + public void removeUnparseableExtraFieldData() {} + + public void setCentralDirectoryExtra(byte[] p0) {} + + public void setComprSize(long p0) {} + + public void setExternalAttributes(long p0) {} + + public void setExtra(byte[] p0) {} + + public void setExtraFields(ZipExtraField[] p0) {} + + public void setGeneralPurposeBit(GeneralPurposeBit p0) {} + + public void setInternalAttributes(int p0) {} + + public void setMethod(int p0) {} + + public void setSize(long p0) {} + + public void setUnixMode(int p0) {} +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipExtraField.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipExtraField.java new file mode 100644 index 00000000000..9fbac163529 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipExtraField.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.tools.zip.ZipExtraField for testing purposes + +package org.apache.tools.zip; + +import org.apache.tools.zip.ZipShort; + +public interface ZipExtraField +{ + ZipShort getCentralDirectoryLength(); + ZipShort getHeaderId(); + ZipShort getLocalFileDataLength(); + byte[] getCentralDirectoryData(); + byte[] getLocalFileDataData(); + void parseFromLocalFileData(byte[] p0, int p1, int p2); +} diff --git a/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipShort.java b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipShort.java new file mode 100644 index 00000000000..7d60df12c47 --- /dev/null +++ b/java/ql/test/stubs/apache-ant-1.10.13/org/apache/tools/zip/ZipShort.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.tools.zip.ZipShort for testing purposes + +package org.apache.tools.zip; + + +public class ZipShort implements Cloneable +{ + protected ZipShort() {} + public Object clone(){ return null; } + public String toString(){ return null; } + public ZipShort(byte[] p0){} + public ZipShort(byte[] p0, int p1){} + public ZipShort(int p0){} + public boolean equals(Object p0){ return false; } + public byte[] getBytes(){ return null; } + public int getValue(){ return 0; } + public int hashCode(){ return 0; } + public static byte[] getBytes(int p0){ return null; } + public static int getValue(byte[] p0){ return 0; } + public static int getValue(byte[] p0, int p1){ return 0; } + public static void putShort(int p0, byte[] p1, int p2){} +} diff --git a/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/ConvertUtilsBean.java b/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/ConvertUtilsBean.java new file mode 100644 index 00000000000..778efe2ca42 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/ConvertUtilsBean.java @@ -0,0 +1,37 @@ +// Generated automatically from org.apache.commons.beanutils.ConvertUtilsBean for testing purposes + +package org.apache.commons.beanutils; + +import org.apache.commons.beanutils.Converter; + +public class ConvertUtilsBean +{ + protected static ConvertUtilsBean getInstance(){ return null; } + public ConvertUtilsBean(){} + public Converter lookup(Class p0){ return null; } + public Converter lookup(Class p0, Class p1){ return null; } + public Object convert(Object p0, Class p1){ return null; } + public Object convert(String p0, Class p1){ return null; } + public Object convert(String[] p0, Class p1){ return null; } + public String convert(Object p0){ return null; } + public boolean getDefaultBoolean(){ return false; } + public byte getDefaultByte(){ return 0; } + public char getDefaultCharacter(){ return '0'; } + public double getDefaultDouble(){ return 0; } + public float getDefaultFloat(){ return 0; } + public int getDefaultInteger(){ return 0; } + public long getDefaultLong(){ return 0; } + public short getDefaultShort(){ return 0; } + public void deregister(){} + public void deregister(Class p0){} + public void register(Converter p0, Class p1){} + public void register(boolean p0, boolean p1, int p2){} + public void setDefaultBoolean(boolean p0){} + public void setDefaultByte(byte p0){} + public void setDefaultCharacter(char p0){} + public void setDefaultDouble(double p0){} + public void setDefaultFloat(float p0){} + public void setDefaultInteger(int p0){} + public void setDefaultLong(long p0){} + public void setDefaultShort(short p0){} +} diff --git a/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/Converter.java b/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/Converter.java new file mode 100644 index 00000000000..b83205d5cda --- /dev/null +++ b/java/ql/test/stubs/apache-commons-beanutils/org/apache/commons/beanutils/Converter.java @@ -0,0 +1,9 @@ +// Generated automatically from org.apache.commons.beanutils.Converter for testing purposes + +package org.apache.commons.beanutils; + + +public interface Converter +{ + T convert(java.lang.Class p0, Object p1); +} diff --git a/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/ArchiveEntry.java b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/ArchiveEntry.java new file mode 100644 index 00000000000..73fb5d3fa1b --- /dev/null +++ b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/ArchiveEntry.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.commons.compress.archivers.ArchiveEntry for testing purposes + +package org.apache.commons.compress.archivers; + +import java.util.Date; + +public interface ArchiveEntry +{ + Date getLastModifiedDate(); + String getName(); + boolean isDirectory(); + long getSize(); + static long SIZE_UNKNOWN = 0; +} diff --git a/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java new file mode 100644 index 00000000000..ef17fdf904b --- /dev/null +++ b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarArchiveEntry.java @@ -0,0 +1,92 @@ +// Generated automatically from org.apache.commons.compress.archivers.tar.TarArchiveEntry for testing purposes + +package org.apache.commons.compress.archivers.tar; + +import java.io.File; +import java.util.Date; +import java.util.Map; +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarConstants; +import org.apache.commons.compress.archivers.zip.ZipEncoding; + +public class TarArchiveEntry implements ArchiveEntry, TarConstants +{ + protected TarArchiveEntry() {} + public Date getLastModifiedDate(){ return null; } + public Date getModTime(){ return null; } + public File getFile(){ return null; } + public Map getExtraPaxHeaders(){ return null; } + public String getExtraPaxHeader(String p0){ return null; } + public String getGroupName(){ return null; } + public String getLinkName(){ return null; } + public String getName(){ return null; } + public String getUserName(){ return null; } + public TarArchiveEntry(File p0){} + public TarArchiveEntry(File p0, String p1){} + public TarArchiveEntry(String p0){} + public TarArchiveEntry(String p0, boolean p1){} + public TarArchiveEntry(String p0, byte p1){} + public TarArchiveEntry(String p0, byte p1, boolean p2){} + public TarArchiveEntry(byte[] p0){} + public TarArchiveEntry(byte[] p0, ZipEncoding p1){} + public TarArchiveEntry(byte[] p0, ZipEncoding p1, boolean p2){} + public TarArchiveEntry[] getDirectoryEntries(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean equals(TarArchiveEntry p0){ return false; } + public boolean isBlockDevice(){ return false; } + public boolean isCharacterDevice(){ return false; } + public boolean isCheckSumOK(){ return false; } + public boolean isDescendent(TarArchiveEntry p0){ return false; } + public boolean isDirectory(){ return false; } + public boolean isExtended(){ return false; } + public boolean isFIFO(){ return false; } + public boolean isFile(){ return false; } + public boolean isGNULongLinkEntry(){ return false; } + public boolean isGNULongNameEntry(){ return false; } + public boolean isGNUSparse(){ return false; } + public boolean isGlobalPaxHeader(){ return false; } + public boolean isLink(){ return false; } + public boolean isOldGNUSparse(){ return false; } + public boolean isPaxGNUSparse(){ return false; } + public boolean isPaxHeader(){ return false; } + public boolean isSparse(){ return false; } + public boolean isStarSparse(){ return false; } + public boolean isSymbolicLink(){ return false; } + public int getDevMajor(){ return 0; } + public int getDevMinor(){ return 0; } + public int getGroupId(){ return 0; } + public int getMode(){ return 0; } + public int getUserId(){ return 0; } + public int hashCode(){ return 0; } + public long getLongGroupId(){ return 0; } + public long getLongUserId(){ return 0; } + public long getRealSize(){ return 0; } + public long getSize(){ return 0; } + public static int DEFAULT_DIR_MODE = 0; + public static int DEFAULT_FILE_MODE = 0; + public static int MAX_NAMELEN = 0; + public static int MILLIS_PER_SECOND = 0; + public static long UNKNOWN = 0; + public void addPaxHeader(String p0, String p1){} + public void clearExtraPaxHeaders(){} + public void parseTarHeader(byte[] p0){} + public void parseTarHeader(byte[] p0, ZipEncoding p1){} + public void setDevMajor(int p0){} + public void setDevMinor(int p0){} + public void setGroupId(int p0){} + public void setGroupId(long p0){} + public void setGroupName(String p0){} + public void setIds(int p0, int p1){} + public void setLinkName(String p0){} + public void setModTime(Date p0){} + public void setModTime(long p0){} + public void setMode(int p0){} + public void setName(String p0){} + public void setNames(String p0, String p1){} + public void setSize(long p0){} + public void setUserId(int p0){} + public void setUserId(long p0){} + public void setUserName(String p0){} + public void writeEntryHeader(byte[] p0){} + public void writeEntryHeader(byte[] p0, ZipEncoding p1, boolean p2){} +} diff --git a/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarConstants.java b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarConstants.java new file mode 100644 index 00000000000..8fd72f07a54 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/tar/TarConstants.java @@ -0,0 +1,70 @@ +// Generated automatically from org.apache.commons.compress.archivers.tar.TarConstants for testing purposes + +package org.apache.commons.compress.archivers.tar; + + +public interface TarConstants +{ + static String GNU_LONGLINK = null; + static String MAGIC_ANT = null; + static String MAGIC_GNU = null; + static String MAGIC_POSIX = null; + static String MAGIC_XSTAR = null; + static String VERSION_ANT = null; + static String VERSION_GNU_SPACE = null; + static String VERSION_GNU_ZERO = null; + static String VERSION_POSIX = null; + static byte LF_BLK = 0; + static byte LF_CHR = 0; + static byte LF_CONTIG = 0; + static byte LF_DIR = 0; + static byte LF_FIFO = 0; + static byte LF_GNUTYPE_LONGLINK = 0; + static byte LF_GNUTYPE_LONGNAME = 0; + static byte LF_GNUTYPE_SPARSE = 0; + static byte LF_LINK = 0; + static byte LF_NORMAL = 0; + static byte LF_OLDNORM = 0; + static byte LF_PAX_EXTENDED_HEADER_LC = 0; + static byte LF_PAX_EXTENDED_HEADER_UC = 0; + static byte LF_PAX_GLOBAL_EXTENDED_HEADER = 0; + static byte LF_SYMLINK = 0; + static int ATIMELEN_GNU = 0; + static int ATIMELEN_XSTAR = 0; + static int CHKSUMLEN = 0; + static int CHKSUM_OFFSET = 0; + static int CTIMELEN_GNU = 0; + static int CTIMELEN_XSTAR = 0; + static int DEFAULT_BLKSIZE = 0; + static int DEFAULT_RCDSIZE = 0; + static int DEVLEN = 0; + static int FORMAT_OLDGNU = 0; + static int FORMAT_POSIX = 0; + static int FORMAT_XSTAR = 0; + static int GIDLEN = 0; + static int GNAMELEN = 0; + static int ISEXTENDEDLEN_GNU = 0; + static int ISEXTENDEDLEN_GNU_SPARSE = 0; + static int LONGNAMESLEN_GNU = 0; + static int MAGICLEN = 0; + static int MAGIC_OFFSET = 0; + static int MODELEN = 0; + static int MODTIMELEN = 0; + static int NAMELEN = 0; + static int OFFSETLEN_GNU = 0; + static int PAD2LEN_GNU = 0; + static int PREFIXLEN = 0; + static int PREFIXLEN_XSTAR = 0; + static int REALSIZELEN_GNU = 0; + static int SIZELEN = 0; + static int SPARSELEN_GNU = 0; + static int SPARSELEN_GNU_SPARSE = 0; + static int UIDLEN = 0; + static int UNAMELEN = 0; + static int VERSIONLEN = 0; + static int VERSION_OFFSET = 0; + static int XSTAR_MAGIC_LEN = 0; + static int XSTAR_MAGIC_OFFSET = 0; + static long MAXID = 0; + static long MAXSIZE = 0; +} diff --git a/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/zip/ZipEncoding.java b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/zip/ZipEncoding.java new file mode 100644 index 00000000000..246fcc8e75d --- /dev/null +++ b/java/ql/test/stubs/apache-commons-compress/org/apache/commons/compress/archivers/zip/ZipEncoding.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.compress.archivers.zip.ZipEncoding for testing purposes + +package org.apache.commons.compress.archivers.zip; + +import java.nio.ByteBuffer; + +public interface ZipEncoding +{ + ByteBuffer encode(String p0); + String decode(byte[] p0); + boolean canEncode(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItem.java b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItem.java new file mode 100644 index 00000000000..bb16bf3338f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItem.java @@ -0,0 +1,27 @@ +// Generated automatically from org.apache.commons.fileupload.FileItem for testing purposes + +package org.apache.commons.fileupload; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.commons.fileupload.FileItemHeadersSupport; + +public interface FileItem extends FileItemHeadersSupport +{ + InputStream getInputStream(); + OutputStream getOutputStream(); + String getContentType(); + String getFieldName(); + String getName(); + String getString(); + String getString(String p0); + boolean isFormField(); + boolean isInMemory(); + byte[] get(); + long getSize(); + void delete(); + void setFieldName(String p0); + void setFormField(boolean p0); + void write(File p0); +} diff --git a/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeaders.java b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeaders.java new file mode 100644 index 00000000000..b502807edae --- /dev/null +++ b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeaders.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.fileupload.FileItemHeaders for testing purposes + +package org.apache.commons.fileupload; + +import java.util.Iterator; + +public interface FileItemHeaders +{ + Iterator getHeaderNames(); + Iterator getHeaders(String p0); + String getHeader(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeadersSupport.java b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeadersSupport.java new file mode 100644 index 00000000000..2b5b27d7361 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-fileupload-1.4/org/apache/commons/fileupload/FileItemHeadersSupport.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.fileupload.FileItemHeadersSupport for testing purposes + +package org.apache.commons.fileupload; + +import org.apache.commons.fileupload.FileItemHeaders; + +public interface FileItemHeadersSupport +{ + FileItemHeaders getHeaders(); + void setHeaders(FileItemHeaders p0); +} diff --git a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/FileUtils.java b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/FileUtils.java new file mode 100644 index 00000000000..1e5e603d915 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/FileUtils.java @@ -0,0 +1,173 @@ +// Generated automatically from org.apache.commons.io.FileUtils for testing purposes + +package org.apache.commons.io; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.math.BigInteger; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.file.CopyOption; +import java.nio.file.LinkOption; +import java.time.Instant; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.chrono.ChronoLocalDate; +import java.time.chrono.ChronoLocalDateTime; +import java.time.chrono.ChronoZonedDateTime; +import java.util.Collection; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Stream; +import java.util.zip.Checksum; +import org.apache.commons.io.LineIterator; +import org.apache.commons.io.filefilter.IOFileFilter; + +public class FileUtils +{ + public FileUtils(){} + public static BigInteger ONE_EB_BI = null; + public static BigInteger ONE_GB_BI = null; + public static BigInteger ONE_KB_BI = null; + public static BigInteger ONE_MB_BI = null; + public static BigInteger ONE_PB_BI = null; + public static BigInteger ONE_TB_BI = null; + public static BigInteger ONE_YB = null; + public static BigInteger ONE_ZB = null; + public static BigInteger sizeOfAsBigInteger(File p0){ return null; } + public static BigInteger sizeOfDirectoryAsBigInteger(File p0){ return null; } + public static Checksum checksum(File p0, Checksum p1){ return null; } + public static Collection listFiles(File p0, IOFileFilter p1, IOFileFilter p2){ return null; } + public static Collection listFiles(File p0, String[] p1, boolean p2){ return null; } + public static Collection listFilesAndDirs(File p0, IOFileFilter p1, IOFileFilter p2){ return null; } + public static File createParentDirectories(File p0){ return null; } + public static File delete(File p0){ return null; } + public static File getFile(File p0, String... p1){ return null; } + public static File getFile(String... p0){ return null; } + public static File getTempDirectory(){ return null; } + public static File getUserDirectory(){ return null; } + public static File toFile(URL p0){ return null; } + public static FileInputStream openInputStream(File p0){ return null; } + public static FileOutputStream openOutputStream(File p0){ return null; } + public static FileOutputStream openOutputStream(File p0, boolean p1){ return null; } + public static File[] EMPTY_FILE_ARRAY = null; + public static File[] convertFileCollectionToFileArray(Collection p0){ return null; } + public static File[] toFiles(URL... p0){ return null; } + public static Iterator iterateFiles(File p0, IOFileFilter p1, IOFileFilter p2){ return null; } + public static Iterator iterateFiles(File p0, String[] p1, boolean p2){ return null; } + public static Iterator iterateFilesAndDirs(File p0, IOFileFilter p1, IOFileFilter p2){ return null; } + public static LineIterator lineIterator(File p0){ return null; } + public static LineIterator lineIterator(File p0, String p1){ return null; } + public static List readLines(File p0){ return null; } + public static List readLines(File p0, Charset p1){ return null; } + public static List readLines(File p0, String p1){ return null; } + public static Stream streamFiles(File p0, boolean p1, String... p2){ return null; } + public static String byteCountToDisplaySize(BigInteger p0){ return null; } + public static String byteCountToDisplaySize(long p0){ return null; } + public static String getTempDirectoryPath(){ return null; } + public static String getUserDirectoryPath(){ return null; } + public static String readFileToString(File p0){ return null; } + public static String readFileToString(File p0, Charset p1){ return null; } + public static String readFileToString(File p0, String p1){ return null; } + public static URL[] toURLs(File... p0){ return null; } + public static boolean contentEquals(File p0, File p1){ return false; } + public static boolean contentEqualsIgnoreEOL(File p0, File p1, String p2){ return false; } + public static boolean deleteQuietly(File p0){ return false; } + public static boolean directoryContains(File p0, File p1){ return false; } + public static boolean isDirectory(File p0, LinkOption... p1){ return false; } + public static boolean isEmptyDirectory(File p0){ return false; } + public static boolean isFileNewer(File p0, ChronoLocalDate p1){ return false; } + public static boolean isFileNewer(File p0, ChronoLocalDate p1, LocalTime p2){ return false; } + public static boolean isFileNewer(File p0, ChronoLocalDateTime p1){ return false; } + public static boolean isFileNewer(File p0, ChronoLocalDateTime p1, ZoneId p2){ return false; } + public static boolean isFileNewer(File p0, ChronoZonedDateTime p1){ return false; } + public static boolean isFileNewer(File p0, Date p1){ return false; } + public static boolean isFileNewer(File p0, File p1){ return false; } + public static boolean isFileNewer(File p0, Instant p1){ return false; } + public static boolean isFileNewer(File p0, long p1){ return false; } + public static boolean isFileOlder(File p0, ChronoLocalDate p1){ return false; } + public static boolean isFileOlder(File p0, ChronoLocalDate p1, LocalTime p2){ return false; } + public static boolean isFileOlder(File p0, ChronoLocalDateTime p1){ return false; } + public static boolean isFileOlder(File p0, ChronoLocalDateTime p1, ZoneId p2){ return false; } + public static boolean isFileOlder(File p0, ChronoZonedDateTime p1){ return false; } + public static boolean isFileOlder(File p0, Date p1){ return false; } + public static boolean isFileOlder(File p0, File p1){ return false; } + public static boolean isFileOlder(File p0, Instant p1){ return false; } + public static boolean isFileOlder(File p0, long p1){ return false; } + public static boolean isRegularFile(File p0, LinkOption... p1){ return false; } + public static boolean isSymlink(File p0){ return false; } + public static boolean waitFor(File p0, int p1){ return false; } + public static byte[] readFileToByteArray(File p0){ return null; } + public static long ONE_EB = 0; + public static long ONE_GB = 0; + public static long ONE_KB = 0; + public static long ONE_MB = 0; + public static long ONE_PB = 0; + public static long ONE_TB = 0; + public static long checksumCRC32(File p0){ return 0; } + public static long copyFile(File p0, OutputStream p1){ return 0; } + public static long lastModified(File p0){ return 0; } + public static long lastModifiedUnchecked(File p0){ return 0; } + public static long sizeOf(File p0){ return 0; } + public static long sizeOfDirectory(File p0){ return 0; } + public static void cleanDirectory(File p0){} + public static void copyDirectory(File p0, File p1){} + public static void copyDirectory(File p0, File p1, FileFilter p2){} + public static void copyDirectory(File p0, File p1, FileFilter p2, boolean p3){} + public static void copyDirectory(File p0, File p1, FileFilter p2, boolean p3, CopyOption... p4){} + public static void copyDirectory(File p0, File p1, boolean p2){} + public static void copyDirectoryToDirectory(File p0, File p1){} + public static void copyFile(File p0, File p1){} + public static void copyFile(File p0, File p1, CopyOption... p2){} + public static void copyFile(File p0, File p1, boolean p2){} + public static void copyFile(File p0, File p1, boolean p2, CopyOption... p3){} + public static void copyFileToDirectory(File p0, File p1){} + public static void copyFileToDirectory(File p0, File p1, boolean p2){} + public static void copyInputStreamToFile(InputStream p0, File p1){} + public static void copyToDirectory(File p0, File p1){} + public static void copyToDirectory(Iterable p0, File p1){} + public static void copyToFile(InputStream p0, File p1){} + public static void copyURLToFile(URL p0, File p1){} + public static void copyURLToFile(URL p0, File p1, int p2, int p3){} + public static void deleteDirectory(File p0){} + public static void forceDelete(File p0){} + public static void forceDeleteOnExit(File p0){} + public static void forceMkdir(File p0){} + public static void forceMkdirParent(File p0){} + public static void moveDirectory(File p0, File p1){} + public static void moveDirectoryToDirectory(File p0, File p1, boolean p2){} + public static void moveFile(File p0, File p1){} + public static void moveFile(File p0, File p1, CopyOption... p2){} + public static void moveFileToDirectory(File p0, File p1, boolean p2){} + public static void moveToDirectory(File p0, File p1, boolean p2){} + public static void touch(File p0){} + public static void write(File p0, CharSequence p1){} + public static void write(File p0, CharSequence p1, Charset p2){} + public static void write(File p0, CharSequence p1, Charset p2, boolean p3){} + public static void write(File p0, CharSequence p1, String p2){} + public static void write(File p0, CharSequence p1, String p2, boolean p3){} + public static void write(File p0, CharSequence p1, boolean p2){} + public static void writeByteArrayToFile(File p0, byte[] p1){} + public static void writeByteArrayToFile(File p0, byte[] p1, boolean p2){} + public static void writeByteArrayToFile(File p0, byte[] p1, int p2, int p3){} + public static void writeByteArrayToFile(File p0, byte[] p1, int p2, int p3, boolean p4){} + public static void writeLines(File p0, Collection p1){} + public static void writeLines(File p0, Collection p1, String p2){} + public static void writeLines(File p0, Collection p1, String p2, boolean p3){} + public static void writeLines(File p0, Collection p1, boolean p2){} + public static void writeLines(File p0, String p1, Collection p2){} + public static void writeLines(File p0, String p1, Collection p2, String p3){} + public static void writeLines(File p0, String p1, Collection p2, String p3, boolean p4){} + public static void writeLines(File p0, String p1, Collection p2, boolean p3){} + public static void writeStringToFile(File p0, String p1){} + public static void writeStringToFile(File p0, String p1, Charset p2){} + public static void writeStringToFile(File p0, String p1, Charset p2, boolean p3){} + public static void writeStringToFile(File p0, String p1, String p2){} + public static void writeStringToFile(File p0, String p1, String p2, boolean p3){} + public static void writeStringToFile(File p0, String p1, boolean p2){} +} diff --git a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/LineIterator.java b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/LineIterator.java new file mode 100644 index 00000000000..7310d52b888 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/LineIterator.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.commons.io.LineIterator for testing purposes + +package org.apache.commons.io; + +import java.io.Closeable; +import java.io.Reader; +import java.util.Iterator; + +public class LineIterator implements Closeable, Iterator +{ + protected LineIterator() {} + protected boolean isValidLine(String p0){ return false; } + public LineIterator(Reader p0){} + public String next(){ return null; } + public String nextLine(){ return null; } + public boolean hasNext(){ return false; } + public static void closeQuietly(LineIterator p0){} + public void close(){} + public void remove(){} +} diff --git a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/file/PathFilter.java b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/file/PathFilter.java new file mode 100644 index 00000000000..c0c4593b977 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/file/PathFilter.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.io.file.PathFilter for testing purposes + +package org.apache.commons.io.file; + +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; + +public interface PathFilter +{ + FileVisitResult accept(Path p0, BasicFileAttributes p1); +} diff --git a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/filefilter/IOFileFilter.java b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/filefilter/IOFileFilter.java new file mode 100644 index 00000000000..3721d146b61 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/filefilter/IOFileFilter.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.commons.io.filefilter.IOFileFilter for testing purposes + +package org.apache.commons.io.filefilter; + +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; +import java.nio.file.FileVisitResult; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import org.apache.commons.io.file.PathFilter; + +public interface IOFileFilter extends FileFilter, FilenameFilter, PathFilter +{ + boolean accept(File p0); + boolean accept(File p0, String p1); + default FileVisitResult accept(Path p0, BasicFileAttributes p1){ return null; } + default IOFileFilter and(IOFileFilter p0){ return null; } + default IOFileFilter negate(){ return null; } + default IOFileFilter or(IOFileFilter p0){ return null; } + static String[] EMPTY_STRING_ARRAY = null; +} diff --git a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java index 3c7c9c5ebf5..19a64de1972 100644 --- a/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java +++ b/java/ql/test/stubs/apache-commons-io-2.6/org/apache/commons/io/output/LockableFileWriter.java @@ -1,7 +1,29 @@ +// Generated automatically from org.apache.commons.io.output.LockableFileWriter for testing purposes + package org.apache.commons.io.output; -public class LockableFileWriter { - - public LockableFileWriter(String filename) { } +import java.io.File; +import java.io.Writer; +import java.nio.charset.Charset; +public class LockableFileWriter extends Writer +{ + protected LockableFileWriter() {} + public LockableFileWriter(File p0){} + public LockableFileWriter(File p0, Charset p1){} + public LockableFileWriter(File p0, Charset p1, boolean p2, String p3){} + public LockableFileWriter(File p0, String p1){} + public LockableFileWriter(File p0, String p1, boolean p2, String p3){} + public LockableFileWriter(File p0, boolean p1){} + public LockableFileWriter(File p0, boolean p1, String p2){} + public LockableFileWriter(String p0){} + public LockableFileWriter(String p0, boolean p1){} + public LockableFileWriter(String p0, boolean p1, String p2){} + public void close(){} + public void flush(){} + public void write(String p0){} + public void write(String p0, int p1, int p2){} + public void write(char[] p0){} + public void write(char[] p0, int p1, int p2){} + public void write(int p0){} } diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyContext.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyContext.java new file mode 100644 index 00000000000..7975d079ea4 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyContext.java @@ -0,0 +1,82 @@ +// Generated automatically from org.apache.commons.jelly.JellyContext for testing purposes + +package org.apache.commons.jelly; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.Iterator; +import java.util.Map; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.TagLibrary; +import org.apache.commons.jelly.XMLOutput; +import org.apache.commons.jelly.parser.XMLParser; +import org.xml.sax.InputSource; + +public class JellyContext +{ + protected ClassLoader classLoader = null; + protected JellyContext createChildContext(){ return null; } + protected URL createRelativeURL(URL p0, String p1){ return null; } + protected URL getJellyContextURL(InputSource p0){ return null; } + protected URL getJellyContextURL(URL p0){ return null; } + protected XMLParser createXMLParser(){ return null; } + protected XMLParser getXMLParser(){ return null; } + protected boolean useContextClassLoader = false; + protected void clearVariables(){} + protected void setParent(JellyContext p0){} + public ClassLoader getClassLoader(){ return null; } + public InputStream getResourceAsStream(String p0){ return null; } + public Iterator getVariableNames(){ return null; } + public JellyContext getParent(){ return null; } + public JellyContext getScope(String p0){ return null; } + public JellyContext newJellyContext(){ return null; } + public JellyContext newJellyContext(Map p0){ return null; } + public JellyContext runScript(File p0, XMLOutput p1){ return null; } + public JellyContext runScript(File p0, XMLOutput p1, boolean p2, boolean p3){ return null; } + public JellyContext runScript(InputSource p0, XMLOutput p1){ return null; } + public JellyContext runScript(InputSource p0, XMLOutput p1, boolean p2, boolean p3){ return null; } + public JellyContext runScript(String p0, XMLOutput p1){ return null; } + public JellyContext runScript(String p0, XMLOutput p1, boolean p2, boolean p3){ return null; } + public JellyContext runScript(URL p0, XMLOutput p1){ return null; } + public JellyContext runScript(URL p0, XMLOutput p1, boolean p2, boolean p3){ return null; } + public JellyContext(){} + public JellyContext(JellyContext p0){} + public JellyContext(JellyContext p0, URL p1){} + public JellyContext(JellyContext p0, URL p1, URL p2){} + public JellyContext(URL p0){} + public JellyContext(URL p0, URL p1){} + public Map getVariables(){ return null; } + public Object findVariable(String p0){ return null; } + public Object getVariable(String p0){ return null; } + public Object getVariable(String p0, String p1){ return null; } + public Script compileScript(InputSource p0){ return null; } + public Script compileScript(String p0){ return null; } + public Script compileScript(URL p0){ return null; } + public TagLibrary getTagLibrary(String p0){ return null; } + public URL getCurrentURL(){ return null; } + public URL getResource(String p0){ return null; } + public URL getRootURL(){ return null; } + public boolean getUseContextClassLoader(){ return false; } + public boolean isAllowDtdToCallExternalEntities(){ return false; } + public boolean isExport(){ return false; } + public boolean isExportLibraries(){ return false; } + public boolean isInherit(){ return false; } + public boolean isTagLibraryRegistered(String p0){ return false; } + public void clear(){} + public void registerTagLibrary(String p0, String p1){} + public void registerTagLibrary(String p0, TagLibrary p1){} + public void removeVariable(String p0){} + public void removeVariable(String p0, String p1){} + public void setAllowDtdToCallExternalEntities(boolean p0){} + public void setClassLoader(ClassLoader p0){} + public void setCurrentURL(URL p0){} + public void setExport(boolean p0){} + public void setExportLibraries(boolean p0){} + public void setInherit(boolean p0){} + public void setRootURL(URL p0){} + public void setUseContextClassLoader(boolean p0){} + public void setVariable(String p0, Object p1){} + public void setVariable(String p0, String p1, Object p2){} + public void setVariables(Map p0){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyException.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyException.java new file mode 100644 index 00000000000..5f81095501d --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyException.java @@ -0,0 +1,32 @@ +// Generated automatically from org.apache.commons.jelly.JellyException for testing purposes + +package org.apache.commons.jelly; + +import java.io.PrintStream; +import java.io.PrintWriter; +import org.apache.commons.jelly.LocationAware; + +public class JellyException extends Exception implements LocationAware +{ + public JellyException(){} + public JellyException(String p0){} + public JellyException(String p0, String p1, String p2, int p3, int p4){} + public JellyException(String p0, Throwable p1){} + public JellyException(String p0, Throwable p1, String p2, String p3, int p4, int p5){} + public JellyException(Throwable p0){} + public JellyException(Throwable p0, String p1, String p2, int p3, int p4){} + public String getElementName(){ return null; } + public String getFileName(){ return null; } + public String getMessage(){ return null; } + public String getReason(){ return null; } + public Throwable getCause(){ return null; } + public int getColumnNumber(){ return 0; } + public int getLineNumber(){ return 0; } + public void printStackTrace(){} + public void printStackTrace(PrintStream p0){} + public void printStackTrace(PrintWriter p0){} + public void setColumnNumber(int p0){} + public void setElementName(String p0){} + public void setFileName(String p0){} + public void setLineNumber(int p0){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyTagException.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyTagException.java new file mode 100644 index 00000000000..f2e2039c33f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/JellyTagException.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.jelly.JellyTagException for testing purposes + +package org.apache.commons.jelly; + +import org.apache.commons.jelly.JellyException; + +public class JellyTagException extends JellyException +{ + public JellyTagException(){} + public JellyTagException(String p0){} + public JellyTagException(String p0, String p1, String p2, int p3, int p4){} + public JellyTagException(String p0, Throwable p1){} + public JellyTagException(String p0, Throwable p1, String p2, String p3, int p4, int p5){} + public JellyTagException(Throwable p0){} + public JellyTagException(Throwable p0, String p1, String p2, int p3, int p4){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/LocationAware.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/LocationAware.java new file mode 100644 index 00000000000..506fc26ad91 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/LocationAware.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.jelly.LocationAware for testing purposes + +package org.apache.commons.jelly; + + +public interface LocationAware +{ + String getElementName(); + String getFileName(); + int getColumnNumber(); + int getLineNumber(); + void setColumnNumber(int p0); + void setElementName(String p0); + void setFileName(String p0); + void setLineNumber(int p0); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Script.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Script.java new file mode 100644 index 00000000000..72bbcdee0f7 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Script.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.commons.jelly.Script for testing purposes + +package org.apache.commons.jelly; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.XMLOutput; + +public interface Script +{ + Script compile(); + void run(JellyContext p0, XMLOutput p1); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Tag.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Tag.java new file mode 100644 index 00000000000..e697338ea19 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/Tag.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.commons.jelly.Tag for testing purposes + +package org.apache.commons.jelly; + +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.XMLOutput; + +public interface Tag +{ + JellyContext getContext(); + Script getBody(); + Tag getParent(); + void doTag(XMLOutput p0); + void invokeBody(XMLOutput p0); + void setBody(Script p0); + void setContext(JellyContext p0); + void setParent(Tag p0); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/TagLibrary.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/TagLibrary.java new file mode 100644 index 00000000000..1074c22554a --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/TagLibrary.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.commons.jelly.TagLibrary for testing purposes + +package org.apache.commons.jelly; + +import java.util.Map; +import org.apache.commons.jelly.Tag; +import org.apache.commons.jelly.expression.Expression; +import org.apache.commons.jelly.expression.ExpressionFactory; +import org.apache.commons.jelly.impl.TagFactory; +import org.apache.commons.jelly.impl.TagScript; +import org.xml.sax.Attributes; + +abstract public class TagLibrary +{ + protected ExpressionFactory getExpressionFactory(){ return null; } + protected Map getTagClasses(){ return null; } + protected void registerTag(String p0, Class p1){} + protected void registerTagFactory(String p0, TagFactory p1){} + public Expression createExpression(ExpressionFactory p0, TagScript p1, String p2, String p3){ return null; } + public Tag createTag(String p0, Attributes p1){ return null; } + public TagLibrary(){} + public TagScript createTagScript(String p0, Attributes p1){ return null; } +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/XMLOutput.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/XMLOutput.java new file mode 100644 index 00000000000..5517aebb64d --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/XMLOutput.java @@ -0,0 +1,59 @@ +// Generated automatically from org.apache.commons.jelly.XMLOutput for testing purposes + +package org.apache.commons.jelly; + +import java.io.OutputStream; +import java.io.Writer; +import org.dom4j.io.XMLWriter; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.XMLReader; +import org.xml.sax.ext.LexicalHandler; + +public class XMLOutput implements ContentHandler, LexicalHandler +{ + protected static String[] LEXICAL_HANDLER_NAMES = null; + protected static XMLOutput createXMLOutput(XMLWriter p0){ return null; } + public ContentHandler getContentHandler(){ return null; } + public LexicalHandler getLexicalHandler(){ return null; } + public String toString(){ return null; } + public XMLOutput(){} + public XMLOutput(ContentHandler p0){} + public XMLOutput(ContentHandler p0, LexicalHandler p1){} + public static XMLOutput createDummyXMLOutput(){ return null; } + public static XMLOutput createXMLOutput(OutputStream p0){ return null; } + public static XMLOutput createXMLOutput(OutputStream p0, boolean p1){ return null; } + public static XMLOutput createXMLOutput(Writer p0){ return null; } + public static XMLOutput createXMLOutput(Writer p0, boolean p1){ return null; } + public static XMLOutput createXMLOutput(XMLReader p0){ return null; } + public void characters(char[] p0, int p1, int p2){} + public void close(){} + public void comment(char[] p0, int p1, int p2){} + public void endCDATA(){} + public void endDTD(){} + public void endDocument(){} + public void endElement(String p0){} + public void endElement(String p0, String p1, String p2){} + public void endEntity(String p0){} + public void endPrefixMapping(String p0){} + public void flush(){} + public void ignorableWhitespace(char[] p0, int p1, int p2){} + public void objectData(Object p0){} + public void processingInstruction(String p0, String p1){} + public void setContentHandler(ContentHandler p0){} + public void setDocumentLocator(Locator p0){} + public void setLexicalHandler(LexicalHandler p0){} + public void skippedEntity(String p0){} + public void startCDATA(){} + public void startDTD(String p0, String p1, String p2){} + public void startDocument(){} + public void startElement(String p0){} + public void startElement(String p0, Attributes p1){} + public void startElement(String p0, String p1, String p2, Attributes p3){} + public void startEntity(String p0){} + public void startPrefixMapping(String p0, String p1){} + public void write(String p0){} + public void writeCDATA(String p0){} + public void writeComment(String p0){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/Expression.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/Expression.java new file mode 100644 index 00000000000..36abe33c196 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/Expression.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.commons.jelly.expression.Expression for testing purposes + +package org.apache.commons.jelly.expression; + +import java.util.Iterator; +import org.apache.commons.jelly.JellyContext; + +public interface Expression +{ + Iterator evaluateAsIterator(JellyContext p0); + Object evaluate(JellyContext p0); + Object evaluateRecurse(JellyContext p0); + String evaluateAsString(JellyContext p0); + String getExpressionText(); + boolean evaluateAsBoolean(JellyContext p0); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/ExpressionFactory.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/ExpressionFactory.java new file mode 100644 index 00000000000..e4125b8d11f --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/expression/ExpressionFactory.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.commons.jelly.expression.ExpressionFactory for testing purposes + +package org.apache.commons.jelly.expression; + +import org.apache.commons.jelly.expression.Expression; + +public interface ExpressionFactory +{ + Expression createExpression(String p0); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/ScriptBlock.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/ScriptBlock.java new file mode 100644 index 00000000000..2f2571fdbac --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/ScriptBlock.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.commons.jelly.impl.ScriptBlock for testing purposes + +package org.apache.commons.jelly.impl; + +import java.util.List; +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.XMLOutput; + +public class ScriptBlock implements Script +{ + public List getScriptList(){ return null; } + public Script compile(){ return null; } + public ScriptBlock(){} + public String toString(){ return null; } + public void addScript(Script p0){} + public void removeScript(Script p0){} + public void run(JellyContext p0, XMLOutput p1){} + public void trimWhitespace(){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagFactory.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagFactory.java new file mode 100644 index 00000000000..0b206865be9 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagFactory.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.commons.jelly.impl.TagFactory for testing purposes + +package org.apache.commons.jelly.impl; + +import org.apache.commons.jelly.Tag; +import org.xml.sax.Attributes; + +public interface TagFactory +{ + Tag createTag(String p0, Attributes p1); +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagScript.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagScript.java new file mode 100644 index 00000000000..04cd3aee9d1 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/impl/TagScript.java @@ -0,0 +1,64 @@ +// Generated automatically from org.apache.commons.jelly.impl.TagScript for testing purposes + +package org.apache.commons.jelly.impl; + +import java.util.Map; +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.JellyException; +import org.apache.commons.jelly.JellyTagException; +import org.apache.commons.jelly.LocationAware; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.Tag; +import org.apache.commons.jelly.XMLOutput; +import org.apache.commons.jelly.expression.Expression; +import org.apache.commons.jelly.impl.TagFactory; +import org.xml.sax.Attributes; +import org.xml.sax.Locator; + +public class TagScript implements Script +{ + protected JellyException createJellyException(String p0){ return null; } + protected JellyException createJellyException(String p0, Exception p1){ return null; } + protected Map attributes = null; + protected Object convertType(Object p0, Class p1){ return null; } + protected Tag createTag(){ return null; } + protected void applyLocation(LocationAware p0){} + protected void configureTag(Tag p0, JellyContext p1){} + protected void endNamespacePrefixes(XMLOutput p0){} + protected void handleException(Error p0){} + protected void handleException(Exception p0){} + protected void handleException(JellyException p0){} + protected void handleException(JellyTagException p0){} + protected void setContextURLs(JellyContext p0){} + protected void setTag(Tag p0, JellyContext p1){} + protected void startNamespacePrefixes(XMLOutput p0){} + public Attributes getSaxAttributes(){ return null; } + public Map getNamespaceContext(){ return null; } + public Script compile(){ return null; } + public Script getTagBody(){ return null; } + public String getElementName(){ return null; } + public String getFileName(){ return null; } + public String getLocalName(){ return null; } + public String toString(){ return null; } + public Tag getTag(JellyContext p0){ return null; } + public TagFactory getTagFactory(){ return null; } + public TagScript getParent(){ return null; } + public TagScript(){} + public TagScript(TagFactory p0){} + public int getColumnNumber(){ return 0; } + public int getLineNumber(){ return 0; } + public static TagScript newInstance(Class p0){ return null; } + public void addAttribute(String p0, Expression p1){} + public void run(JellyContext p0, XMLOutput p1){} + public void setColumnNumber(int p0){} + public void setElementName(String p0){} + public void setFileName(String p0){} + public void setLineNumber(int p0){} + public void setLocalName(String p0){} + public void setLocator(Locator p0){} + public void setParent(TagScript p0){} + public void setSaxAttributes(Attributes p0){} + public void setTagBody(Script p0){} + public void setTagFactory(TagFactory p0){} + public void setTagNamespacesMap(Map p0){} +} diff --git a/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/parser/XMLParser.java b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/parser/XMLParser.java new file mode 100644 index 00000000000..18f7bbbb5ef --- /dev/null +++ b/java/ql/test/stubs/apache-commons-jelly-1.0.1/org/apache/commons/jelly/parser/XMLParser.java @@ -0,0 +1,99 @@ +// Generated automatically from org.apache.commons.jelly.parser.XMLParser for testing purposes + +package org.apache.commons.jelly.parser; + +import java.io.File; +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; +import java.util.Map; +import java.util.Properties; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import org.apache.commons.jelly.JellyContext; +import org.apache.commons.jelly.Script; +import org.apache.commons.jelly.expression.Expression; +import org.apache.commons.jelly.expression.ExpressionFactory; +import org.apache.commons.jelly.impl.ScriptBlock; +import org.apache.commons.jelly.impl.TagScript; +import org.apache.commons.logging.Log; +import org.xml.sax.Attributes; +import org.xml.sax.ErrorHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.DefaultHandler; + +public class XMLParser extends DefaultHandler +{ + protected ClassLoader classLoader = null; + protected ErrorHandler errorHandler = null; + protected Expression createConstantExpression(String p0, String p1, String p2){ return null; } + protected ExpressionFactory createExpressionFactory(){ return null; } + protected Locator locator = null; + protected Map namespaces = null; + protected Properties getJellyProperties(){ return null; } + protected SAXException createSAXException(Exception p0){ return null; } + protected SAXException createSAXException(String p0){ return null; } + protected SAXException createSAXException(String p0, Exception p1){ return null; } + protected SAXParser parser = null; + protected String getCurrentURI(){ return null; } + protected TagScript createStaticTag(String p0, String p1, String p2, Attributes p3){ return null; } + protected TagScript createTag(String p0, String p1, Attributes p2){ return null; } + protected XMLReader reader = null; + protected boolean useContextClassLoader = false; + protected boolean validating = false; + protected static SAXParserFactory factory = null; + protected void addExpressionScript(ScriptBlock p0, Expression p1){} + protected void addTextScript(String p0){} + protected void configure(){} + protected void configureTagScript(TagScript p0){} + public ClassLoader getClassLoader(){ return null; } + public ErrorHandler getErrorHandler(){ return null; } + public ExpressionFactory getExpressionFactory(){ return null; } + public JellyContext getContext(){ return null; } + public Log getLogger(){ return null; } + public SAXParser getParser(){ return null; } + public Script parse(File p0){ return null; } + public Script parse(InputSource p0){ return null; } + public Script parse(InputStream p0){ return null; } + public Script parse(Reader p0){ return null; } + public Script parse(String p0){ return null; } + public Script parse(URL p0){ return null; } + public ScriptBlock getScript(){ return null; } + public String findNamespaceURI(String p0){ return null; } + public XMLParser(){} + public XMLParser(SAXParser p0){} + public XMLParser(XMLReader p0){} + public XMLParser(boolean p0){} + public XMLReader getReader(){ return null; } + public XMLReader getXMLReader(){ return null; } + public boolean getUseContextClassLoader(){ return false; } + public boolean getValidating(){ return false; } + public void characters(char[] p0, int p1, int p2){} + public void endDocument(){} + public void endElement(String p0, String p1, String p2){} + public void endPrefixMapping(String p0){} + public void error(SAXParseException p0){} + public void fatalError(SAXParseException p0){} + public void ignorableWhitespace(char[] p0, int p1, int p2){} + public void notationDecl(String p0, String p1, String p2){} + public void processingInstruction(String p0, String p1){} + public void setClassLoader(ClassLoader p0){} + public void setContext(JellyContext p0){} + public void setDefaultNamespaceURI(String p0){} + public void setDocumentLocator(Locator p0){} + public void setErrorHandler(ErrorHandler p0){} + public void setExpressionFactory(ExpressionFactory p0){} + public void setLogger(Log p0){} + public void setUseContextClassLoader(boolean p0){} + public void setValidating(boolean p0){} + public void skippedEntity(String p0){} + public void startDocument(){} + public void startElement(String p0, String p1, String p2, Attributes p3){} + public void startPrefixMapping(String p0, String p1){} + public void unparsedEntityDecl(String p0, String p1, String p2, String p3){} + public void warning(SAXParseException p0){} +} diff --git a/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/Nestable.java b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/Nestable.java new file mode 100644 index 00000000000..343212afa54 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/Nestable.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.commons.lang.exception.Nestable for testing purposes + +package org.apache.commons.lang.exception; + +import java.io.PrintStream; +import java.io.PrintWriter; + +public interface Nestable +{ + String getMessage(); + String getMessage(int p0); + String[] getMessages(); + Throwable getCause(); + Throwable getThrowable(int p0); + Throwable[] getThrowables(); + int getThrowableCount(); + int indexOfThrowable(Class p0); + int indexOfThrowable(Class p0, int p1); + void printPartialStackTrace(PrintWriter p0); + void printStackTrace(PrintStream p0); + void printStackTrace(PrintWriter p0); +} diff --git a/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableDelegate.java b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableDelegate.java new file mode 100644 index 00000000000..67a94cd97d2 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableDelegate.java @@ -0,0 +1,30 @@ +// Generated automatically from org.apache.commons.lang.exception.NestableDelegate for testing purposes + +package org.apache.commons.lang.exception; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Serializable; +import java.util.List; +import org.apache.commons.lang.exception.Nestable; + +public class NestableDelegate implements Serializable +{ + protected NestableDelegate() {} + protected String[] getStackFrames(Throwable p0){ return null; } + protected void trimStackFrames(List p0){} + public NestableDelegate(Nestable p0){} + public String getMessage(String p0){ return null; } + public String getMessage(int p0){ return null; } + public String[] getMessages(){ return null; } + public Throwable getThrowable(int p0){ return null; } + public Throwable[] getThrowables(){ return null; } + public int getThrowableCount(){ return 0; } + public int indexOfThrowable(Class p0, int p1){ return 0; } + public static boolean matchSubclasses = false; + public static boolean topDown = false; + public static boolean trimStackFrames = false; + public void printStackTrace(){} + public void printStackTrace(PrintStream p0){} + public void printStackTrace(PrintWriter p0){} +} diff --git a/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java new file mode 100644 index 00000000000..353fabe4707 --- /dev/null +++ b/java/ql/test/stubs/apache-commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java @@ -0,0 +1,30 @@ +// Generated automatically from org.apache.commons.lang.exception.NestableRuntimeException for testing purposes + +package org.apache.commons.lang.exception; + +import java.io.PrintStream; +import java.io.PrintWriter; +import org.apache.commons.lang.exception.Nestable; +import org.apache.commons.lang.exception.NestableDelegate; + +public class NestableRuntimeException extends RuntimeException implements Nestable +{ + protected NestableDelegate delegate = null; + public NestableRuntimeException(){} + public NestableRuntimeException(String p0){} + public NestableRuntimeException(String p0, Throwable p1){} + public NestableRuntimeException(Throwable p0){} + public String getMessage(){ return null; } + public String getMessage(int p0){ return null; } + public String[] getMessages(){ return null; } + public Throwable getCause(){ return null; } + public Throwable getThrowable(int p0){ return null; } + public Throwable[] getThrowables(){ return null; } + public final void printPartialStackTrace(PrintWriter p0){} + public int getThrowableCount(){ return 0; } + public int indexOfThrowable(Class p0){ return 0; } + public int indexOfThrowable(Class p0, int p1){ return 0; } + public void printStackTrace(){} + public void printStackTrace(PrintStream p0){} + public void printStackTrace(PrintWriter p0){} +} 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 6e4886fc85c..7674e4c8b3e 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,53 +1,11 @@ -/* - * ==================================================================== - * 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 - * . - * - */ +// Generated automatically from org.apache.http.Header for testing purposes 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. - * - *

    - *     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>
    - *
    - * - * @since 4.0 - */ -public interface Header extends NameValuePair { - HeaderElement[] getElements() throws ParseException; +import org.apache.http.HeaderElement; +import org.apache.http.NameValuePair; +public interface Header extends NameValuePair +{ + HeaderElement[] getElements(); } diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HeaderElement.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HeaderElement.java index 9fef05a049a..6c362a9e216 100644 --- a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HeaderElement.java +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HeaderElement.java @@ -1,65 +1,15 @@ -/* - * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/HeaderElement.java $ - * $Revision: 569828 $ - * $Date: 2007-08-26 08:49:38 -0700 (Sun, 26 Aug 2007) $ - * - * ==================================================================== - * 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 - * . - * - */ +// Generated automatically from org.apache.http.HeaderElement for testing purposes package org.apache.http; -/** - * One element of an HTTP {@link Header header} value. - * - * @author Oleg Kalnichevski - * - * - * - * @version $Revision: 569828 $ $Date: 2007-08-26 08:49:38 -0700 (Sun, 26 Aug - * 2007) $ - * - * @since 4.0 - * - * @deprecated Please use {@link java.net.URL#openConnection} instead. Please - * visit this - * webpage for further details. - */ -@Deprecated -public interface HeaderElement { - - String getName(); - - String getValue(); +import org.apache.http.NameValuePair; +public interface HeaderElement +{ + NameValuePair getParameter(int p0); + NameValuePair getParameterByName(String p0); NameValuePair[] getParameters(); - - NameValuePair getParameterByName(String name); - + String getName(); + String getValue(); int getParameterCount(); - - NameValuePair getParameter(int index); } diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpEntity.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpEntity.java index 2de524318b2..2c5f89dafcf 100644 --- a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpEntity.java +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/HttpEntity.java @@ -1,33 +1,4 @@ -/* - * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/HttpEntity.java $ - * $Revision: 645824 $ - * $Date: 2008-04-08 03:12:41 -0700 (Tue, 08 Apr 2008) $ - * - * ==================================================================== - * 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 - * . - * - */ +// Generated automatically from org.apache.http.HttpEntity for testing purposes package org.apache.http; @@ -35,152 +6,15 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -/** - * An entity that can be sent or received with an HTTP message. Entities can be - * found in some {@link HttpEntityEnclosingRequest requests} and in - * {@link HttpResponse responses}, where they are optional. - *

    - * In some places, the JavaDoc distinguishes three kinds of entities, depending - * on where their {@link #getContent content} originates: - *

      - *
    • streamed: The content is received from a stream, or generated on - * the fly. In particular, this category includes entities being received from a - * {@link HttpConnection connection}. {@link #isStreaming Streamed} entities are - * generally not {@link #isRepeatable repeatable}.
    • - *
    • self-contained: The content is in memory or obtained by means that - * are independent from a connection or other entity. Self-contained entities - * are generally {@link #isRepeatable repeatable}.
    • - *
    • wrapping: The content is obtained from another entity.
    • - *
    - * This distinction is important for connection management with incoming - * entities. For entities that are created by an application and only sent using - * the HTTP components framework, the difference between streamed and - * self-contained is of little importance. In that case, it is suggested to - * consider non-repeatable entities as streamed, and those that are repeatable - * (without a huge effort) as self-contained. - * - * @author Oleg Kalnichevski - * - * @version $Revision: 645824 $ - * - * @since 4.0 - * - * @deprecated Please use {@link java.net.URL#openConnection} instead. Please - * visit this - * webpage for further details. - */ -@Deprecated -public interface HttpEntity { - - /** - * Tells if the entity is capable to produce its data more than once. A - * repeatable entity's getContent() and writeTo(OutputStream) methods can be - * called more than once whereas a non-repeatable entity's can not. - * - * @return true if the entity is repeatable, false otherwise. - */ - boolean isRepeatable(); - - /** - * Tells about chunked encoding for this entity. The primary purpose of this - * method is to indicate whether chunked encoding should be used when the entity - * is sent. For entities that are received, it can also indicate whether the - * entity was received with chunked encoding.
    - * The behavior of wrapping entities is implementation dependent, but should - * respect the primary purpose. - * - * @return true if chunked encoding is preferred for this entity, - * or false if it is not - */ - boolean isChunked(); - - /** - * Tells the length of the content, if known. - * - * @return the number of bytes of the content, or a negative number if unknown. - * If the content length is known but exceeds - * {@link java.lang.Long#MAX_VALUE Long.MAX_VALUE}, a negative number is - * returned. - */ - long getContentLength(); - - /** - * Obtains the Content-Type header, if known. This is the header that should be - * used when sending the entity, or the one that was received with the entity. - * It can include a charset attribute. - * - * @return the Content-Type header for this entity, or null if the - * content type is unknown - */ - Header getContentType(); - - /** - * Obtains the Content-Encoding header, if known. This is the header that should - * be used when sending the entity, or the one that was received with the - * entity. Wrapping entities that modify the content encoding should adjust this - * header accordingly. - * - * @return the Content-Encoding header for this entity, or null if - * the content encoding is unknown - */ +public interface HttpEntity +{ Header getContentEncoding(); - - /** - * Creates a new InputStream object of the entity. It is a programming error to - * return the same InputStream object more than once. Entities that are not - * {@link #isRepeatable repeatable} will throw an exception if this method is - * called multiple times. - * - * @return a new input stream that returns the entity data. - * - * @throws IOException if the stream could not be created - * @throws IllegalStateException if this entity is not repeatable and the stream - * has already been obtained previously - */ + Header getContentType(); InputStream getContent() throws IOException, IllegalStateException; - - /** - * Writes the entity content to the output stream. - * - * @param outstream the output stream to write entity content to - * - * @throws IOException if an I/O error occurs - */ - void writeTo(OutputStream outstream) throws IOException; - - /** - * Tells whether this entity depends on an underlying stream. Streamed entities - * should return true until the content has been consumed, - * false afterwards. Self-contained entities should return - * false. Wrapping entities should delegate this call to the - * wrapped entity.
    - * The content of a streamed entity is consumed when the stream returned by - * {@link #getContent getContent} has been read to EOF, or after - * {@link #consumeContent consumeContent} has been called. If a streamed entity - * can not detect whether the stream has been read to EOF, it should return - * true until {@link #consumeContent consumeContent} is called. - * - * @return true if the entity content is streamed and not yet - * consumed, false otherwise - */ - boolean isStreaming(); // don't expect an exception here - - /** - * TODO: The name of this method is misnomer. It will be renamed to #finish() in - * the next major release.
    - * This method is called to indicate that the content of this entity is no - * longer required. All entity implementations are expected to release all - * allocated resources as a result of this method invocation. Content streaming - * entities are also expected to dispose of the remaining content, if any. - * Wrapping entities should delegate this call to the wrapped entity.
    - * This method is of particular importance for entities being received from a - * {@link HttpConnection connection}. The entity needs to be consumed completely - * in order to re-use the connection with keep-alive. - * - * @throws IOException if an I/O error occurs. This indicates that connection - * keep-alive is not possible. - */ + boolean isChunked(); + boolean isRepeatable(); + boolean isStreaming(); + long getContentLength(); void consumeContent() throws IOException; - -} // interface HttpEntity + void writeTo(OutputStream outstream) throws IOException; +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/NameValuePair.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/NameValuePair.java index 4ed98cac597..2219b56c811 100644 --- a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/NameValuePair.java +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/NameValuePair.java @@ -1,124 +1,10 @@ -/* - * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/NameValuePair.java $ - * $Revision: 496070 $ - * $Date: 2007-01-14 04:18:34 -0800 (Sun, 14 Jan 2007) $ - * - * ==================================================================== - * 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 - * . - * - */ +// Generated automatically from org.apache.http.NameValuePair for testing purposes package org.apache.http; -/** - * A simple class encapsulating an attribute/value pair. - *

    - * This class comforms to the generic grammar and formatting rules outlined in - * the Section - * 2.2 and Section - * 3.6 of RFC - * 2616 - *

    - * 2.2 Basic Rules - *

    - * The following rules are used throughout this specification to describe basic - * parsing constructs. The US-ASCII coded character set is defined by ANSI - * X3.4-1986. - *

    - * - *
    - *     OCTET          = 
    - *     CHAR           = 
    - *     UPALPHA        = 
    - *     LOALPHA        = 
    - *     ALPHA          = UPALPHA | LOALPHA
    - *     DIGIT          = 
    - *     CTL            = 
    - *     CR             = 
    - *     LF             = 
    - *     SP             = 
    - *     HT             = 
    - *     <">            = 
    - * 
    - *

    - * Many HTTP/1.1 header field values consist of words separated by LWS or - * special characters. These special characters MUST be in a quoted string to be - * used within a parameter value (as defined in section 3.6). - *

    - * - *

    - * token          = 1*
    - * separators     = "(" | ")" | "<" | ">" | "@"
    - *                | "," | ";" | ":" | "\" | <">
    - *                | "/" | "[" | "]" | "?" | "="
    - *                | "{" | "}" | SP | HT
    - * 
    - *

    - * A string of text is parsed as a single word if it is quoted using - * double-quote marks. - *

    - * - *
    - * quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
    - * qdtext         = >
    - * 
    - *

    - * The backslash character ("\") MAY be used as a single-character quoting - * mechanism only within quoted-string and comment constructs. - *

    - * - *
    - * quoted-pair    = "\" CHAR
    - * 
    - * - * 3.6 Transfer Codings - *

    - * Parameters are in the form of attribute/value pairs. - *

    - * - *
    - * parameter               = attribute "=" value
    - * attribute               = token
    - * value                   = token | quoted-string
    - * 
    - * - * @author Oleg Kalnichevski - * - * - * @deprecated Please use {@link java.net.URL#openConnection} instead. Please - * visit this - * webpage for further details. - */ -@Deprecated -public interface NameValuePair { +public interface NameValuePair +{ String getName(); - String getValue(); - } diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URIBuilder.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URIBuilder.java new file mode 100644 index 00000000000..e81eead0e88 --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URIBuilder.java @@ -0,0 +1,51 @@ +// Generated automatically from org.apache.http.client.utils.URIBuilder for testing purposes + +package org.apache.http.client.utils; + +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import org.apache.http.NameValuePair; + +public class URIBuilder +{ + public Charset getCharset(){ return null; } + public List getQueryParams(){ return null; } + public List getPathSegments(){ return null; } + public String getFragment(){ return null; } + public String getHost(){ return null; } + public String getPath(){ return null; } + public String getScheme(){ return null; } + public String getUserInfo(){ return null; } + public String toString(){ return null; } + public URI build(){ return null; } + public URIBuilder addParameter(String p0, String p1){ return null; } + public URIBuilder addParameters(List p0){ return null; } + public URIBuilder clearParameters(){ return null; } + public URIBuilder removeQuery(){ return null; } + public URIBuilder setCharset(Charset p0){ return null; } + public URIBuilder setCustomQuery(String p0){ return null; } + public URIBuilder setFragment(String p0){ return null; } + public URIBuilder setHost(String p0){ return null; } + public URIBuilder setParameter(String p0, String p1){ return null; } + public URIBuilder setParameters(List p0){ return null; } + public URIBuilder setParameters(NameValuePair... p0){ return null; } + public URIBuilder setPath(String p0){ return null; } + public URIBuilder setPathSegments(List p0){ return null; } + public URIBuilder setPathSegments(String... p0){ return null; } + public URIBuilder setPort(int p0){ return null; } + public URIBuilder setQuery(String p0){ return null; } + public URIBuilder setScheme(String p0){ return null; } + public URIBuilder setUserInfo(String p0){ return null; } + public URIBuilder setUserInfo(String p0, String p1){ return null; } + public URIBuilder(){} + public URIBuilder(String p0){} + public URIBuilder(String p0, Charset p1){} + public URIBuilder(URI p0){} + public URIBuilder(URI p0, Charset p1){} + public boolean isAbsolute(){ return false; } + public boolean isOpaque(){ return false; } + public boolean isPathEmpty(){ return false; } + public boolean isQueryEmpty(){ return false; } + public int getPort(){ return 0; } +} diff --git a/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URLEncodedUtils.java b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URLEncodedUtils.java new file mode 100644 index 00000000000..3dd3278311e --- /dev/null +++ b/java/ql/test/stubs/apache-http-4.4.13/org/apache/http/client/utils/URLEncodedUtils.java @@ -0,0 +1,34 @@ +// Generated automatically from org.apache.http.client.utils.URLEncodedUtils for testing purposes + +package org.apache.http.client.utils; + +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Scanner; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.util.CharArrayBuffer; + +public class URLEncodedUtils +{ + public URLEncodedUtils(){} + public static List parse(CharArrayBuffer p0, Charset p1, char... p2){ return null; } + public static List parse(HttpEntity p0){ return null; } + public static List parse(String p0, Charset p1){ return null; } + public static List parse(String p0, Charset p1, char... p2){ return null; } + public static List parse(URI p0, Charset p1){ return null; } + public static List parse(URI p0, String p1){ return null; } + public static List parsePathSegments(CharSequence p0){ return null; } + public static List parsePathSegments(CharSequence p0, Charset p1){ return null; } + public static String CONTENT_TYPE = null; + public static String format(Iterable p0, Charset p1){ return null; } + public static String format(Iterable p0, char p1, Charset p2){ return null; } + public static String format(List p0, String p1){ return null; } + public static String format(List p0, char p1, String p2){ return null; } + public static String formatSegments(Iterable p0, Charset p1){ return null; } + public static String formatSegments(String... p0){ return null; } + public static boolean isEncoded(HttpEntity p0){ return false; } + public static void parse(List p0, Scanner p1, String p2){} + public static void parse(List p0, Scanner p1, String p2, String p3){} +} 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 index 9bc34144de1..7fc54ea0a67 100644 --- 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 @@ -1,93 +1,28 @@ -/* - * ==================================================================== - * 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 - * . - * - */ +// Generated automatically from org.apache.http.util.ByteArrayBuffer for testing purposes package org.apache.http.util; import java.io.Serializable; +import org.apache.http.util.CharArrayBuffer; -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; - } - +public class ByteArrayBuffer implements Serializable +{ + protected ByteArrayBuffer() {} + public ByteArrayBuffer(int p0){} + public boolean isEmpty(){ return false; } + public boolean isFull(){ return false; } + public byte[] buffer(){ return null; } + public byte[] toByteArray(){ return null; } + public int byteAt(int p0){ return 0; } + public int capacity(){ return 0; } + public int indexOf(byte p0){ return 0; } + public int indexOf(byte p0, int p1, int p2){ return 0; } + public int length(){ return 0; } + public void append(CharArrayBuffer p0, int p1, int p2){} + public void append(byte[] p0, int p1, int p2){} + public void append(char[] p0, int p1, int p2){} + public void append(int p0){} + public void clear(){} + public void ensureCapacity(int p0){} + public void setLength(int p0){} } 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 index 465962e362e..07c43f35ca1 100644 --- 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 @@ -1,127 +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 - * . - * - */ +// Generated automatically from org.apache.http.util.CharArrayBuffer for testing purposes 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; - } +import org.apache.http.util.ByteArrayBuffer; +public class CharArrayBuffer implements CharSequence, Serializable +{ + protected CharArrayBuffer() {} + public CharArrayBuffer(int p0){} + public CharSequence subSequence(int p0, int p1){ return null; } + public String substring(int p0, int p1){ return null; } + public String substringTrimmed(int p0, int p1){ return null; } + public String toString(){ return null; } + public boolean isEmpty(){ return false; } + public boolean isFull(){ return false; } + public char charAt(int p0){ return '0'; } + public char[] buffer(){ return null; } + public char[] toCharArray(){ return null; } + public int capacity(){ return 0; } + public int indexOf(int p0){ return 0; } + public int indexOf(int p0, int p1, int p2){ return 0; } + public int length(){ return 0; } + public void append(ByteArrayBuffer p0, int p1, int p2){} + public void append(CharArrayBuffer p0){} + public void append(CharArrayBuffer p0, int p1, int p2){} + public void append(Object p0){} + public void append(String p0){} + public void append(byte[] p0, int p1, int p2){} + public void append(char p0){} + public void append(char[] p0, int p1, int p2){} + public void clear(){} + public void ensureCapacity(int p0){} + public void setLength(int p0){} } diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Installer.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Installer.java new file mode 100644 index 00000000000..02abcd95563 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Installer.java @@ -0,0 +1,11 @@ +// Generated automatically from org.codehaus.cargo.container.installer.Installer for testing purposes + +package org.codehaus.cargo.container.installer; + +import org.codehaus.cargo.util.log.Loggable; + +public interface Installer extends Loggable +{ + String getHome(); + void install(); +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Proxy.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Proxy.java new file mode 100644 index 00000000000..de5da1c1766 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/Proxy.java @@ -0,0 +1,23 @@ +// Generated automatically from org.codehaus.cargo.container.installer.Proxy for testing purposes + +package org.codehaus.cargo.container.installer; + +import java.util.Map; +import org.codehaus.cargo.util.log.LoggedObject; + +public class Proxy extends LoggedObject +{ + public Map configure(){ return null; } + public Proxy(){} + public String getExcludeHosts(){ return null; } + public String getHost(){ return null; } + public String getPassword(){ return null; } + public String getUser(){ return null; } + public int getPort(){ return 0; } + public void clear(Map p0){} + public void setExcludeHosts(String p0){} + public void setHost(String p0){} + public void setPassword(String p0){} + public void setPort(int p0){} + public void setUser(String p0){} +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/ZipURLInstaller.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/ZipURLInstaller.java new file mode 100644 index 00000000000..638a19d89fc --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/container/installer/ZipURLInstaller.java @@ -0,0 +1,34 @@ +// Generated automatically from org.codehaus.cargo.container.installer.ZipURLInstaller for testing purposes + +package org.codehaus.cargo.container.installer; + +import java.net.URL; +import org.codehaus.cargo.container.installer.Installer; +import org.codehaus.cargo.container.installer.Proxy; +import org.codehaus.cargo.util.FileHandler; +import org.codehaus.cargo.util.log.LoggedObject; +import org.codehaus.cargo.util.log.Logger; + +public class ZipURLInstaller extends LoggedObject implements Installer +{ + protected ZipURLInstaller() {} + protected String getSourceFileName(){ return null; } + protected void doDownload(){} + public FileHandler getFileHandler(){ return null; } + public String getDownloadDir(){ return null; } + public String getDownloadFile(){ return null; } + public String getExtractDir(){ return null; } + public String getHome(){ return null; } + public ZipURLInstaller(URL p0){} + public ZipURLInstaller(URL p0, String p1, String p2){} + public boolean isAlreadyDownloaded(){ return false; } + public boolean isAlreadyExtracted(){ return false; } + public void download(){} + public void install(){} + public void registerInstallation(){} + public void setDownloadDir(String p0){} + public void setExtractDir(String p0){} + public void setFileHandler(FileHandler p0){} + public void setLogger(Logger p0){} + public void setProxy(Proxy p0){} +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/FileHandler.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/FileHandler.java new file mode 100644 index 00000000000..07579277d95 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/FileHandler.java @@ -0,0 +1,49 @@ +// Generated automatically from org.codehaus.cargo.util.FileHandler for testing purposes + +package org.codehaus.cargo.util; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import org.codehaus.cargo.util.XmlReplacement; +import org.codehaus.cargo.util.log.Loggable; + +public interface FileHandler extends Loggable +{ + InputStream getInputStream(String p0); + OutputStream getOutputStream(String p0); + String append(String p0, String p1); + String createDirectory(String p0, String p1); + String createUniqueTmpDirectory(); + String getAbsolutePath(String p0); + String getName(String p0); + String getParent(String p0); + String getTmpPath(String p0); + String getURL(String p0); + String readTextFile(String p0, Charset p1); + String[] getChildren(String p0); + String[] getChildren(String p0, List p1); + boolean exists(String p0); + boolean isDirectory(String p0); + boolean isDirectoryEmpty(String p0); + long getSize(String p0); + static String NEW_LINE = null; + void copy(InputStream p0, OutputStream p1); + void copy(InputStream p0, OutputStream p1, int p2); + void copyDirectory(String p0, String p1); + void copyDirectory(String p0, String p1, List p2); + void copyDirectory(String p0, String p1, Map p2, Charset p3); + void copyFile(String p0, String p1); + void copyFile(String p0, String p1, Map p2, Charset p3); + void copyFile(String p0, String p1, boolean p2); + void createFile(String p0); + void delete(String p0); + void explode(String p0, String p1); + void mkdirs(String p0); + void replaceInFile(String p0, Map p1, Charset p2); + void replaceInFile(String p0, Map p1, Charset p2, boolean p3); + void replaceInXmlFile(XmlReplacement... p0); + void writeTextFile(String p0, String p1, Charset p2); +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/XmlReplacement.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/XmlReplacement.java new file mode 100644 index 00000000000..16caa14f2b8 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/XmlReplacement.java @@ -0,0 +1,28 @@ +// Generated automatically from org.codehaus.cargo.util.XmlReplacement for testing purposes + +package org.codehaus.cargo.util; + + +public class XmlReplacement +{ + public String getAttributeName(){ return null; } + public String getFile(){ return null; } + public String getValue(){ return null; } + public String getXpathExpression(){ return null; } + public String toString(){ return null; } + public XmlReplacement(){} + public XmlReplacement(String p0, String p1, String p2, XmlReplacement.ReplacementBehavior p3, String p4){} + public XmlReplacement.ReplacementBehavior getReplacementBehavior(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public void setAttributeName(String p0){} + public void setFile(String p0){} + public void setReplacementBehavior(XmlReplacement.ReplacementBehavior p0){} + public void setValue(String p0){} + public void setXpathExpression(String p0){} + static public enum ReplacementBehavior + { + ADD_MISSING_NODES, IGNORE_IF_NON_EXISTING, THROW_EXCEPTION; + private ReplacementBehavior() {} + } +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LogLevel.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LogLevel.java new file mode 100644 index 00000000000..b7b0d5a37d8 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LogLevel.java @@ -0,0 +1,18 @@ +// Generated automatically from org.codehaus.cargo.util.log.LogLevel for testing purposes + +package org.codehaus.cargo.util.log; + + +public class LogLevel implements Comparable +{ + protected LogLevel() {} + public String getLevel(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(LogLevel p0){ return 0; } + public int hashCode(){ return 0; } + public static LogLevel DEBUG = null; + public static LogLevel INFO = null; + public static LogLevel WARN = null; + public static LogLevel toLevel(String p0){ return null; } +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Loggable.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Loggable.java new file mode 100644 index 00000000000..3369fa27ef5 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Loggable.java @@ -0,0 +1,11 @@ +// Generated automatically from org.codehaus.cargo.util.log.Loggable for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.Logger; + +public interface Loggable +{ + Logger getLogger(); + void setLogger(Logger p0); +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LoggedObject.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LoggedObject.java new file mode 100644 index 00000000000..421da028778 --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/LoggedObject.java @@ -0,0 +1,13 @@ +// Generated automatically from org.codehaus.cargo.util.log.LoggedObject for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.Loggable; +import org.codehaus.cargo.util.log.Logger; + +public class LoggedObject implements Loggable +{ + public LoggedObject(){} + public Logger getLogger(){ return null; } + public void setLogger(Logger p0){} +} diff --git a/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Logger.java b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Logger.java new file mode 100644 index 00000000000..965e4bc1ccd --- /dev/null +++ b/java/ql/test/stubs/cargo/org/codehaus/cargo/util/log/Logger.java @@ -0,0 +1,14 @@ +// Generated automatically from org.codehaus.cargo.util.log.Logger for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.LogLevel; + +public interface Logger +{ + LogLevel getLevel(); + void debug(String p0, String p1); + void info(String p0, String p1); + void setLevel(LogLevel p0); + void warn(String p0, String p1); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Attribute.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Attribute.java new file mode 100644 index 00000000000..cf198ce1121 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Attribute.java @@ -0,0 +1,21 @@ +// Generated automatically from org.dom4j.Attribute for testing purposes + +package org.dom4j; + +import org.dom4j.Namespace; +import org.dom4j.Node; +import org.dom4j.QName; + +public interface Attribute extends Node +{ + Namespace getNamespace(); + Object getData(); + QName getQName(); + String getNamespacePrefix(); + String getNamespaceURI(); + String getQualifiedName(); + String getValue(); + void setData(Object p0); + void setNamespace(Namespace p0); + void setValue(String p0); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Branch.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Branch.java index 5218b8f098f..7ab008a5860 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Branch.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Branch.java @@ -1,54 +1,41 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* - * Adapted from DOM4J version 2.1.1 as available at - * https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar - * Only relevant stubs of this file have been retained for test purposes. - */ +// Generated automatically from org.dom4j.Branch for testing purposes package org.dom4j; -public interface Branch extends Node { -} +import java.util.Iterator; +import java.util.List; +import org.dom4j.Comment; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.ProcessingInstruction; +import org.dom4j.QName; -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file +public interface Branch extends Node +{ + Element addElement(QName p0); + Element addElement(String p0); + Element addElement(String p0, String p1); + Element elementByID(String p0); + Iterator nodeIterator(); + List content(); + List processingInstructions(); + List processingInstructions(String p0); + Node node(int p0); + ProcessingInstruction processingInstruction(String p0); + boolean remove(Comment p0); + boolean remove(Element p0); + boolean remove(Node p0); + boolean remove(ProcessingInstruction p0); + boolean removeProcessingInstruction(String p0); + int indexOf(Node p0); + int nodeCount(); + void add(Comment p0); + void add(Element p0); + void add(Node p0); + void add(ProcessingInstruction p0); + void appendContent(Branch p0); + void clearContent(); + void normalize(); + void setContent(List p0); + void setProcessingInstructions(List p0); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CDATA.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CDATA.java new file mode 100644 index 00000000000..da5b95ff7f6 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CDATA.java @@ -0,0 +1,9 @@ +// Generated automatically from org.dom4j.CDATA for testing purposes + +package org.dom4j; + +import org.dom4j.CharacterData; + +public interface CDATA extends CharacterData +{ +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CharacterData.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CharacterData.java new file mode 100644 index 00000000000..43a06f456f5 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/CharacterData.java @@ -0,0 +1,10 @@ +// Generated automatically from org.dom4j.CharacterData for testing purposes + +package org.dom4j; + +import org.dom4j.Node; + +public interface CharacterData extends Node +{ + void appendText(String p0); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Comment.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Comment.java new file mode 100644 index 00000000000..c6382d5f7cf --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Comment.java @@ -0,0 +1,9 @@ +// Generated automatically from org.dom4j.Comment for testing purposes + +package org.dom4j; + +import org.dom4j.CharacterData; + +public interface Comment extends CharacterData +{ +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Document.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Document.java index 234048883a0..8341f53ff4b 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Document.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Document.java @@ -1,55 +1,24 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* - * Adapted from DOM4J version 2.1.1 as available at - * https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar - * Only relevant stubs of this file have been retained for test purposes. - */ +// Generated automatically from org.dom4j.Document for testing purposes package org.dom4j; -public interface Document extends Branch { +import java.util.Map; +import org.dom4j.Branch; +import org.dom4j.DocumentType; +import org.dom4j.Element; +import org.xml.sax.EntityResolver; +public interface Document extends Branch +{ + Document addComment(String p0); + Document addDocType(String p0, String p1, String p2); + Document addProcessingInstruction(String p0, Map p1); + Document addProcessingInstruction(String p0, String p1); + DocumentType getDocType(); + Element getRootElement(); + EntityResolver getEntityResolver(); + String getXMLEncoding(); + void setDocType(DocumentType p0); + void setEntityResolver(EntityResolver p0); + void setRootElement(Element p0); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentFactory.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentFactory.java index b7a50a5cfef..d433362a7f4 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentFactory.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentFactory.java @@ -1,118 +1,62 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.DocumentFactory for testing purposes package org.dom4j; import java.io.Serializable; +import java.util.List; import java.util.Map; - +import org.dom4j.Attribute; +import org.dom4j.CDATA; +import org.dom4j.Comment; +import org.dom4j.Document; +import org.dom4j.DocumentType; +import org.dom4j.Element; +import org.dom4j.Entity; +import org.dom4j.Namespace; +import org.dom4j.NodeFilter; +import org.dom4j.ProcessingInstruction; +import org.dom4j.QName; +import org.dom4j.Text; +import org.dom4j.XPath; import org.dom4j.rule.Pattern; +import org.dom4j.tree.QNameCache; import org.jaxen.VariableContext; -public class DocumentFactory implements Serializable { - public DocumentFactory() { - } - - public static synchronized DocumentFactory getInstance() { - return null; - } - - public Document createDocument() { - return null; - } - - public Document createDocument(String encoding) { - return null; - } - - public Document createDocument(Element rootElement) { - return null; - } - - public Element createElement(String name) { - return null; - } - - public Element createElement(String qualifiedName, String namespaceURI) { - return null; - } - - public Namespace createNamespace(String prefix, String uri) { - return null; - } - - public XPath createXPath(String xpathExpression) throws InvalidXPathException { - return null; - } - - public XPath createXPath(String xpathExpression, VariableContext variableContext) { - return null; - } - - public NodeFilter createXPathFilter(String xpathFilterExpression, VariableContext variableContext) { - return null; - } - - public NodeFilter createXPathFilter(String xpathFilterExpression) { - return null; - } - - public Pattern createPattern(String xpathPattern) { - return null; - } - - public Map getXPathNamespaceURIs() { - return null; - } - - public void setXPathNamespaceURIs(Map namespaceURIs) { - } - +public class DocumentFactory implements Serializable +{ + protected QName intern(QName p0){ return null; } + protected QNameCache cache = null; + protected QNameCache createQNameCache(){ return null; } + protected static DocumentFactory createSingleton(String p0){ return null; } + protected void init(){} + public Attribute createAttribute(Element p0, QName p1, String p2){ return null; } + public Attribute createAttribute(Element p0, String p1, String p2){ return null; } + public CDATA createCDATA(String p0){ return null; } + public Comment createComment(String p0){ return null; } + public Document createDocument(){ return null; } + public Document createDocument(Element p0){ return null; } + public Document createDocument(String p0){ return null; } + public DocumentFactory(){} + public DocumentType createDocType(String p0, String p1, String p2){ return null; } + public Element createElement(QName p0){ return null; } + public Element createElement(String p0){ return null; } + public Element createElement(String p0, String p1){ return null; } + public Entity createEntity(String p0, String p1){ return null; } + public List getQNames(){ return null; } + public Map getXPathNamespaceURIs(){ return null; } + public Namespace createNamespace(String p0, String p1){ return null; } + public NodeFilter createXPathFilter(String p0){ return null; } + public NodeFilter createXPathFilter(String p0, VariableContext p1){ return null; } + public Pattern createPattern(String p0){ return null; } + public ProcessingInstruction createProcessingInstruction(String p0, Map p1){ return null; } + public ProcessingInstruction createProcessingInstruction(String p0, String p1){ return null; } + public QName createQName(String p0){ return null; } + public QName createQName(String p0, Namespace p1){ return null; } + public QName createQName(String p0, String p1){ return null; } + public QName createQName(String p0, String p1, String p2){ return null; } + public Text createText(String p0){ return null; } + public XPath createXPath(String p0){ return null; } + public XPath createXPath(String p0, VariableContext p1){ return null; } + public static DocumentFactory getInstance(){ return null; } + public void setXPathNamespaceURIs(Map p0){} } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentType.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentType.java new file mode 100644 index 00000000000..76e5a15a4fd --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/DocumentType.java @@ -0,0 +1,20 @@ +// Generated automatically from org.dom4j.DocumentType for testing purposes + +package org.dom4j; + +import java.util.List; +import org.dom4j.Node; + +public interface DocumentType extends Node +{ + List getExternalDeclarations(); + List getInternalDeclarations(); + String getElementName(); + String getPublicID(); + String getSystemID(); + void setElementName(String p0); + void setExternalDeclarations(List p0); + void setInternalDeclarations(List p0); + void setPublicID(String p0); + void setSystemID(String p0); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Element.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Element.java index a702debc0cd..df9a8a94d90 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Element.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Element.java @@ -1,140 +1,88 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ +// Generated automatically from org.dom4j.Element for testing purposes -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ package org.dom4j; import java.util.Iterator; import java.util.List; import java.util.Map; +import org.dom4j.Attribute; +import org.dom4j.Branch; +import org.dom4j.CDATA; +import org.dom4j.Entity; +import org.dom4j.Namespace; +import org.dom4j.Node; +import org.dom4j.QName; +import org.dom4j.Text; -public interface Element extends Branch { - - Namespace getNamespace(); - - Namespace getNamespaceForPrefix(String prefix); - - Namespace getNamespaceForURI(String uri); - - List getNamespacesForURI(String uri); - - String getNamespacePrefix(); - - String getNamespaceURI(); - - String getQualifiedName(); - - List additionalNamespaces(); - - List declaredNamespaces(); - - Element addAttribute(String name, String value); - - Element addComment(String comment); - - Element addCDATA(String cdata); - - Element addEntity(String name, String text); - - Element addNamespace(String prefix, String uri); - - Element addProcessingInstruction(String target, String text); - - Element addProcessingInstruction(String target, Map data); - - Element addText(String text); - - void add(Namespace namespace); - - String getText(); - - String getTextTrim(); - - String getStringValue(); - - Object getData(); - - void setData(Object data); - - int attributeCount(); - - String attributeValue(String name); - - String attributeValue(String name, String defaultValue); - - void setAttributeValue(String name, String value); - - Element element(String name); - - List elements(); - - List elements(String name); - - Iterator elementIterator(); - - Iterator elementIterator(String name); - - boolean isRootElement(); - - boolean hasMixedContent(); - - boolean isTextOnly(); - - void appendAttributes(Element element); - - Element createCopy(); - - Element createCopy(String name); - - String elementText(String name); - - String elementTextTrim(String name); - - Node getXPathResult(int index); - +public interface Element extends Branch +{ + Attribute attribute(QName p0); + Attribute attribute(String p0); + Attribute attribute(int p0); + Element addAttribute(QName p0, String p1); + Element addAttribute(String p0, String p1); + Element addCDATA(String p0); + Element addComment(String p0); + Element addEntity(String p0, String p1); + Element addNamespace(String p0, String p1); + Element addProcessingInstruction(String p0, Map p1); + Element addProcessingInstruction(String p0, String p1); + Element addText(String p0); + Element createCopy(); + Element createCopy(QName p0); + Element createCopy(String p0); + Element element(QName p0); + Element element(String p0); + Iterator attributeIterator(); + Iterator elementIterator(); + Iterator elementIterator(QName p0); + Iterator elementIterator(String p0); + List additionalNamespaces(); + List attributes(); + List declaredNamespaces(); + List elements(); + List elements(QName p0); + List elements(String p0); + List getNamespacesForURI(String p0); + Namespace getNamespace(); + Namespace getNamespaceForPrefix(String p0); + Namespace getNamespaceForURI(String p0); + Node getXPathResult(int p0); + Object getData(); + QName getQName(); + QName getQName(String p0); + String attributeValue(QName p0); + String attributeValue(QName p0, String p1); + String attributeValue(String p0); + String attributeValue(String p0, String p1); + String elementText(QName p0); + String elementText(String p0); + String elementTextTrim(QName p0); + String elementTextTrim(String p0); + String getNamespacePrefix(); + String getNamespaceURI(); + String getQualifiedName(); + String getStringValue(); + String getText(); + String getTextTrim(); + boolean hasMixedContent(); + boolean isRootElement(); + boolean isTextOnly(); + boolean remove(Attribute p0); + boolean remove(CDATA p0); + boolean remove(Entity p0); + boolean remove(Namespace p0); + boolean remove(Text p0); + int attributeCount(); + void add(Attribute p0); + void add(CDATA p0); + void add(Entity p0); + void add(Namespace p0); + void add(Text p0); + void appendAttributes(Element p0); + void setAttributeValue(QName p0, String p1); + void setAttributeValue(String p0, String p1); + void setAttributes(List p0); + void setData(Object p0); + void setQName(QName p0); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Entity.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Entity.java new file mode 100644 index 00000000000..ced1d9c2f59 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Entity.java @@ -0,0 +1,9 @@ +// Generated automatically from org.dom4j.Entity for testing purposes + +package org.dom4j; + +import org.dom4j.Node; + +public interface Entity extends Node +{ +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Namespace.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Namespace.java index e8539bc788b..17ce68e2646 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Namespace.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Namespace.java @@ -1,119 +1,35 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.Namespace for testing purposes package org.dom4j; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.Visitor; import org.dom4j.tree.AbstractNode; +import org.dom4j.tree.NamespaceCache; -public class Namespace extends AbstractNode { - - public Namespace(String prefix, String uri) { - } - - public static Namespace get(String prefix, String uri) { - return null; - } - - public static Namespace get(String uri) { - return null; - } - - public short getNodeType() { - return 0; - } - - public int hashCode() { - return 0; - } - - public boolean equals(Object object) { - return false; - } - - public String getText() { - return null; - } - - public String getStringValue() { - return null; - } - - public String getPrefix() { - return null; - } - - public String getURI() { - return null; - } - - public String getXPathNameStep() { - return null; - } - - public String getPath(Element context) { - return null; - } - - public String getUniquePath(Element context) { - return null; - } - - public String toString() { - return null; - } - - public String asXML() { - return null; - } - - public void accept(Visitor visitor) { - } - +public class Namespace extends AbstractNode +{ + protected Namespace() {} + protected Node createXPathResult(Element p0){ return null; } + protected int createHashCode(){ return 0; } + protected static NamespaceCache cache = null; + public Namespace(String p0, String p1){} + public String asXML(){ return null; } + public String getPath(Element p0){ return null; } + public String getPrefix(){ return null; } + public String getStringValue(){ return null; } + public String getText(){ return null; } + public String getURI(){ return null; } + public String getUniquePath(Element p0){ return null; } + public String getXPathNameStep(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public short getNodeType(){ return 0; } + public static Namespace NO_NAMESPACE = null; + public static Namespace XML_NAMESPACE = null; + public static Namespace get(String p0){ return null; } + public static Namespace get(String p0, String p1){ return null; } + public void accept(Visitor p0){} } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Node.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Node.java index dfc47088026..7ec5e8f9fff 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Node.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Node.java @@ -1,75 +1,60 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.Node for testing purposes package org.dom4j; +import java.io.Writer; import java.util.List; +import org.dom4j.Document; +import org.dom4j.Element; +import org.dom4j.Visitor; +import org.dom4j.XPath; -public interface Node extends Cloneable { - - List selectNodes(String xpathExpression); - - Object selectObject(String xpathExpression); - - List selectNodes(String xpathExpression, String comparisonXPathExpression); - - List selectNodes(String xpathExpression, String comparisonXPathExpression, boolean removeDuplicates); - - Node selectSingleNode(String xpathExpression); - - String valueOf(String xpathExpression); - - Number numberValueOf(String xpathExpression); - - boolean matches(String xpathExpression); - - XPath createXPath(String xpathExpression) throws InvalidXPathException; - +public interface Node extends Cloneable +{ + Document getDocument(); + Element getParent(); + List selectNodes(String p0); + List selectNodes(String p0, String p1); + List selectNodes(String p0, String p1, boolean p2); + Node asXPathResult(Element p0); + Node detach(); + Node selectSingleNode(String p0); + Number numberValueOf(String p0); + Object clone(); + Object selectObject(String p0); + String asXML(); + String getName(); + String getNodeTypeName(); + String getPath(); + String getPath(Element p0); + String getStringValue(); + String getText(); + String getUniquePath(); + String getUniquePath(Element p0); + String valueOf(String p0); + XPath createXPath(String p0); + boolean hasContent(); + boolean isReadOnly(); + boolean matches(String p0); + boolean supportsParent(); + short getNodeType(); + static short ANY_NODE = 0; + static short ATTRIBUTE_NODE = 0; + static short CDATA_SECTION_NODE = 0; + static short COMMENT_NODE = 0; + static short DOCUMENT_NODE = 0; + static short DOCUMENT_TYPE_NODE = 0; + static short ELEMENT_NODE = 0; + static short ENTITY_REFERENCE_NODE = 0; + static short MAX_NODE_TYPE = 0; + static short NAMESPACE_NODE = 0; + static short PROCESSING_INSTRUCTION_NODE = 0; + static short TEXT_NODE = 0; + static short UNKNOWN_NODE = 0; + void accept(Visitor p0); + void setDocument(Document p0); + void setName(String p0); + void setParent(Element p0); + void setText(String p0); + void write(Writer p0); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/NodeFilter.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/NodeFilter.java index 782e9dae66c..d844aaf9c85 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/NodeFilter.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/NodeFilter.java @@ -1,56 +1,10 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.NodeFilter for testing purposes package org.dom4j; -public interface NodeFilter { - boolean matches(Node node); +import org.dom4j.Node; +public interface NodeFilter +{ + boolean matches(Node p0); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/ProcessingInstruction.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/ProcessingInstruction.java new file mode 100644 index 00000000000..ab83b2a76d2 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/ProcessingInstruction.java @@ -0,0 +1,18 @@ +// Generated automatically from org.dom4j.ProcessingInstruction for testing purposes + +package org.dom4j; + +import java.util.Map; +import org.dom4j.Node; + +public interface ProcessingInstruction extends Node +{ + Map getValues(); + String getTarget(); + String getText(); + String getValue(String p0); + boolean removeValue(String p0); + void setTarget(String p0); + void setValue(String p0, String p1); + void setValues(Map p0); +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/QName.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/QName.java new file mode 100644 index 00000000000..9d6d88223af --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/QName.java @@ -0,0 +1,31 @@ +// Generated automatically from org.dom4j.QName for testing purposes + +package org.dom4j; + +import java.io.Serializable; +import org.dom4j.DocumentFactory; +import org.dom4j.Namespace; + +public class QName implements Serializable +{ + protected QName() {} + protected static ThreadLocal cachePerThread = null; + public DocumentFactory getDocumentFactory(){ return null; } + public Namespace getNamespace(){ return null; } + public QName(String p0){} + public QName(String p0, Namespace p1){} + public QName(String p0, Namespace p1, String p2){} + public String getName(){ return null; } + public String getNamespacePrefix(){ return null; } + public String getNamespaceURI(){ return null; } + public String getQualifiedName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static QName get(String p0){ return null; } + public static QName get(String p0, Namespace p1){ return null; } + public static QName get(String p0, Namespace p1, String p2){ return null; } + public static QName get(String p0, String p1){ return null; } + public static QName get(String p0, String p1, String p2){ return null; } + public void setDocumentFactory(DocumentFactory p0){} +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Text.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Text.java new file mode 100644 index 00000000000..fbae297121e --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Text.java @@ -0,0 +1,9 @@ +// Generated automatically from org.dom4j.Text for testing purposes + +package org.dom4j; + +import org.dom4j.CharacterData; + +public interface Text extends CharacterData +{ +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Visitor.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Visitor.java index b8f55de44e4..e7dc7e6b836 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Visitor.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/Visitor.java @@ -1,60 +1,28 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.Visitor for testing purposes package org.dom4j; -public interface Visitor { - void visit(Document document); - - void visit(Element node); - - void visit(Namespace namespace); +import org.dom4j.Attribute; +import org.dom4j.CDATA; +import org.dom4j.Comment; +import org.dom4j.Document; +import org.dom4j.DocumentType; +import org.dom4j.Element; +import org.dom4j.Entity; +import org.dom4j.Namespace; +import org.dom4j.ProcessingInstruction; +import org.dom4j.Text; +public interface Visitor +{ + void visit(Attribute p0); + void visit(CDATA p0); + void visit(Comment p0); + void visit(Document p0); + void visit(DocumentType p0); + void visit(Element p0); + void visit(Entity p0); + void visit(Namespace p0); + void visit(ProcessingInstruction p0); + void visit(Text p0); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/XPath.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/XPath.java index 64147c75a13..90f755f882a 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/XPath.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/XPath.java @@ -1,86 +1,35 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.XPath for testing purposes package org.dom4j; import java.util.List; import java.util.Map; +import org.dom4j.Node; +import org.dom4j.NodeFilter; +import org.jaxen.FunctionContext; +import org.jaxen.NamespaceContext; +import org.jaxen.VariableContext; -public interface XPath extends NodeFilter { - String getText(); - - boolean matches(Node node); - - Object evaluate(Object context); - - Object selectObject(Object context); - - List selectNodes(Object context); - - List selectNodes(Object context, XPath sortXPath); - - List selectNodes(Object context, XPath sortXPath, boolean distinct); - - Node selectSingleNode(Object context); - - String valueOf(Object context); - - Number numberValueOf(Object context); - - boolean booleanValueOf(Object context); - - void sort(List list); - - void sort(List list, boolean distinct); - - void setNamespaceURIs(Map map); - - void setVariableContext(org.jaxen.VariableContext variableContext); +public interface XPath extends NodeFilter +{ + FunctionContext getFunctionContext(); + List selectNodes(Object p0); + List selectNodes(Object p0, XPath p1); + List selectNodes(Object p0, XPath p1, boolean p2); + NamespaceContext getNamespaceContext(); + Node selectSingleNode(Object p0); + Number numberValueOf(Object p0); + Object evaluate(Object p0); + Object selectObject(Object p0); + String getText(); + String valueOf(Object p0); + VariableContext getVariableContext(); + boolean booleanValueOf(Object p0); + boolean matches(Node p0); + void setFunctionContext(FunctionContext p0); + void setNamespaceContext(NamespaceContext p0); + void setNamespaceURIs(Map p0); + void setVariableContext(VariableContext p0); + void sort(List p0); + void sort(List p0, boolean p1); } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/OutputFormat.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/OutputFormat.java new file mode 100644 index 00000000000..b771b40cf00 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/OutputFormat.java @@ -0,0 +1,44 @@ +// Generated automatically from org.dom4j.io.OutputFormat for testing purposes + +package org.dom4j.io; + + +public class OutputFormat implements Cloneable +{ + protected static String STANDARD_INDENT = null; + public OutputFormat(){} + public OutputFormat(String p0){} + public OutputFormat(String p0, boolean p1){} + public OutputFormat(String p0, boolean p1, String p2){} + public String getEncoding(){ return null; } + public String getIndent(){ return null; } + public String getLineSeparator(){ return null; } + public boolean isExpandEmptyElements(){ return false; } + public boolean isNewLineAfterDeclaration(){ return false; } + public boolean isNewlines(){ return false; } + public boolean isOmitEncoding(){ return false; } + public boolean isPadText(){ return false; } + public boolean isSuppressDeclaration(){ return false; } + public boolean isTrimText(){ return false; } + public boolean isXHTML(){ return false; } + public char getAttributeQuoteCharacter(){ return '0'; } + public int getNewLineAfterNTags(){ return 0; } + public int parseOptions(String[] p0, int p1){ return 0; } + public static OutputFormat createCompactFormat(){ return null; } + public static OutputFormat createPrettyPrint(){ return null; } + public void setAttributeQuoteCharacter(char p0){} + public void setEncoding(String p0){} + public void setExpandEmptyElements(boolean p0){} + public void setIndent(String p0){} + public void setIndent(boolean p0){} + public void setIndentSize(int p0){} + public void setLineSeparator(String p0){} + public void setNewLineAfterDeclaration(boolean p0){} + public void setNewLineAfterNTags(int p0){} + public void setNewlines(boolean p0){} + public void setOmitEncoding(boolean p0){} + public void setPadText(boolean p0){} + public void setSuppressDeclaration(boolean p0){} + public void setTrimText(boolean p0){} + public void setXHTML(boolean p0){} +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/XMLWriter.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/XMLWriter.java new file mode 100644 index 00000000000..bdffb5d4561 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/io/XMLWriter.java @@ -0,0 +1,126 @@ +// Generated automatically from org.dom4j.io.XMLWriter for testing purposes + +package org.dom4j.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import org.dom4j.Attribute; +import org.dom4j.CDATA; +import org.dom4j.Comment; +import org.dom4j.Document; +import org.dom4j.DocumentType; +import org.dom4j.Element; +import org.dom4j.Entity; +import org.dom4j.Namespace; +import org.dom4j.Node; +import org.dom4j.ProcessingInstruction; +import org.dom4j.Text; +import org.dom4j.io.OutputFormat; +import org.xml.sax.Attributes; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.helpers.XMLFilterImpl; + +public class XMLWriter extends XMLFilterImpl implements LexicalHandler +{ + protected OutputFormat getOutputFormat(){ return null; } + protected String escapeAttributeEntities(String p0){ return null; } + protected String escapeElementEntities(String p0){ return null; } + protected Writer createWriter(OutputStream p0, String p1){ return null; } + protected Writer writer = null; + protected boolean isExpandEmptyElements(){ return false; } + protected boolean isNamespaceDeclaration(Namespace p0){ return false; } + protected boolean preserve = false; + protected boolean shouldEncodeChar(char p0){ return false; } + protected final boolean isElementSpacePreserved(Element p0){ return false; } + protected int defaultMaximumAllowedCharacter(){ return 0; } + protected int lastOutputNodeType = 0; + protected static OutputFormat DEFAULT_FORMAT = null; + protected static String[] LEXICAL_HANDLER_NAMES = null; + protected void handleException(IOException p0){} + protected void indent(){} + protected void installLexicalHandler(){} + protected void writeAttribute(Attribute p0){} + protected void writeAttribute(Attributes p0, int p1){} + protected void writeAttributes(Attributes p0){} + protected void writeAttributes(Element p0){} + protected void writeCDATA(String p0){} + protected void writeClose(String p0){} + protected void writeComment(String p0){} + protected void writeDeclaration(){} + protected void writeDocType(DocumentType p0){} + protected void writeDocType(String p0, String p1, String p2){} + protected void writeElement(Element p0){} + protected void writeElementContent(Element p0){} + protected void writeEmptyElementClose(String p0){} + protected void writeEntity(Entity p0){} + protected void writeEntityRef(String p0){} + protected void writeEscapeAttributeEntities(String p0){} + protected void writeNamespace(Namespace p0){} + protected void writeNamespace(String p0, String p1){} + protected void writeNamespaces(){} + protected void writeNode(Node p0){} + protected void writeNodeText(Node p0){} + protected void writePrintln(){} + protected void writeProcessingInstruction(ProcessingInstruction p0){} + protected void writeString(String p0){} + public LexicalHandler getLexicalHandler(){ return null; } + public Object getProperty(String p0){ return null; } + public XMLWriter(){} + public XMLWriter(OutputFormat p0){} + public XMLWriter(OutputStream p0){} + public XMLWriter(OutputStream p0, OutputFormat p1){} + public XMLWriter(Writer p0){} + public XMLWriter(Writer p0, OutputFormat p1){} + public boolean isEscapeText(){ return false; } + public boolean resolveEntityRefs(){ return false; } + public int getMaximumAllowedCharacter(){ return 0; } + public void characters(char[] p0, int p1, int p2){} + public void close(){} + public void comment(char[] p0, int p1, int p2){} + public void endCDATA(){} + public void endDTD(){} + public void endDocument(){} + public void endElement(String p0, String p1, String p2){} + public void endEntity(String p0){} + public void endPrefixMapping(String p0){} + public void flush(){} + public void ignorableWhitespace(char[] p0, int p1, int p2){} + public void notationDecl(String p0, String p1, String p2){} + public void parse(InputSource p0){} + public void println(){} + public void processingInstruction(String p0, String p1){} + public void setDocumentLocator(Locator p0){} + public void setEscapeText(boolean p0){} + public void setIndentLevel(int p0){} + public void setLexicalHandler(LexicalHandler p0){} + public void setMaximumAllowedCharacter(int p0){} + public void setOutputStream(OutputStream p0){} + public void setProperty(String p0, Object p1){} + public void setResolveEntityRefs(boolean p0){} + public void setWriter(Writer p0){} + public void startCDATA(){} + public void startDTD(String p0, String p1, String p2){} + public void startDocument(){} + public void startElement(String p0, String p1, String p2, Attributes p3){} + public void startEntity(String p0){} + public void startPrefixMapping(String p0, String p1){} + public void unparsedEntityDecl(String p0, String p1, String p2, String p3){} + public void write(Attribute p0){} + public void write(CDATA p0){} + public void write(Comment p0){} + public void write(Document p0){} + public void write(DocumentType p0){} + public void write(Element p0){} + public void write(Entity p0){} + public void write(Namespace p0){} + public void write(Node p0){} + public void write(Object p0){} + public void write(ProcessingInstruction p0){} + public void write(String p0){} + public void write(Text p0){} + public void writeClose(Element p0){} + public void writeOpen(Element p0){} +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/rule/Pattern.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/rule/Pattern.java index bf08c6cfd0a..f30b294bc5f 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/rule/Pattern.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/rule/Pattern.java @@ -1,67 +1,19 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.rule.Pattern for testing purposes package org.dom4j.rule; import org.dom4j.Node; import org.dom4j.NodeFilter; -public interface Pattern extends NodeFilter { - boolean matches(Node node); - - double getPriority(); - +public interface Pattern extends NodeFilter +{ Pattern[] getUnionPatterns(); - - short getMatchType(); - String getMatchesNodeName(); - + boolean matches(Node p0); + double getPriority(); + short getMatchType(); + static double DEFAULT_PRIORITY = 0; + static short ANY_NODE = 0; + static short NONE = 0; + static short NUMBER_OF_TYPES = 0; } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/AbstractNode.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/AbstractNode.java index 29ca5198145..d3dfc09f336 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/AbstractNode.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/AbstractNode.java @@ -1,183 +1,53 @@ -/* - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - * - * This software is open source. - * See the bottom of this file for the licence. - */ - -/* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ +// Generated automatically from org.dom4j.tree.AbstractNode for testing purposes package org.dom4j.tree; -import org.dom4j.*; -import org.dom4j.rule.Pattern; -import java.io.IOException; import java.io.Serializable; import java.io.Writer; import java.util.List; +import org.dom4j.Document; +import org.dom4j.DocumentFactory; +import org.dom4j.Element; +import org.dom4j.Node; +import org.dom4j.NodeFilter; +import org.dom4j.XPath; +import org.dom4j.rule.Pattern; -public abstract class AbstractNode implements Node, Cloneable, Serializable { - public AbstractNode() { - } - - public short getNodeType() { - return 0; - } - - public String getNodeTypeName() { - return null; - } - - public Document getDocument() { - return null; - } - - public void setDocument(Document document) { - } - - public Element getParent() { - return null; - } - - public void setParent(Element parent) { - } - - public boolean supportsParent() { - return false; - } - - public boolean isReadOnly() { - return false; - } - - public boolean hasContent() { - return false; - } - - public String getPath() { - return null; - } - - public String getUniquePath() { - return null; - } - - public Object clone() { - return null; - } - - public Node detach() { - return null; - } - - public String getName() { - return null; - } - - public void setName(String name) { - } - - public String getText() { - return null; - } - - public String getStringValue() { - return null; - } - - public void setText(String text) { - } - - public void write(Writer writer) throws IOException { - } - - public Object selectObject(String xpathExpression) { - return null; - } - - public List selectNodes(String xpathExpression) { - return null; - } - - public List selectNodes(String xpathExpression, String comparisonXPathExpression) { - return null; - } - - public List selectNodes(String xpathExpression, String comparisonXPathExpression, boolean removeDuplicates) { - return null; - } - - public Node selectSingleNode(String xpathExpression) { - return null; - } - - public String valueOf(String xpathExpression) { - return null; - } - - public Number numberValueOf(String xpathExpression) { - return null; - } - - public boolean matches(String patternText) { - return false; - } - - public XPath createXPath(String xpathExpression) { - return null; - } - - public NodeFilter createXPathFilter(String patternText) { - return null; - } - - public Pattern createPattern(String patternText) { - return null; - } - - public Node asXPathResult(Element parent) { - return null; - } - +abstract public class AbstractNode implements Cloneable, Node, Serializable +{ + protected DocumentFactory getDocumentFactory(){ return null; } + protected Node createXPathResult(Element p0){ return null; } + protected static String[] NODE_TYPE_NAMES = null; + public AbstractNode(){} + public Document getDocument(){ return null; } + public Element getParent(){ return null; } + public List selectNodes(String p0){ return null; } + public List selectNodes(String p0, String p1){ return null; } + public List selectNodes(String p0, String p1, boolean p2){ return null; } + public Node asXPathResult(Element p0){ return null; } + public Node detach(){ return null; } + public Node selectSingleNode(String p0){ return null; } + public NodeFilter createXPathFilter(String p0){ return null; } + public Number numberValueOf(String p0){ return null; } + public Object clone(){ return null; } + public Object selectObject(String p0){ return null; } + public Pattern createPattern(String p0){ return null; } + public String getName(){ return null; } + public String getNodeTypeName(){ return null; } + public String getPath(){ return null; } + public String getStringValue(){ return null; } + public String getText(){ return null; } + public String getUniquePath(){ return null; } + public String valueOf(String p0){ return null; } + public XPath createXPath(String p0){ return null; } + public boolean hasContent(){ return false; } + public boolean isReadOnly(){ return false; } + public boolean matches(String p0){ return false; } + public boolean supportsParent(){ return false; } + public short getNodeType(){ return 0; } + public void setDocument(Document p0){} + public void setName(String p0){} + public void setParent(Element p0){} + public void setText(String p0){} + public void write(Writer p0){} } - -/* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: - * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. - * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. - * - * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org - * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/NamespaceCache.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/NamespaceCache.java new file mode 100644 index 00000000000..b998094483f --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/NamespaceCache.java @@ -0,0 +1,17 @@ +// Generated automatically from org.dom4j.tree.NamespaceCache for testing purposes + +package org.dom4j.tree; + +import java.util.Map; +import org.dom4j.Namespace; + +public class NamespaceCache +{ + protected Map getURICache(String p0){ return null; } + protected Namespace createNamespace(String p0, String p1){ return null; } + protected static Map cache = null; + protected static Map noPrefixCache = null; + public Namespace get(String p0){ return null; } + public Namespace get(String p0, String p1){ return null; } + public NamespaceCache(){} +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/QNameCache.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/QNameCache.java new file mode 100644 index 00000000000..c4e553a9148 --- /dev/null +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/tree/QNameCache.java @@ -0,0 +1,28 @@ +// Generated automatically from org.dom4j.tree.QNameCache for testing purposes + +package org.dom4j.tree; + +import java.util.List; +import java.util.Map; +import org.dom4j.DocumentFactory; +import org.dom4j.Namespace; +import org.dom4j.QName; + +public class QNameCache +{ + protected Map createMap(){ return null; } + protected Map getNamespaceCache(Namespace p0){ return null; } + protected Map namespaceCache = null; + protected Map noNamespaceCache = null; + protected QName createQName(String p0){ return null; } + protected QName createQName(String p0, Namespace p1){ return null; } + protected QName createQName(String p0, Namespace p1, String p2){ return null; } + public List getQNames(){ return null; } + public QName get(String p0){ return null; } + public QName get(String p0, Namespace p1){ return null; } + public QName get(String p0, Namespace p1, String p2){ return null; } + public QName get(String p0, String p1){ return null; } + public QName intern(QName p0){ return null; } + public QNameCache(){} + public QNameCache(DocumentFactory p0){} +} diff --git a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/xpath/DefaultXPath.java b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/xpath/DefaultXPath.java index fc7e32ed616..e4acaaf4b0e 100644 --- a/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/xpath/DefaultXPath.java +++ b/java/ql/test/stubs/dom4j-2.1.1/org/dom4j/xpath/DefaultXPath.java @@ -1,15 +1,14 @@ /* * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. * - * This software is open source. - * See the bottom of this file for the licence. + * This software is open source. See the bottom of this file for the licence. */ /* -* Adapted from DOM4J version 2.1.1 as available at -* https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar -* Only relevant stubs of this file have been retained for test purposes. -*/ + * Adapted from DOM4J version 2.1.1 as available at + * https://search.maven.org/remotecontent?filepath=org/dom4j/dom4j/2.1.1/dom4j-2.1.1-sources.jar + * Only relevant stubs of this file have been retained for test purposes. + */ package org.dom4j.xpath; @@ -19,117 +18,112 @@ import java.util.Map; import org.dom4j.InvalidXPathException; import org.dom4j.Node; import org.dom4j.XPath; +import org.jaxen.FunctionContext; +import org.jaxen.NamespaceContext; +import org.jaxen.VariableContext; public class DefaultXPath implements org.dom4j.XPath, Serializable { - public DefaultXPath(String text) throws InvalidXPathException { + public DefaultXPath(String text) throws InvalidXPathException {} + + public FunctionContext getFunctionContext() { + return null; + } + + public List selectNodes(Object p0) { + return null; + } + + public List selectNodes(Object p0, XPath p1) { + return null; + } + + public List selectNodes(Object p0, XPath p1, boolean p2) { + return null; + } + + public NamespaceContext getNamespaceContext() { + return null; + } + + public Node selectSingleNode(Object p0) { + return null; + } + + public Number numberValueOf(Object p0) { + return null; + } + + public Object evaluate(Object p0) { + return null; + } + + public Object selectObject(Object p0) { + return null; } - @Override public String getText() { return null; } - @Override - public boolean matches(Node node) { + public String valueOf(Object p0) { + return null; + } + + public VariableContext getVariableContext() { + return null; + } + + public boolean booleanValueOf(Object p0) { return false; } - @Override - public Object evaluate(Object context) { - return null; - } - - @Override - public Object selectObject(Object context) { - return null; - } - - @Override - public List selectNodes(Object context) { - return null; - } - - @Override - public List selectNodes(Object context, XPath sortXPath) { - return null; - } - - @Override - public List selectNodes(Object context, XPath sortXPath, boolean distinct) { - return null; - } - - @Override - public Node selectSingleNode(Object context) { - return null; - } - - @Override - public String valueOf(Object context) { - return null; - } - - @Override - public Number numberValueOf(Object context) { - return null; - } - - @Override - public boolean booleanValueOf(Object context) { + public boolean matches(Node p0) { return false; } - @Override - public void sort(List list) { - } + public void setFunctionContext(FunctionContext p0) {} - @Override - public void sort(List list, boolean distinct) { - } + public void setNamespaceContext(NamespaceContext p0) {} - @Override - public void setNamespaceURIs(Map map) { - } + public void setNamespaceURIs(Map p0) {} - @Override - public void setVariableContext(org.jaxen.VariableContext variableContext) { - } + public void setVariableContext(VariableContext p0) {} + + public void sort(List p0) {} + + public void sort(List p0, boolean p1) {} } /* - * Redistribution and use of this software and associated documentation - * ("Software"), with or without modification, are permitted provided that the - * following conditions are met: + * Redistribution and use of this software and associated documentation ("Software"), with or + * without modification, are permitted provided that the following conditions are met: * - * 1. Redistributions of source code must retain copyright statements and - * notices. Redistributions must also contain a copy of this document. + * 1. Redistributions of source code must retain copyright statements and notices. Redistributions + * must also contain a copy of this document. * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided with + * the distribution. * - * 3. The name "DOM4J" must not be used to endorse or promote products derived - * from this Software without prior written permission of MetaStuff, Ltd. For - * written permission, please contact dom4j-info@metastuff.com. + * 3. The name "DOM4J" must not be used to endorse or promote products derived from this Software + * without prior written permission of MetaStuff, Ltd. For written permission, please contact + * dom4j-info@metastuff.com. * - * 4. Products derived from this Software may not be called "DOM4J" nor may - * "DOM4J" appear in their names without prior written permission of MetaStuff, - * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd. + * 4. Products derived from this Software may not be called "DOM4J" nor may "DOM4J" appear in their + * names without prior written permission of MetaStuff, Ltd. DOM4J is a registered trademark of + * MetaStuff, Ltd. * * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org * - * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. + * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY + * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved. - */ \ No newline at end of file + */ diff --git a/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKClipboard.java b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKClipboard.java new file mode 100644 index 00000000000..36d910d98ba --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKClipboard.java @@ -0,0 +1,26 @@ +// Generated automatically from com.sun.javafx.tk.TKClipboard for testing purposes + +package com.sun.javafx.tk; + +import java.security.AccessControlContext; +import java.util.Set; +import javafx.scene.image.Image; +import javafx.scene.input.DataFormat; +import javafx.scene.input.TransferMode; +import javafx.util.Pair; + +public interface TKClipboard +{ + Image getDragView(); + Object getContent(DataFormat p0); + Set getContentTypes(); + Set getTransferModes(); + boolean hasContent(DataFormat p0); + boolean putContent(Pair... p0); + double getDragViewOffsetX(); + double getDragViewOffsetY(); + void setDragView(Image p0); + void setDragViewOffsetX(double p0); + void setDragViewOffsetY(double p0); + void setSecurityContext(AccessControlContext p0); +} diff --git a/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKDragGestureListener.java b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKDragGestureListener.java new file mode 100644 index 00000000000..01877fec3e7 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKDragGestureListener.java @@ -0,0 +1,10 @@ +// Generated automatically from com.sun.javafx.tk.TKDragGestureListener for testing purposes + +package com.sun.javafx.tk; + +import com.sun.javafx.tk.TKClipboard; + +public interface TKDragGestureListener +{ + void dragGestureRecognized(double p0, double p1, double p2, double p3, int p4, TKClipboard p5); +} diff --git a/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKPulseListener.java b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKPulseListener.java new file mode 100644 index 00000000000..f381217d017 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/sun/javafx/tk/TKPulseListener.java @@ -0,0 +1,9 @@ +// Generated automatically from com.sun.javafx.tk.TKPulseListener for testing purposes + +package com.sun.javafx.tk; + + +public interface TKPulseListener +{ + void pulse(); +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfig.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfig.java new file mode 100644 index 00000000000..a4ff001fcb7 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfig.java @@ -0,0 +1,93 @@ +// Generated automatically from com.zaxxer.hikari.HikariConfig for testing purposes + +package com.zaxxer.hikari; + +import com.zaxxer.hikari.HikariConfigMXBean; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import java.util.Properties; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import javax.sql.DataSource; + +public class HikariConfig implements HikariConfigMXBean +{ + protected void loadProperties(String p0){} + public DataSource getDataSource(){ return null; } + public HikariConfig(){} + public HikariConfig(Properties p0){} + public HikariConfig(String p0){} + public MetricsTrackerFactory getMetricsTrackerFactory(){ return null; } + public Object getHealthCheckRegistry(){ return null; } + public Object getMetricRegistry(){ return null; } + public Properties getDataSourceProperties(){ return null; } + public Properties getHealthCheckProperties(){ return null; } + public ScheduledExecutorService getScheduledExecutor(){ return null; } + public ScheduledThreadPoolExecutor getScheduledExecutorService(){ return null; } + public String getCatalog(){ return null; } + public String getConnectionInitSql(){ return null; } + public String getConnectionTestQuery(){ return null; } + public String getDataSourceClassName(){ return null; } + public String getDataSourceJNDI(){ return null; } + public String getDriverClassName(){ return null; } + public String getJdbcUrl(){ return null; } + public String getPassword(){ return null; } + public String getPoolName(){ return null; } + public String getTransactionIsolation(){ return null; } + public String getUsername(){ return null; } + public ThreadFactory getThreadFactory(){ return null; } + public boolean isAllowPoolSuspension(){ return false; } + public boolean isAutoCommit(){ return false; } + public boolean isInitializationFailFast(){ return false; } + public boolean isIsolateInternalQueries(){ return false; } + public boolean isJdbc4ConnectionTest(){ return false; } + public boolean isReadOnly(){ return false; } + public boolean isRegisterMbeans(){ return false; } + public int getMaximumPoolSize(){ return 0; } + public int getMinimumIdle(){ return 0; } + public long getConnectionTimeout(){ return 0; } + public long getIdleTimeout(){ return 0; } + public long getInitializationFailTimeout(){ return 0; } + public long getLeakDetectionThreshold(){ return 0; } + public long getMaxLifetime(){ return 0; } + public long getValidationTimeout(){ return 0; } + public void addDataSourceProperty(String p0, Object p1){} + public void addHealthCheckProperty(String p0, String p1){} + public void copyState(HikariConfig p0){} + public void setAllowPoolSuspension(boolean p0){} + public void setAutoCommit(boolean p0){} + public void setCatalog(String p0){} + public void setConnectionInitSql(String p0){} + public void setConnectionTestQuery(String p0){} + public void setConnectionTimeout(long p0){} + public void setDataSource(DataSource p0){} + public void setDataSourceClassName(String p0){} + public void setDataSourceJNDI(String p0){} + public void setDataSourceProperties(Properties p0){} + public void setDriverClassName(String p0){} + public void setHealthCheckProperties(Properties p0){} + public void setHealthCheckRegistry(Object p0){} + public void setIdleTimeout(long p0){} + public void setInitializationFailFast(boolean p0){} + public void setInitializationFailTimeout(long p0){} + public void setIsolateInternalQueries(boolean p0){} + public void setJdbc4ConnectionTest(boolean p0){} + public void setJdbcUrl(String p0){} + public void setLeakDetectionThreshold(long p0){} + public void setMaxLifetime(long p0){} + public void setMaximumPoolSize(int p0){} + public void setMetricRegistry(Object p0){} + public void setMetricsTrackerFactory(MetricsTrackerFactory p0){} + public void setMinimumIdle(int p0){} + public void setPassword(String p0){} + public void setPoolName(String p0){} + public void setReadOnly(boolean p0){} + public void setRegisterMbeans(boolean p0){} + public void setScheduledExecutor(ScheduledExecutorService p0){} + public void setScheduledExecutorService(ScheduledThreadPoolExecutor p0){} + public void setThreadFactory(ThreadFactory p0){} + public void setTransactionIsolation(String p0){} + public void setUsername(String p0){} + public void setValidationTimeout(long p0){} + public void validate(){} +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfigMXBean.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfigMXBean.java new file mode 100644 index 00000000000..5d03182f84a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariConfigMXBean.java @@ -0,0 +1,25 @@ +// Generated automatically from com.zaxxer.hikari.HikariConfigMXBean for testing purposes + +package com.zaxxer.hikari; + + +public interface HikariConfigMXBean +{ + String getPoolName(); + int getMaximumPoolSize(); + int getMinimumIdle(); + long getConnectionTimeout(); + long getIdleTimeout(); + long getLeakDetectionThreshold(); + long getMaxLifetime(); + long getValidationTimeout(); + void setConnectionTimeout(long p0); + void setIdleTimeout(long p0); + void setLeakDetectionThreshold(long p0); + void setMaxLifetime(long p0); + void setMaximumPoolSize(int p0); + void setMinimumIdle(int p0); + void setPassword(String p0); + void setUsername(String p0); + void setValidationTimeout(long p0); +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariDataSource.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariDataSource.java new file mode 100644 index 00000000000..e81f7c654f0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariDataSource.java @@ -0,0 +1,40 @@ +// Generated automatically from com.zaxxer.hikari.HikariDataSource for testing purposes + +package com.zaxxer.hikari; + +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariConfigMXBean; +import com.zaxxer.hikari.HikariPoolMXBean; +import com.zaxxer.hikari.metrics.MetricsTrackerFactory; +import java.io.Closeable; +import java.io.PrintWriter; +import java.sql.Connection; +import java.util.logging.Logger; +import javax.sql.DataSource; + +public class HikariDataSource extends HikariConfig implements Closeable, DataSource +{ + public T unwrap(java.lang.Class p0){ return null; } + public Connection getConnection(){ return null; } + public Connection getConnection(String p0, String p1){ return null; } + public HikariConfigMXBean getHikariConfigMXBean(){ return null; } + public HikariDataSource(){} + public HikariDataSource(HikariConfig p0){} + public HikariPoolMXBean getHikariPoolMXBean(){ return null; } + public Logger getParentLogger(){ return null; } + public PrintWriter getLogWriter(){ return null; } + public String toString(){ return null; } + public boolean isClosed(){ return false; } + public boolean isWrapperFor(Class p0){ return false; } + public int getLoginTimeout(){ return 0; } + public void close(){} + public void evictConnection(Connection p0){} + public void resumePool(){} + public void setHealthCheckRegistry(Object p0){} + public void setLogWriter(PrintWriter p0){} + public void setLoginTimeout(int p0){} + public void setMetricRegistry(Object p0){} + public void setMetricsTrackerFactory(MetricsTrackerFactory p0){} + public void shutdown(){} + public void suspendPool(){} +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariPoolMXBean.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariPoolMXBean.java new file mode 100644 index 00000000000..25b499bca19 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/HikariPoolMXBean.java @@ -0,0 +1,15 @@ +// Generated automatically from com.zaxxer.hikari.HikariPoolMXBean for testing purposes + +package com.zaxxer.hikari; + + +public interface HikariPoolMXBean +{ + int getActiveConnections(); + int getIdleConnections(); + int getThreadsAwaitingConnection(); + int getTotalConnections(); + void resumePool(); + void softEvictConnections(); + void suspendPool(); +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTracker.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTracker.java new file mode 100644 index 00000000000..5dcb6100c24 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTracker.java @@ -0,0 +1,13 @@ +// Generated automatically from com.zaxxer.hikari.metrics.MetricsTracker for testing purposes + +package com.zaxxer.hikari.metrics; + + +public class MetricsTracker implements AutoCloseable +{ + public MetricsTracker(){} + public void close(){} + public void recordConnectionAcquiredNanos(long p0){} + public void recordConnectionTimeout(){} + public void recordConnectionUsageMillis(long p0){} +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTrackerFactory.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTrackerFactory.java new file mode 100644 index 00000000000..ee70d6a542c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/MetricsTrackerFactory.java @@ -0,0 +1,11 @@ +// Generated automatically from com.zaxxer.hikari.metrics.MetricsTrackerFactory for testing purposes + +package com.zaxxer.hikari.metrics; + +import com.zaxxer.hikari.metrics.MetricsTracker; +import com.zaxxer.hikari.metrics.PoolStats; + +public interface MetricsTrackerFactory +{ + MetricsTracker create(String p0, PoolStats p1); +} diff --git a/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/PoolStats.java b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/PoolStats.java new file mode 100644 index 00000000000..98b7871d56b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/com/zaxxer/hikari/metrics/PoolStats.java @@ -0,0 +1,19 @@ +// Generated automatically from com.zaxxer.hikari.metrics.PoolStats for testing purposes + +package com.zaxxer.hikari.metrics; + + +abstract public class PoolStats +{ + protected PoolStats() {} + protected abstract void update(); + protected int activeConnections = 0; + protected int idleConnections = 0; + protected int pendingThreads = 0; + protected int totalConnections = 0; + public PoolStats(long p0){} + public int getActiveConnections(){ return 0; } + public int getIdleConnections(){ return 0; } + public int getPendingThreads(){ return 0; } + public int getTotalConnections(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/io/micrometer/observation/Context.java b/java/ql/test/stubs/javafx-web/io/micrometer/observation/Context.java new file mode 100644 index 00000000000..4d207214807 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/io/micrometer/observation/Context.java @@ -0,0 +1,9 @@ +// Generated automatically from io.micrometer.observation.Context for testing purposes + +package io.micrometer.observation; + + +public class Context +{ + protected Context() {} +} diff --git a/java/ql/test/stubs/javafx-web/io/micrometer/observation/ObservationRegistry.java b/java/ql/test/stubs/javafx-web/io/micrometer/observation/ObservationRegistry.java new file mode 100644 index 00000000000..64187242e84 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/io/micrometer/observation/ObservationRegistry.java @@ -0,0 +1,9 @@ +// Generated automatically from io.micrometer.observation.ObservationRegistry for testing purposes + +package io.micrometer.observation; + + +public class ObservationRegistry +{ + protected ObservationRegistry() {} +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/RuntimeType.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/RuntimeType.java new file mode 100644 index 00000000000..76edb9fd512 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/RuntimeType.java @@ -0,0 +1,10 @@ +// Generated automatically from jakarta.ws.rs.RuntimeType for testing purposes + +package jakarta.ws.rs; + + +public enum RuntimeType +{ + CLIENT, SERVER; + private RuntimeType() {} +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/AsyncInvoker.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/AsyncInvoker.java new file mode 100644 index 00000000000..d96a2e6fecc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/AsyncInvoker.java @@ -0,0 +1,47 @@ +// Generated automatically from jakarta.ws.rs.client.AsyncInvoker for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.InvocationCallback; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; +import java.util.concurrent.Future; + +public interface AsyncInvoker +{ + java.util.concurrent.Future delete(jakarta.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future delete(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.Future delete(java.lang.Class p0); + java.util.concurrent.Future get(jakarta.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future get(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.Future get(java.lang.Class p0); + java.util.concurrent.Future method(String p0, Entity p1, jakarta.ws.rs.client.InvocationCallback p2); + java.util.concurrent.Future method(String p0, Entity p1, jakarta.ws.rs.core.GenericType p2); + java.util.concurrent.Future method(String p0, Entity p1, java.lang.Class p2); + java.util.concurrent.Future method(String p0, jakarta.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future method(String p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.Future method(String p0, java.lang.Class p1); + java.util.concurrent.Future options(jakarta.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future options(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.Future options(java.lang.Class p0); + java.util.concurrent.Future post(Entity p0, jakarta.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future post(Entity p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.Future post(Entity p0, java.lang.Class p1); + java.util.concurrent.Future put(Entity p0, jakarta.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future put(Entity p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.Future put(Entity p0, java.lang.Class p1); + java.util.concurrent.Future trace(jakarta.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future trace(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.Future trace(java.lang.Class p0); + java.util.concurrent.Future delete(); + java.util.concurrent.Future get(); + java.util.concurrent.Future head(); + java.util.concurrent.Future head(InvocationCallback p0); + java.util.concurrent.Future method(String p0); + java.util.concurrent.Future method(String p0, Entity p1); + java.util.concurrent.Future options(); + java.util.concurrent.Future post(Entity p0); + java.util.concurrent.Future put(Entity p0); + java.util.concurrent.Future trace(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Client.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Client.java new file mode 100644 index 00000000000..c2d1e654a47 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Client.java @@ -0,0 +1,24 @@ +// Generated automatically from jakarta.ws.rs.client.Client for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.client.WebTarget; +import jakarta.ws.rs.core.Configurable; +import jakarta.ws.rs.core.Link; +import jakarta.ws.rs.core.UriBuilder; +import java.net.URI; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + +public interface Client extends AutoCloseable, Configurable +{ + HostnameVerifier getHostnameVerifier(); + Invocation.Builder invocation(Link p0); + SSLContext getSslContext(); + WebTarget target(Link p0); + WebTarget target(String p0); + WebTarget target(URI p0); + WebTarget target(UriBuilder p0); + void close(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/ClientBuilder.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/ClientBuilder.java new file mode 100644 index 00000000000..4e5c0c4c330 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/ClientBuilder.java @@ -0,0 +1,33 @@ +// Generated automatically from jakarta.ws.rs.client.ClientBuilder for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.core.Configurable; +import jakarta.ws.rs.core.Configuration; +import java.security.KeyStore; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; + +abstract public class ClientBuilder implements Configurable +{ + protected ClientBuilder(){} + public ClientBuilder keyStore(KeyStore p0, String p1){ return null; } + public abstract Client build(); + public abstract ClientBuilder connectTimeout(long p0, TimeUnit p1); + public abstract ClientBuilder executorService(ExecutorService p0); + public abstract ClientBuilder hostnameVerifier(HostnameVerifier p0); + public abstract ClientBuilder keyStore(KeyStore p0, char[] p1); + public abstract ClientBuilder readTimeout(long p0, TimeUnit p1); + public abstract ClientBuilder scheduledExecutorService(ScheduledExecutorService p0); + public abstract ClientBuilder sslContext(SSLContext p0); + public abstract ClientBuilder trustStore(KeyStore p0); + public abstract ClientBuilder withConfig(Configuration p0); + public static Client newClient(){ return null; } + public static Client newClient(Configuration p0){ return null; } + public static ClientBuilder newBuilder(){ return null; } + public static String JAXRS_DEFAULT_CLIENT_BUILDER_PROPERTY = null; +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/CompletionStageRxInvoker.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/CompletionStageRxInvoker.java new file mode 100644 index 00000000000..4a454692c98 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/CompletionStageRxInvoker.java @@ -0,0 +1,38 @@ +// Generated automatically from jakarta.ws.rs.client.CompletionStageRxInvoker for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.RxInvoker; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; +import java.util.concurrent.CompletionStage; + +public interface CompletionStageRxInvoker extends RxInvoker +{ + java.util.concurrent.CompletionStage delete(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.CompletionStage delete(java.lang.Class p0); + java.util.concurrent.CompletionStage get(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.CompletionStage get(java.lang.Class p0); + java.util.concurrent.CompletionStage method(String p0, Entity p1, jakarta.ws.rs.core.GenericType p2); + java.util.concurrent.CompletionStage method(String p0, Entity p1, java.lang.Class p2); + java.util.concurrent.CompletionStage method(String p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.CompletionStage method(String p0, java.lang.Class p1); + java.util.concurrent.CompletionStage options(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.CompletionStage options(java.lang.Class p0); + java.util.concurrent.CompletionStage post(Entity p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.CompletionStage post(Entity p0, java.lang.Class p1); + java.util.concurrent.CompletionStage put(Entity p0, jakarta.ws.rs.core.GenericType p1); + java.util.concurrent.CompletionStage put(Entity p0, java.lang.Class p1); + java.util.concurrent.CompletionStage trace(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.CompletionStage trace(java.lang.Class p0); + CompletionStage delete(); + CompletionStage get(); + CompletionStage head(); + CompletionStage method(String p0); + CompletionStage method(String p0, Entity p1); + CompletionStage options(); + CompletionStage post(Entity p0); + CompletionStage put(Entity p0); + CompletionStage trace(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Entity.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Entity.java new file mode 100644 index 00000000000..30977a07dd2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Entity.java @@ -0,0 +1,36 @@ +// Generated automatically from jakarta.ws.rs.client.Entity for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.core.Form; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.Variant; +import java.lang.annotation.Annotation; +import java.util.Locale; + +public class Entity +{ + protected Entity() {} + public Annotation[] getAnnotations(){ return null; } + public Locale getLanguage(){ return null; } + public MediaType getMediaType(){ return null; } + public String getEncoding(){ return null; } + public String toString(){ return null; } + public T getEntity(){ return null; } + public Variant getVariant(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static jakarta.ws.rs.client.Entity entity(T p0, MediaType p1){ return null; } + public static jakarta.ws.rs.client.Entity entity(T p0, MediaType p1, Annotation[] p2){ return null; } + public static jakarta.ws.rs.client.Entity entity(T p0, String p1){ return null; } + public static jakarta.ws.rs.client.Entity entity(T p0, Variant p1){ return null; } + public static jakarta.ws.rs.client.Entity entity(T p0, Variant p1, Annotation[] p2){ return null; } + public static jakarta.ws.rs.client.Entity html(T p0){ return null; } + public static jakarta.ws.rs.client.Entity json(T p0){ return null; } + public static jakarta.ws.rs.client.Entity text(T p0){ return null; } + public static jakarta.ws.rs.client.Entity xhtml(T p0){ return null; } + public static jakarta.ws.rs.client.Entity xml(T p0){ return null; } + public static Entity
    form(Form p0){ return null; } + public static Entity form(MultivaluedMap p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Invocation.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Invocation.java new file mode 100644 index 00000000000..87267ee1d5d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/Invocation.java @@ -0,0 +1,53 @@ +// Generated automatically from jakarta.ws.rs.client.Invocation for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.AsyncInvoker; +import jakarta.ws.rs.client.CompletionStageRxInvoker; +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.client.InvocationCallback; +import jakarta.ws.rs.client.RxInvoker; +import jakarta.ws.rs.client.SyncInvoker; +import jakarta.ws.rs.core.CacheControl; +import jakarta.ws.rs.core.Cookie; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.Response; +import java.util.Locale; +import java.util.concurrent.Future; + +public interface Invocation +{ + T invoke(jakarta.ws.rs.core.GenericType p0); + T invoke(java.lang.Class p0); + java.util.concurrent.Future submit(jakarta.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future submit(jakarta.ws.rs.core.GenericType p0); + java.util.concurrent.Future submit(java.lang.Class p0); + Invocation property(String p0, Object p1); + Response invoke(); + java.util.concurrent.Future submit(); + static public interface Builder extends SyncInvoker + { + T rx(java.lang.Class p0); + AsyncInvoker async(); + CompletionStageRxInvoker rx(); + Invocation build(String p0); + Invocation build(String p0, Entity p1); + Invocation buildDelete(); + Invocation buildGet(); + Invocation buildPost(Entity p0); + Invocation buildPut(Entity p0); + Invocation.Builder accept(MediaType... p0); + Invocation.Builder accept(String... p0); + Invocation.Builder acceptEncoding(String... p0); + Invocation.Builder acceptLanguage(Locale... p0); + Invocation.Builder acceptLanguage(String... p0); + Invocation.Builder cacheControl(CacheControl p0); + Invocation.Builder cookie(Cookie p0); + Invocation.Builder cookie(String p0, String p1); + Invocation.Builder header(String p0, Object p1); + Invocation.Builder headers(MultivaluedMap p0); + Invocation.Builder property(String p0, Object p1); + } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/InvocationCallback.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/InvocationCallback.java new file mode 100644 index 00000000000..45551014541 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/InvocationCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from jakarta.ws.rs.client.InvocationCallback for testing purposes + +package jakarta.ws.rs.client; + + +public interface InvocationCallback +{ + void completed(RESPONSE p0); + void failed(Throwable p0); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/RxInvoker.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/RxInvoker.java new file mode 100644 index 00000000000..d36b6155b78 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/RxInvoker.java @@ -0,0 +1,35 @@ +// Generated automatically from jakarta.ws.rs.client.RxInvoker for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.GenericType; + +public interface RxInvoker +{ + T delete(jakarta.ws.rs.core.GenericType p0); + T delete(java.lang.Class p0); + T get(jakarta.ws.rs.core.GenericType p0); + T get(java.lang.Class p0); + T method(String p0, Entity p1, jakarta.ws.rs.core.GenericType p2); + T method(String p0, Entity p1, java.lang.Class p2); + T method(String p0, jakarta.ws.rs.core.GenericType p1); + T method(String p0, java.lang.Class p1); + T options(jakarta.ws.rs.core.GenericType p0); + T options(java.lang.Class p0); + T post(Entity p0, jakarta.ws.rs.core.GenericType p1); + T post(Entity p0, java.lang.Class p1); + T put(Entity p0, jakarta.ws.rs.core.GenericType p1); + T put(Entity p0, java.lang.Class p1); + T trace(jakarta.ws.rs.core.GenericType p0); + T trace(java.lang.Class p0); + T delete(); + T get(); + T head(); + T method(String p0); + T method(String p0, Entity p1); + T options(); + T post(Entity p0); + T put(Entity p0); + T trace(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/SyncInvoker.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/SyncInvoker.java new file mode 100644 index 00000000000..3689869116e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/SyncInvoker.java @@ -0,0 +1,36 @@ +// Generated automatically from jakarta.ws.rs.client.SyncInvoker for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Entity; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Response; + +public interface SyncInvoker +{ + T delete(jakarta.ws.rs.core.GenericType p0); + T delete(java.lang.Class p0); + T get(jakarta.ws.rs.core.GenericType p0); + T get(java.lang.Class p0); + T method(String p0, Entity p1, jakarta.ws.rs.core.GenericType p2); + T method(String p0, Entity p1, java.lang.Class p2); + T method(String p0, jakarta.ws.rs.core.GenericType p1); + T method(String p0, java.lang.Class p1); + T options(jakarta.ws.rs.core.GenericType p0); + T options(java.lang.Class p0); + T post(Entity p0, jakarta.ws.rs.core.GenericType p1); + T post(Entity p0, java.lang.Class p1); + T put(Entity p0, jakarta.ws.rs.core.GenericType p1); + T put(Entity p0, java.lang.Class p1); + T trace(jakarta.ws.rs.core.GenericType p0); + T trace(java.lang.Class p0); + Response delete(); + Response get(); + Response head(); + Response method(String p0); + Response method(String p0, Entity p1); + Response options(); + Response post(Entity p0); + Response put(Entity p0); + Response trace(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/WebTarget.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/WebTarget.java new file mode 100644 index 00000000000..249828a6b86 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/client/WebTarget.java @@ -0,0 +1,28 @@ +// Generated automatically from jakarta.ws.rs.client.WebTarget for testing purposes + +package jakarta.ws.rs.client; + +import jakarta.ws.rs.client.Invocation; +import jakarta.ws.rs.core.Configurable; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.Map; + +public interface WebTarget extends Configurable +{ + Invocation.Builder request(); + Invocation.Builder request(MediaType... p0); + Invocation.Builder request(String... p0); + URI getUri(); + UriBuilder getUriBuilder(); + WebTarget matrixParam(String p0, Object... p1); + WebTarget path(String p0); + WebTarget queryParam(String p0, Object... p1); + WebTarget resolveTemplate(String p0, Object p1); + WebTarget resolveTemplate(String p0, Object p1, boolean p2); + WebTarget resolveTemplateFromEncoded(String p0, Object p1); + WebTarget resolveTemplates(Map p0); + WebTarget resolveTemplates(Map p0, boolean p1); + WebTarget resolveTemplatesFromEncoded(Map p0); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/CacheControl.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/CacheControl.java new file mode 100644 index 00000000000..400fab26e4d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/CacheControl.java @@ -0,0 +1,34 @@ +// Generated automatically from jakarta.ws.rs.core.CacheControl for testing purposes + +package jakarta.ws.rs.core; + +import java.util.List; +import java.util.Map; + +public class CacheControl +{ + public CacheControl(){} + public List getNoCacheFields(){ return null; } + public List getPrivateFields(){ return null; } + public Map getCacheExtension(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isMustRevalidate(){ return false; } + public boolean isNoCache(){ return false; } + public boolean isNoStore(){ return false; } + public boolean isNoTransform(){ return false; } + public boolean isPrivate(){ return false; } + public boolean isProxyRevalidate(){ return false; } + public int getMaxAge(){ return 0; } + public int getSMaxAge(){ return 0; } + public int hashCode(){ return 0; } + public static CacheControl valueOf(String p0){ return null; } + public void setMaxAge(int p0){} + public void setMustRevalidate(boolean p0){} + public void setNoCache(boolean p0){} + public void setNoStore(boolean p0){} + public void setNoTransform(boolean p0){} + public void setPrivate(boolean p0){} + public void setProxyRevalidate(boolean p0){} + public void setSMaxAge(int p0){} +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configurable.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configurable.java new file mode 100644 index 00000000000..6806fd9fa34 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configurable.java @@ -0,0 +1,20 @@ +// Generated automatically from jakarta.ws.rs.core.Configurable for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.Configuration; +import java.util.Map; + +public interface Configurable +{ + C property(String p0, Object p1); + C register(Class p0); + C register(Class p0, Class... p1); + C register(Class p0, Map, Integer> p1); + C register(Class p0, int p1); + C register(Object p0); + C register(Object p0, Class... p1); + C register(Object p0, Map, Integer> p1); + C register(Object p0, int p1); + Configuration getConfiguration(); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configuration.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configuration.java new file mode 100644 index 00000000000..a03617bb948 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Configuration.java @@ -0,0 +1,25 @@ +// Generated automatically from jakarta.ws.rs.core.Configuration for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.RuntimeType; +import jakarta.ws.rs.core.Feature; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +public interface Configuration +{ + Collection getPropertyNames(); + Map, Integer> getContracts(Class p0); + Map getProperties(); + Object getProperty(String p0); + RuntimeType getRuntimeType(); + Set> getClasses(); + Set getInstances(); + boolean isEnabled(Feature p0); + boolean isEnabled(java.lang.Class p0); + boolean isRegistered(Class p0); + boolean isRegistered(Object p0); + default boolean hasProperty(String p0){ return false; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Cookie.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Cookie.java new file mode 100644 index 00000000000..fcaef867a1e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Cookie.java @@ -0,0 +1,33 @@ +// Generated automatically from jakarta.ws.rs.core.Cookie for testing purposes + +package jakarta.ws.rs.core; + + +public class Cookie +{ + protected Cookie() {} + abstract static public class AbstractCookieBuilder> + { + protected AbstractCookieBuilder() {} + public AbstractCookieBuilder(String p0){} + public T domain(String p0){ return null; } + public T path(String p0){ return null; } + public T value(String p0){ return null; } + public T version(int p0){ return null; } + public abstract Cookie build(); + } + protected Cookie(Cookie.AbstractCookieBuilder p0){} + public Cookie(String p0, String p1){} + public Cookie(String p0, String p1, String p2, String p3){} + public Cookie(String p0, String p1, String p2, String p3, int p4){} + public String getDomain(){ return null; } + public String getName(){ return null; } + public String getPath(){ return null; } + public String getValue(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getVersion(){ return 0; } + public int hashCode(){ return 0; } + public static Cookie valueOf(String p0){ return null; } + public static int DEFAULT_VERSION = 0; +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/EntityTag.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/EntityTag.java new file mode 100644 index 00000000000..47d0dba0c93 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/EntityTag.java @@ -0,0 +1,17 @@ +// Generated automatically from jakarta.ws.rs.core.EntityTag for testing purposes + +package jakarta.ws.rs.core; + + +public class EntityTag +{ + protected EntityTag() {} + public EntityTag(String p0){} + public EntityTag(String p0, boolean p1){} + public String getValue(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isWeak(){ return false; } + public int hashCode(){ return 0; } + public static EntityTag valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Feature.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Feature.java new file mode 100644 index 00000000000..bbb179974fd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Feature.java @@ -0,0 +1,10 @@ +// Generated automatically from jakarta.ws.rs.core.Feature for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.FeatureContext; + +public interface Feature +{ + boolean configure(FeatureContext p0); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/FeatureContext.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/FeatureContext.java new file mode 100644 index 00000000000..8d0e04ed10b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/FeatureContext.java @@ -0,0 +1,9 @@ +// Generated automatically from jakarta.ws.rs.core.FeatureContext for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.Configurable; + +public interface FeatureContext extends Configurable +{ +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Form.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Form.java new file mode 100644 index 00000000000..67e025dbb14 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Form.java @@ -0,0 +1,14 @@ +// Generated automatically from jakarta.ws.rs.core.Form for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.MultivaluedMap; + +public class Form +{ + public Form param(String p0, String p1){ return null; } + public Form(){} + public Form(MultivaluedMap p0){} + public Form(String p0, String p1){} + public MultivaluedMap asMap(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/GenericType.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/GenericType.java new file mode 100644 index 00000000000..a70692d41c5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/GenericType.java @@ -0,0 +1,17 @@ +// Generated automatically from jakarta.ws.rs.core.GenericType for testing purposes + +package jakarta.ws.rs.core; + +import java.lang.reflect.Type; + +public class GenericType +{ + protected GenericType(){} + public GenericType(Type p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final Class getRawType(){ return null; } + public final Type getType(){ return null; } + public int hashCode(){ return 0; } + public static GenericType forInstance(Object p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Link.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Link.java new file mode 100644 index 00000000000..bc66793f67c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Link.java @@ -0,0 +1,48 @@ +// Generated automatically from jakarta.ws.rs.core.Link for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.UriBuilder; +import java.net.URI; +import java.util.List; +import java.util.Map; + +abstract public class Link +{ + public Link(){} + public abstract List getRels(); + public abstract Map getParams(); + public abstract String getRel(); + public abstract String getTitle(); + public abstract String getType(); + public abstract String toString(); + public abstract URI getUri(); + public abstract UriBuilder getUriBuilder(); + public static Link valueOf(String p0){ return null; } + public static Link.Builder fromLink(Link p0){ return null; } + public static Link.Builder fromMethod(Class p0, String p1){ return null; } + public static Link.Builder fromPath(String p0){ return null; } + public static Link.Builder fromResource(Class p0){ return null; } + public static Link.Builder fromUri(String p0){ return null; } + public static Link.Builder fromUri(URI p0){ return null; } + public static Link.Builder fromUriBuilder(UriBuilder p0){ return null; } + public static String REL = null; + public static String TITLE = null; + public static String TYPE = null; + static public interface Builder + { + Link build(Object... p0); + Link buildRelativized(URI p0, Object... p1); + Link.Builder baseUri(String p0); + Link.Builder baseUri(URI p0); + Link.Builder link(Link p0); + Link.Builder link(String p0); + Link.Builder param(String p0, String p1); + Link.Builder rel(String p0); + Link.Builder title(String p0); + Link.Builder type(String p0); + Link.Builder uri(String p0); + Link.Builder uri(URI p0); + Link.Builder uriBuilder(UriBuilder p0); + } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MediaType.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MediaType.java new file mode 100644 index 00000000000..f8d34b1ba8d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MediaType.java @@ -0,0 +1,54 @@ +// Generated automatically from jakarta.ws.rs.core.MediaType for testing purposes + +package jakarta.ws.rs.core; + +import java.util.Map; + +public class MediaType +{ + public Map getParameters(){ return null; } + public MediaType withCharset(String p0){ return null; } + public MediaType(){} + public MediaType(String p0, String p1){} + public MediaType(String p0, String p1, Map p2){} + public MediaType(String p0, String p1, String p2){} + public String getSubtype(){ return null; } + public String getType(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isCompatible(MediaType p0){ return false; } + public boolean isWildcardSubtype(){ return false; } + public boolean isWildcardType(){ return false; } + public int hashCode(){ return 0; } + public static MediaType APPLICATION_ATOM_XML_TYPE = null; + public static MediaType APPLICATION_FORM_URLENCODED_TYPE = null; + public static MediaType APPLICATION_JSON_PATCH_JSON_TYPE = null; + public static MediaType APPLICATION_JSON_TYPE = null; + public static MediaType APPLICATION_OCTET_STREAM_TYPE = null; + public static MediaType APPLICATION_SVG_XML_TYPE = null; + public static MediaType APPLICATION_XHTML_XML_TYPE = null; + public static MediaType APPLICATION_XML_TYPE = null; + public static MediaType MULTIPART_FORM_DATA_TYPE = null; + public static MediaType SERVER_SENT_EVENTS_TYPE = null; + public static MediaType TEXT_HTML_TYPE = null; + public static MediaType TEXT_PLAIN_TYPE = null; + public static MediaType TEXT_XML_TYPE = null; + public static MediaType WILDCARD_TYPE = null; + public static MediaType valueOf(String p0){ return null; } + public static String APPLICATION_ATOM_XML = null; + public static String APPLICATION_FORM_URLENCODED = null; + public static String APPLICATION_JSON = null; + public static String APPLICATION_JSON_PATCH_JSON = null; + public static String APPLICATION_OCTET_STREAM = null; + public static String APPLICATION_SVG_XML = null; + public static String APPLICATION_XHTML_XML = null; + public static String APPLICATION_XML = null; + public static String CHARSET_PARAMETER = null; + public static String MEDIA_TYPE_WILDCARD = null; + public static String MULTIPART_FORM_DATA = null; + public static String SERVER_SENT_EVENTS = null; + public static String TEXT_HTML = null; + public static String TEXT_PLAIN = null; + public static String TEXT_XML = null; + public static String WILDCARD = null; +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MultivaluedMap.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MultivaluedMap.java new file mode 100644 index 00000000000..5cefd2248c2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/MultivaluedMap.java @@ -0,0 +1,17 @@ +// Generated automatically from jakarta.ws.rs.core.MultivaluedMap for testing purposes + +package jakarta.ws.rs.core; + +import java.util.List; +import java.util.Map; + +public interface MultivaluedMap extends java.util.Map> +{ + V getFirst(K p0); + boolean equalsIgnoreValueOrder(MultivaluedMap p0); + void add(K p0, V p1); + void addAll(K p0, V... p1); + void addAll(K p0, java.util.List p1); + void addFirst(K p0, V p1); + void putSingle(K p0, V p1); +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/NewCookie.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/NewCookie.java new file mode 100644 index 00000000000..77c3f68c4db --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/NewCookie.java @@ -0,0 +1,51 @@ +// Generated automatically from jakarta.ws.rs.core.NewCookie for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.Cookie; + +public class NewCookie extends Cookie +{ + protected NewCookie() {} + abstract static public class AbstractNewCookieBuilder> extends Cookie.AbstractCookieBuilder> + { + protected AbstractNewCookieBuilder() {} + public AbstractNewCookieBuilder(Cookie p0){} + public AbstractNewCookieBuilder(String p0){} + public T comment(String p0){ return null; } + public T expiry(java.util.Date p0){ return null; } + public T httpOnly(boolean p0){ return null; } + public T maxAge(int p0){ return null; } + public T sameSite(NewCookie.SameSite p0){ return null; } + public T secure(boolean p0){ return null; } + public abstract NewCookie build(); + } + protected NewCookie(NewCookie.AbstractNewCookieBuilder p0){} + public Cookie toCookie(){ return null; } + public NewCookie(Cookie p0){} + public NewCookie(Cookie p0, String p1, int p2, boolean p3){} + public NewCookie(Cookie p0, String p1, int p2, java.util.Date p3, boolean p4, boolean p5){} + public NewCookie(Cookie p0, String p1, int p2, java.util.Date p3, boolean p4, boolean p5, NewCookie.SameSite p6){} + public NewCookie(String p0, String p1){} + public NewCookie(String p0, String p1, String p2, String p3, String p4, int p5, boolean p6){} + public NewCookie(String p0, String p1, String p2, String p3, String p4, int p5, boolean p6, boolean p7){} + public NewCookie(String p0, String p1, String p2, String p3, int p4, String p5, int p6, boolean p7){} + public NewCookie(String p0, String p1, String p2, String p3, int p4, String p5, int p6, java.util.Date p7, boolean p8, boolean p9){} + public NewCookie(String p0, String p1, String p2, String p3, int p4, String p5, int p6, java.util.Date p7, boolean p8, boolean p9, NewCookie.SameSite p10){} + public NewCookie.SameSite getSameSite(){ return null; } + public String getComment(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isHttpOnly(){ return false; } + public boolean isSecure(){ return false; } + public int getMaxAge(){ return 0; } + public int hashCode(){ return 0; } + public java.util.Date getExpiry(){ return null; } + public static NewCookie valueOf(String p0){ return null; } + public static int DEFAULT_MAX_AGE = 0; + static public enum SameSite + { + LAX, NONE, STRICT; + private SameSite() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Response.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Response.java new file mode 100644 index 00000000000..260ff646053 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Response.java @@ -0,0 +1,131 @@ +// Generated automatically from jakarta.ws.rs.core.Response for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.CacheControl; +import jakarta.ws.rs.core.EntityTag; +import jakarta.ws.rs.core.GenericType; +import jakarta.ws.rs.core.Link; +import jakarta.ws.rs.core.MediaType; +import jakarta.ws.rs.core.MultivaluedMap; +import jakarta.ws.rs.core.NewCookie; +import jakarta.ws.rs.core.Variant; +import java.lang.annotation.Annotation; +import java.net.URI; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +abstract public class Response implements AutoCloseable +{ + abstract static public class ResponseBuilder + { + protected ResponseBuilder(){} + protected static Response.ResponseBuilder newInstance(){ return null; } + public Response.ResponseBuilder status(Response.Status p0){ return null; } + public Response.ResponseBuilder status(Response.StatusType p0){ return null; } + public abstract Response build(); + public abstract Response.ResponseBuilder allow(Set p0); + public abstract Response.ResponseBuilder allow(String... p0); + public abstract Response.ResponseBuilder cacheControl(CacheControl p0); + public abstract Response.ResponseBuilder clone(); + public abstract Response.ResponseBuilder contentLocation(URI p0); + public abstract Response.ResponseBuilder cookie(NewCookie... p0); + public abstract Response.ResponseBuilder encoding(String p0); + public abstract Response.ResponseBuilder entity(Object p0); + public abstract Response.ResponseBuilder entity(Object p0, Annotation[] p1); + public abstract Response.ResponseBuilder expires(java.util.Date p0); + public abstract Response.ResponseBuilder header(String p0, Object p1); + public abstract Response.ResponseBuilder language(Locale p0); + public abstract Response.ResponseBuilder language(String p0); + public abstract Response.ResponseBuilder lastModified(java.util.Date p0); + public abstract Response.ResponseBuilder link(String p0, String p1); + public abstract Response.ResponseBuilder link(URI p0, String p1); + public abstract Response.ResponseBuilder links(Link... p0); + public abstract Response.ResponseBuilder location(URI p0); + public abstract Response.ResponseBuilder replaceAll(MultivaluedMap p0); + public abstract Response.ResponseBuilder status(int p0); + public abstract Response.ResponseBuilder status(int p0, String p1); + public abstract Response.ResponseBuilder tag(EntityTag p0); + public abstract Response.ResponseBuilder tag(String p0); + public abstract Response.ResponseBuilder type(MediaType p0); + public abstract Response.ResponseBuilder type(String p0); + public abstract Response.ResponseBuilder variant(Variant p0); + public abstract Response.ResponseBuilder variants(Variant... p0); + public abstract Response.ResponseBuilder variants(java.util.List p0); + } + protected Response(){} + public MultivaluedMap getHeaders(){ return null; } + public abstract T readEntity(jakarta.ws.rs.core.GenericType p0); + public abstract T readEntity(jakarta.ws.rs.core.GenericType p0, Annotation[] p1); + public abstract T readEntity(java.lang.Class p0); + public abstract T readEntity(java.lang.Class p0, Annotation[] p1); + public abstract EntityTag getEntityTag(); + public abstract Link getLink(String p0); + public abstract Link.Builder getLinkBuilder(String p0); + public abstract Locale getLanguage(); + public abstract MediaType getMediaType(); + public abstract MultivaluedMap getMetadata(); + public abstract MultivaluedMap getStringHeaders(); + public abstract Object getEntity(); + public abstract Response.StatusType getStatusInfo(); + public abstract Set getAllowedMethods(); + public abstract String getHeaderString(String p0); + public abstract URI getLocation(); + public abstract boolean bufferEntity(); + public abstract boolean hasEntity(); + public abstract boolean hasLink(String p0); + public abstract int getLength(); + public abstract int getStatus(); + public abstract java.util.Date getDate(); + public abstract java.util.Date getLastModified(); + public abstract java.util.Map getCookies(); + public abstract java.util.Set getLinks(); + public abstract void close(); + public boolean isClosed(){ return false; } + public static Response.ResponseBuilder accepted(){ return null; } + public static Response.ResponseBuilder accepted(Object p0){ return null; } + public static Response.ResponseBuilder created(URI p0){ return null; } + public static Response.ResponseBuilder fromResponse(Response p0){ return null; } + public static Response.ResponseBuilder noContent(){ return null; } + public static Response.ResponseBuilder notAcceptable(java.util.List p0){ return null; } + public static Response.ResponseBuilder notModified(){ return null; } + public static Response.ResponseBuilder notModified(EntityTag p0){ return null; } + public static Response.ResponseBuilder notModified(String p0){ return null; } + public static Response.ResponseBuilder ok(){ return null; } + public static Response.ResponseBuilder ok(Object p0){ return null; } + public static Response.ResponseBuilder ok(Object p0, MediaType p1){ return null; } + public static Response.ResponseBuilder ok(Object p0, String p1){ return null; } + public static Response.ResponseBuilder ok(Object p0, Variant p1){ return null; } + public static Response.ResponseBuilder seeOther(URI p0){ return null; } + public static Response.ResponseBuilder serverError(){ return null; } + public static Response.ResponseBuilder status(Response.Status p0){ return null; } + public static Response.ResponseBuilder status(Response.StatusType p0){ return null; } + public static Response.ResponseBuilder status(int p0){ return null; } + public static Response.ResponseBuilder status(int p0, String p1){ return null; } + public static Response.ResponseBuilder temporaryRedirect(URI p0){ return null; } + static public enum Status + { + ACCEPTED, BAD_GATEWAY, BAD_REQUEST, CONFLICT, CREATED, EXPECTATION_FAILED, FORBIDDEN, FOUND, GATEWAY_TIMEOUT, GONE, HTTP_VERSION_NOT_SUPPORTED, INTERNAL_SERVER_ERROR, LENGTH_REQUIRED, METHOD_NOT_ALLOWED, MOVED_PERMANENTLY, MULTIPLE_CHOICES, NETWORK_AUTHENTICATION_REQUIRED, NOT_ACCEPTABLE, NOT_FOUND, NOT_IMPLEMENTED, NOT_MODIFIED, NO_CONTENT, OK, PARTIAL_CONTENT, PAYMENT_REQUIRED, PERMANENT_REDIRECT, PRECONDITION_FAILED, PRECONDITION_REQUIRED, PROXY_AUTHENTICATION_REQUIRED, REQUESTED_RANGE_NOT_SATISFIABLE, REQUEST_ENTITY_TOO_LARGE, REQUEST_HEADER_FIELDS_TOO_LARGE, REQUEST_TIMEOUT, REQUEST_URI_TOO_LONG, RESET_CONTENT, SEE_OTHER, SERVICE_UNAVAILABLE, TEMPORARY_REDIRECT, TOO_MANY_REQUESTS, UNAUTHORIZED, UNAVAILABLE_FOR_LEGAL_REASONS, UNSUPPORTED_MEDIA_TYPE, USE_PROXY; + private Status() {} + public Response.Status.Family getFamily(){ return null; } + public String getReasonPhrase(){ return null; } + public String toString(){ return null; } + public int getStatusCode(){ return 0; } + public static Response.Status fromStatusCode(int p0){ return null; } + static public enum Family + { + CLIENT_ERROR, INFORMATIONAL, OTHER, REDIRECTION, SERVER_ERROR, SUCCESSFUL; + private Family() {} + public static Response.Status.Family familyOf(int p0){ return null; } + } + } + static public interface StatusType + { + Response.Status.Family getFamily(); + String getReasonPhrase(); + default Response.Status toEnum(){ return null; } + int getStatusCode(); + } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/UriBuilder.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/UriBuilder.java new file mode 100644 index 00000000000..019133cfb89 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/UriBuilder.java @@ -0,0 +1,54 @@ +// Generated automatically from jakarta.ws.rs.core.UriBuilder for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.Link; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Map; + +abstract public class UriBuilder +{ + protected UriBuilder(){} + public abstract String toTemplate(); + public abstract URI build(Object... p0); + public abstract URI build(Object[] p0, boolean p1); + public abstract URI buildFromEncoded(Object... p0); + public abstract URI buildFromEncodedMap(Map p0); + public abstract URI buildFromMap(Map p0); + public abstract URI buildFromMap(Map p0, boolean p1); + public abstract UriBuilder clone(); + public abstract UriBuilder fragment(String p0); + public abstract UriBuilder host(String p0); + public abstract UriBuilder matrixParam(String p0, Object... p1); + public abstract UriBuilder path(Class p0); + public abstract UriBuilder path(Class p0, String p1); + public abstract UriBuilder path(Method p0); + public abstract UriBuilder path(String p0); + public abstract UriBuilder port(int p0); + public abstract UriBuilder queryParam(String p0, Object... p1); + public abstract UriBuilder replaceMatrix(String p0); + public abstract UriBuilder replaceMatrixParam(String p0, Object... p1); + public abstract UriBuilder replacePath(String p0); + public abstract UriBuilder replaceQuery(String p0); + public abstract UriBuilder replaceQueryParam(String p0, Object... p1); + public abstract UriBuilder resolveTemplate(String p0, Object p1); + public abstract UriBuilder resolveTemplate(String p0, Object p1, boolean p2); + public abstract UriBuilder resolveTemplateFromEncoded(String p0, Object p1); + public abstract UriBuilder resolveTemplates(Map p0); + public abstract UriBuilder resolveTemplates(Map p0, boolean p1); + public abstract UriBuilder resolveTemplatesFromEncoded(Map p0); + public abstract UriBuilder scheme(String p0); + public abstract UriBuilder schemeSpecificPart(String p0); + public abstract UriBuilder segment(String... p0); + public abstract UriBuilder uri(String p0); + public abstract UriBuilder uri(URI p0); + public abstract UriBuilder userInfo(String p0); + public static UriBuilder fromLink(Link p0){ return null; } + public static UriBuilder fromMethod(Class p0, String p1){ return null; } + public static UriBuilder fromPath(String p0){ return null; } + public static UriBuilder fromResource(Class p0){ return null; } + public static UriBuilder fromUri(String p0){ return null; } + public static UriBuilder fromUri(URI p0){ return null; } + public static UriBuilder newInstance(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Variant.java b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Variant.java new file mode 100644 index 00000000000..e580c5318ff --- /dev/null +++ b/java/ql/test/stubs/javafx-web/jakarta/ws/rs/core/Variant.java @@ -0,0 +1,36 @@ +// Generated automatically from jakarta.ws.rs.core.Variant for testing purposes + +package jakarta.ws.rs.core; + +import jakarta.ws.rs.core.MediaType; +import java.util.List; +import java.util.Locale; + +public class Variant +{ + protected Variant() {} + abstract static public class VariantListBuilder + { + protected VariantListBuilder(){} + public abstract Variant.VariantListBuilder add(); + public abstract Variant.VariantListBuilder encodings(String... p0); + public abstract Variant.VariantListBuilder languages(Locale... p0); + public abstract Variant.VariantListBuilder mediaTypes(MediaType... p0); + public abstract java.util.List build(); + public static Variant.VariantListBuilder newInstance(){ return null; } + } + public Locale getLanguage(){ return null; } + public MediaType getMediaType(){ return null; } + public String getEncoding(){ return null; } + public String getLanguageString(){ return null; } + public String toString(){ return null; } + public Variant(MediaType p0, Locale p1, String p2){} + public Variant(MediaType p0, String p1, String p2){} + public Variant(MediaType p0, String p1, String p2, String p3){} + public Variant(MediaType p0, String p1, String p2, String p3, String p4){} + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static Variant.VariantListBuilder encodings(String... p0){ return null; } + public static Variant.VariantListBuilder languages(Locale... p0){ return null; } + public static Variant.VariantListBuilder mediaTypes(MediaType... p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/animation/Interpolatable.java b/java/ql/test/stubs/javafx-web/javafx/animation/Interpolatable.java new file mode 100644 index 00000000000..518ddddb556 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/animation/Interpolatable.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.animation.Interpolatable for testing purposes + +package javafx.animation; + + +public interface Interpolatable +{ + T interpolate(T p0, double p1); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/InvalidationListener.java b/java/ql/test/stubs/javafx-web/javafx/beans/InvalidationListener.java new file mode 100644 index 00000000000..71ba5cf74d6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/InvalidationListener.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.InvalidationListener for testing purposes + +package javafx.beans; + +import javafx.beans.Observable; + +public interface InvalidationListener +{ + void invalidated(Observable p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/Observable.java b/java/ql/test/stubs/javafx-web/javafx/beans/Observable.java new file mode 100644 index 00000000000..f8b9e5d6d85 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/Observable.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.beans.Observable for testing purposes + +package javafx.beans; + +import javafx.beans.InvalidationListener; + +public interface Observable +{ + void addListener(InvalidationListener p0); + void removeListener(InvalidationListener p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/Binding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/Binding.java new file mode 100644 index 00000000000..eb119f82920 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/Binding.java @@ -0,0 +1,14 @@ +// Generated automatically from javafx.beans.binding.Binding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.value.ObservableValue; +import javafx.collections.ObservableList; + +public interface Binding extends javafx.beans.value.ObservableValue +{ + ObservableList getDependencies(); + boolean isValid(); + void dispose(); + void invalidate(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanBinding.java new file mode 100644 index 00000000000..3bd08ab5503 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.BooleanBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.Binding; +import javafx.beans.binding.BooleanExpression; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class BooleanBinding extends BooleanExpression implements Binding +{ + protected abstract boolean computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public BooleanBinding(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public final boolean get(){ return false; } + public final boolean isValid(){ return false; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanExpression.java new file mode 100644 index 00000000000..0fc8e4a0300 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/BooleanExpression.java @@ -0,0 +1,24 @@ +// Generated automatically from javafx.beans.binding.BooleanExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.ObjectExpression; +import javafx.beans.binding.StringBinding; +import javafx.beans.value.ObservableBooleanValue; +import javafx.beans.value.ObservableValue; + +abstract public class BooleanExpression implements ObservableBooleanValue +{ + public Boolean getValue(){ return null; } + public BooleanBinding and(ObservableBooleanValue p0){ return null; } + public BooleanBinding isEqualTo(ObservableBooleanValue p0){ return null; } + public BooleanBinding isNotEqualTo(ObservableBooleanValue p0){ return null; } + public BooleanBinding not(){ return null; } + public BooleanBinding or(ObservableBooleanValue p0){ return null; } + public BooleanExpression(){} + public ObjectExpression asObject(){ return null; } + public StringBinding asString(){ return null; } + public static BooleanExpression booleanExpression(ObservableBooleanValue p0){ return null; } + public static BooleanExpression booleanExpression(ObservableValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleBinding.java new file mode 100644 index 00000000000..6e7f925ec38 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.DoubleBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.DoubleExpression; +import javafx.beans.binding.NumberBinding; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class DoubleBinding extends DoubleExpression implements NumberBinding +{ + protected abstract double computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public DoubleBinding(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public final boolean isValid(){ return false; } + public final double get(){ return 0; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleExpression.java new file mode 100644 index 00000000000..530ddb07861 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/DoubleExpression.java @@ -0,0 +1,44 @@ +// Generated automatically from javafx.beans.binding.DoubleExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.DoubleBinding; +import javafx.beans.binding.NumberExpressionBase; +import javafx.beans.binding.ObjectExpression; +import javafx.beans.value.ObservableDoubleValue; +import javafx.beans.value.ObservableNumberValue; +import javafx.beans.value.ObservableValue; + +abstract public class DoubleExpression extends NumberExpressionBase implements ObservableDoubleValue +{ + public Double getValue(){ return null; } + public DoubleBinding add(ObservableNumberValue p0){ return null; } + public DoubleBinding add(double p0){ return null; } + public DoubleBinding add(float p0){ return null; } + public DoubleBinding add(int p0){ return null; } + public DoubleBinding add(long p0){ return null; } + public DoubleBinding divide(ObservableNumberValue p0){ return null; } + public DoubleBinding divide(double p0){ return null; } + public DoubleBinding divide(float p0){ return null; } + public DoubleBinding divide(int p0){ return null; } + public DoubleBinding divide(long p0){ return null; } + public DoubleBinding multiply(ObservableNumberValue p0){ return null; } + public DoubleBinding multiply(double p0){ return null; } + public DoubleBinding multiply(float p0){ return null; } + public DoubleBinding multiply(int p0){ return null; } + public DoubleBinding multiply(long p0){ return null; } + public DoubleBinding negate(){ return null; } + public DoubleBinding subtract(ObservableNumberValue p0){ return null; } + public DoubleBinding subtract(double p0){ return null; } + public DoubleBinding subtract(float p0){ return null; } + public DoubleBinding subtract(int p0){ return null; } + public DoubleBinding subtract(long p0){ return null; } + public DoubleExpression(){} + public ObjectExpression asObject(){ return null; } + public double doubleValue(){ return 0; } + public float floatValue(){ return 0; } + public int intValue(){ return 0; } + public long longValue(){ return 0; } + public static DoubleExpression doubleExpression(javafx.beans.value.ObservableValue p0){ return null; } + public static DoubleExpression doubleExpression(ObservableDoubleValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatBinding.java new file mode 100644 index 00000000000..0db30664dc6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.FloatBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.FloatExpression; +import javafx.beans.binding.NumberBinding; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class FloatBinding extends FloatExpression implements NumberBinding +{ + protected abstract float computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public FloatBinding(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public final boolean isValid(){ return false; } + public final float get(){ return 0; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatExpression.java new file mode 100644 index 00000000000..2aaba3e4034 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/FloatExpression.java @@ -0,0 +1,40 @@ +// Generated automatically from javafx.beans.binding.FloatExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.DoubleBinding; +import javafx.beans.binding.FloatBinding; +import javafx.beans.binding.NumberExpressionBase; +import javafx.beans.binding.ObjectExpression; +import javafx.beans.value.ObservableFloatValue; +import javafx.beans.value.ObservableValue; + +abstract public class FloatExpression extends NumberExpressionBase implements ObservableFloatValue +{ + public DoubleBinding add(double p0){ return null; } + public DoubleBinding divide(double p0){ return null; } + public DoubleBinding multiply(double p0){ return null; } + public DoubleBinding subtract(double p0){ return null; } + public Float getValue(){ return null; } + public FloatBinding add(float p0){ return null; } + public FloatBinding add(int p0){ return null; } + public FloatBinding add(long p0){ return null; } + public FloatBinding divide(float p0){ return null; } + public FloatBinding divide(int p0){ return null; } + public FloatBinding divide(long p0){ return null; } + public FloatBinding multiply(float p0){ return null; } + public FloatBinding multiply(int p0){ return null; } + public FloatBinding multiply(long p0){ return null; } + public FloatBinding negate(){ return null; } + public FloatBinding subtract(float p0){ return null; } + public FloatBinding subtract(int p0){ return null; } + public FloatBinding subtract(long p0){ return null; } + public FloatExpression(){} + public ObjectExpression asObject(){ return null; } + public double doubleValue(){ return 0; } + public float floatValue(){ return 0; } + public int intValue(){ return 0; } + public long longValue(){ return 0; } + public static FloatExpression floatExpression(javafx.beans.value.ObservableValue p0){ return null; } + public static FloatExpression floatExpression(ObservableFloatValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerBinding.java new file mode 100644 index 00000000000..f15f45d9a99 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.IntegerBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.IntegerExpression; +import javafx.beans.binding.NumberBinding; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class IntegerBinding extends IntegerExpression implements NumberBinding +{ + protected abstract int computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public IntegerBinding(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public final boolean isValid(){ return false; } + public final int get(){ return 0; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerExpression.java new file mode 100644 index 00000000000..24fab5ecd60 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/IntegerExpression.java @@ -0,0 +1,42 @@ +// Generated automatically from javafx.beans.binding.IntegerExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.DoubleBinding; +import javafx.beans.binding.FloatBinding; +import javafx.beans.binding.IntegerBinding; +import javafx.beans.binding.LongBinding; +import javafx.beans.binding.NumberExpressionBase; +import javafx.beans.binding.ObjectExpression; +import javafx.beans.value.ObservableIntegerValue; +import javafx.beans.value.ObservableValue; + +abstract public class IntegerExpression extends NumberExpressionBase implements ObservableIntegerValue +{ + public DoubleBinding add(double p0){ return null; } + public DoubleBinding divide(double p0){ return null; } + public DoubleBinding multiply(double p0){ return null; } + public DoubleBinding subtract(double p0){ return null; } + public FloatBinding add(float p0){ return null; } + public FloatBinding divide(float p0){ return null; } + public FloatBinding multiply(float p0){ return null; } + public FloatBinding subtract(float p0){ return null; } + public Integer getValue(){ return null; } + public IntegerBinding add(int p0){ return null; } + public IntegerBinding divide(int p0){ return null; } + public IntegerBinding multiply(int p0){ return null; } + public IntegerBinding negate(){ return null; } + public IntegerBinding subtract(int p0){ return null; } + public IntegerExpression(){} + public LongBinding add(long p0){ return null; } + public LongBinding divide(long p0){ return null; } + public LongBinding multiply(long p0){ return null; } + public LongBinding subtract(long p0){ return null; } + public ObjectExpression asObject(){ return null; } + public double doubleValue(){ return 0; } + public float floatValue(){ return 0; } + public int intValue(){ return 0; } + public long longValue(){ return 0; } + public static IntegerExpression integerExpression(javafx.beans.value.ObservableValue p0){ return null; } + public static IntegerExpression integerExpression(ObservableIntegerValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongBinding.java new file mode 100644 index 00000000000..90c872ddf87 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.LongBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.LongExpression; +import javafx.beans.binding.NumberBinding; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class LongBinding extends LongExpression implements NumberBinding +{ + protected abstract long computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public LongBinding(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public final boolean isValid(){ return false; } + public final long get(){ return 0; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongExpression.java new file mode 100644 index 00000000000..c27444d3243 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/LongExpression.java @@ -0,0 +1,41 @@ +// Generated automatically from javafx.beans.binding.LongExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.DoubleBinding; +import javafx.beans.binding.FloatBinding; +import javafx.beans.binding.LongBinding; +import javafx.beans.binding.NumberExpressionBase; +import javafx.beans.binding.ObjectExpression; +import javafx.beans.value.ObservableLongValue; +import javafx.beans.value.ObservableValue; + +abstract public class LongExpression extends NumberExpressionBase implements ObservableLongValue +{ + public DoubleBinding add(double p0){ return null; } + public DoubleBinding divide(double p0){ return null; } + public DoubleBinding multiply(double p0){ return null; } + public DoubleBinding subtract(double p0){ return null; } + public FloatBinding add(float p0){ return null; } + public FloatBinding divide(float p0){ return null; } + public FloatBinding multiply(float p0){ return null; } + public FloatBinding subtract(float p0){ return null; } + public Long getValue(){ return null; } + public LongBinding add(int p0){ return null; } + public LongBinding add(long p0){ return null; } + public LongBinding divide(int p0){ return null; } + public LongBinding divide(long p0){ return null; } + public LongBinding multiply(int p0){ return null; } + public LongBinding multiply(long p0){ return null; } + public LongBinding negate(){ return null; } + public LongBinding subtract(int p0){ return null; } + public LongBinding subtract(long p0){ return null; } + public LongExpression(){} + public ObjectExpression asObject(){ return null; } + public double doubleValue(){ return 0; } + public float floatValue(){ return 0; } + public int intValue(){ return 0; } + public long longValue(){ return 0; } + public static LongExpression longExpression(javafx.beans.value.ObservableValue p0){ return null; } + public static LongExpression longExpression(ObservableLongValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberBinding.java new file mode 100644 index 00000000000..893219bb85c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberBinding.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.binding.NumberBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.Binding; +import javafx.beans.binding.NumberExpression; + +public interface NumberBinding extends Binding, NumberExpression +{ +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpression.java new file mode 100644 index 00000000000..e6c2a118a5c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpression.java @@ -0,0 +1,73 @@ +// Generated automatically from javafx.beans.binding.NumberExpression for testing purposes + +package javafx.beans.binding; + +import java.util.Locale; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.NumberBinding; +import javafx.beans.binding.StringBinding; +import javafx.beans.value.ObservableNumberValue; + +public interface NumberExpression extends ObservableNumberValue +{ + BooleanBinding greaterThan(ObservableNumberValue p0); + BooleanBinding greaterThan(double p0); + BooleanBinding greaterThan(float p0); + BooleanBinding greaterThan(int p0); + BooleanBinding greaterThan(long p0); + BooleanBinding greaterThanOrEqualTo(ObservableNumberValue p0); + BooleanBinding greaterThanOrEqualTo(double p0); + BooleanBinding greaterThanOrEqualTo(float p0); + BooleanBinding greaterThanOrEqualTo(int p0); + BooleanBinding greaterThanOrEqualTo(long p0); + BooleanBinding isEqualTo(ObservableNumberValue p0); + BooleanBinding isEqualTo(ObservableNumberValue p0, double p1); + BooleanBinding isEqualTo(double p0, double p1); + BooleanBinding isEqualTo(float p0, double p1); + BooleanBinding isEqualTo(int p0); + BooleanBinding isEqualTo(int p0, double p1); + BooleanBinding isEqualTo(long p0); + BooleanBinding isEqualTo(long p0, double p1); + BooleanBinding isNotEqualTo(ObservableNumberValue p0); + BooleanBinding isNotEqualTo(ObservableNumberValue p0, double p1); + BooleanBinding isNotEqualTo(double p0, double p1); + BooleanBinding isNotEqualTo(float p0, double p1); + BooleanBinding isNotEqualTo(int p0); + BooleanBinding isNotEqualTo(int p0, double p1); + BooleanBinding isNotEqualTo(long p0); + BooleanBinding isNotEqualTo(long p0, double p1); + BooleanBinding lessThan(ObservableNumberValue p0); + BooleanBinding lessThan(double p0); + BooleanBinding lessThan(float p0); + BooleanBinding lessThan(int p0); + BooleanBinding lessThan(long p0); + BooleanBinding lessThanOrEqualTo(ObservableNumberValue p0); + BooleanBinding lessThanOrEqualTo(double p0); + BooleanBinding lessThanOrEqualTo(float p0); + BooleanBinding lessThanOrEqualTo(int p0); + BooleanBinding lessThanOrEqualTo(long p0); + NumberBinding add(ObservableNumberValue p0); + NumberBinding add(double p0); + NumberBinding add(float p0); + NumberBinding add(int p0); + NumberBinding add(long p0); + NumberBinding divide(ObservableNumberValue p0); + NumberBinding divide(double p0); + NumberBinding divide(float p0); + NumberBinding divide(int p0); + NumberBinding divide(long p0); + NumberBinding multiply(ObservableNumberValue p0); + NumberBinding multiply(double p0); + NumberBinding multiply(float p0); + NumberBinding multiply(int p0); + NumberBinding multiply(long p0); + NumberBinding negate(); + NumberBinding subtract(ObservableNumberValue p0); + NumberBinding subtract(double p0); + NumberBinding subtract(float p0); + NumberBinding subtract(int p0); + NumberBinding subtract(long p0); + StringBinding asString(); + StringBinding asString(Locale p0, String p1); + StringBinding asString(String p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpressionBase.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpressionBase.java new file mode 100644 index 00000000000..5cce40064d1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/NumberExpressionBase.java @@ -0,0 +1,59 @@ +// Generated automatically from javafx.beans.binding.NumberExpressionBase for testing purposes + +package javafx.beans.binding; + +import java.util.Locale; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.NumberBinding; +import javafx.beans.binding.NumberExpression; +import javafx.beans.binding.StringBinding; +import javafx.beans.value.ObservableNumberValue; + +abstract public class NumberExpressionBase implements NumberExpression +{ + public BooleanBinding greaterThan(ObservableNumberValue p0){ return null; } + public BooleanBinding greaterThan(double p0){ return null; } + public BooleanBinding greaterThan(float p0){ return null; } + public BooleanBinding greaterThan(int p0){ return null; } + public BooleanBinding greaterThan(long p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(ObservableNumberValue p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(double p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(float p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(int p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(long p0){ return null; } + public BooleanBinding isEqualTo(ObservableNumberValue p0){ return null; } + public BooleanBinding isEqualTo(ObservableNumberValue p0, double p1){ return null; } + public BooleanBinding isEqualTo(double p0, double p1){ return null; } + public BooleanBinding isEqualTo(float p0, double p1){ return null; } + public BooleanBinding isEqualTo(int p0){ return null; } + public BooleanBinding isEqualTo(int p0, double p1){ return null; } + public BooleanBinding isEqualTo(long p0){ return null; } + public BooleanBinding isEqualTo(long p0, double p1){ return null; } + public BooleanBinding isNotEqualTo(ObservableNumberValue p0){ return null; } + public BooleanBinding isNotEqualTo(ObservableNumberValue p0, double p1){ return null; } + public BooleanBinding isNotEqualTo(double p0, double p1){ return null; } + public BooleanBinding isNotEqualTo(float p0, double p1){ return null; } + public BooleanBinding isNotEqualTo(int p0){ return null; } + public BooleanBinding isNotEqualTo(int p0, double p1){ return null; } + public BooleanBinding isNotEqualTo(long p0){ return null; } + public BooleanBinding isNotEqualTo(long p0, double p1){ return null; } + public BooleanBinding lessThan(ObservableNumberValue p0){ return null; } + public BooleanBinding lessThan(double p0){ return null; } + public BooleanBinding lessThan(float p0){ return null; } + public BooleanBinding lessThan(int p0){ return null; } + public BooleanBinding lessThan(long p0){ return null; } + public BooleanBinding lessThanOrEqualTo(ObservableNumberValue p0){ return null; } + public BooleanBinding lessThanOrEqualTo(double p0){ return null; } + public BooleanBinding lessThanOrEqualTo(float p0){ return null; } + public BooleanBinding lessThanOrEqualTo(int p0){ return null; } + public BooleanBinding lessThanOrEqualTo(long p0){ return null; } + public NumberBinding add(ObservableNumberValue p0){ return null; } + public NumberBinding divide(ObservableNumberValue p0){ return null; } + public NumberBinding multiply(ObservableNumberValue p0){ return null; } + public NumberBinding subtract(ObservableNumberValue p0){ return null; } + public NumberExpressionBase(){} + public StringBinding asString(){ return null; } + public StringBinding asString(Locale p0, String p1){ return null; } + public StringBinding asString(String p0){ return null; } + public static NumberExpressionBase numberExpression(ObservableNumberValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/ObjectExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/ObjectExpression.java new file mode 100644 index 00000000000..de7a09b8113 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/ObjectExpression.java @@ -0,0 +1,24 @@ +// Generated automatically from javafx.beans.binding.ObjectExpression for testing purposes + +package javafx.beans.binding; + +import java.util.Locale; +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.StringBinding; +import javafx.beans.value.ObservableObjectValue; + +abstract public class ObjectExpression implements javafx.beans.value.ObservableObjectValue +{ + public BooleanBinding isEqualTo(Object p0){ return null; } + public BooleanBinding isEqualTo(ObservableObjectValue p0){ return null; } + public BooleanBinding isNotEqualTo(Object p0){ return null; } + public BooleanBinding isNotEqualTo(ObservableObjectValue p0){ return null; } + public BooleanBinding isNotNull(){ return null; } + public BooleanBinding isNull(){ return null; } + public ObjectExpression(){} + public StringBinding asString(){ return null; } + public StringBinding asString(Locale p0, String p1){ return null; } + public StringBinding asString(String p0){ return null; } + public T getValue(){ return null; } + public static javafx.beans.binding.ObjectExpression objectExpression(javafx.beans.value.ObservableObjectValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringBinding.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringBinding.java new file mode 100644 index 00000000000..bd2a844ff79 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringBinding.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.beans.binding.StringBinding for testing purposes + +package javafx.beans.binding; + +import javafx.beans.InvalidationListener; +import javafx.beans.Observable; +import javafx.beans.binding.Binding; +import javafx.beans.binding.StringExpression; +import javafx.beans.value.ChangeListener; +import javafx.collections.ObservableList; + +abstract public class StringBinding extends StringExpression implements Binding +{ + protected abstract String computeValue(); + protected final void bind(Observable... p0){} + protected final void unbind(Observable... p0){} + protected void onInvalidating(){} + public ObservableList getDependencies(){ return null; } + public String toString(){ return null; } + public StringBinding(){} + public final String get(){ return null; } + public final boolean isValid(){ return false; } + public final void invalidate(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void dispose(){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringExpression.java b/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringExpression.java new file mode 100644 index 00000000000..4d7d53ec5b4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/binding/StringExpression.java @@ -0,0 +1,38 @@ +// Generated automatically from javafx.beans.binding.StringExpression for testing purposes + +package javafx.beans.binding; + +import javafx.beans.binding.BooleanBinding; +import javafx.beans.binding.IntegerBinding; +import javafx.beans.value.ObservableStringValue; +import javafx.beans.value.ObservableValue; + +abstract public class StringExpression implements ObservableStringValue +{ + public BooleanBinding greaterThan(ObservableStringValue p0){ return null; } + public BooleanBinding greaterThan(String p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(ObservableStringValue p0){ return null; } + public BooleanBinding greaterThanOrEqualTo(String p0){ return null; } + public BooleanBinding isEmpty(){ return null; } + public BooleanBinding isEqualTo(ObservableStringValue p0){ return null; } + public BooleanBinding isEqualTo(String p0){ return null; } + public BooleanBinding isEqualToIgnoreCase(ObservableStringValue p0){ return null; } + public BooleanBinding isEqualToIgnoreCase(String p0){ return null; } + public BooleanBinding isNotEmpty(){ return null; } + public BooleanBinding isNotEqualTo(ObservableStringValue p0){ return null; } + public BooleanBinding isNotEqualTo(String p0){ return null; } + public BooleanBinding isNotEqualToIgnoreCase(ObservableStringValue p0){ return null; } + public BooleanBinding isNotEqualToIgnoreCase(String p0){ return null; } + public BooleanBinding isNotNull(){ return null; } + public BooleanBinding isNull(){ return null; } + public BooleanBinding lessThan(ObservableStringValue p0){ return null; } + public BooleanBinding lessThan(String p0){ return null; } + public BooleanBinding lessThanOrEqualTo(ObservableStringValue p0){ return null; } + public BooleanBinding lessThanOrEqualTo(String p0){ return null; } + public IntegerBinding length(){ return null; } + public String getValue(){ return null; } + public StringExpression concat(Object p0){ return null; } + public StringExpression(){} + public final String getValueSafe(){ return null; } + public static StringExpression stringExpression(ObservableValue p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/BooleanProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/BooleanProperty.java new file mode 100644 index 00000000000..88dd6f25909 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/BooleanProperty.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.beans.property.BooleanProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.Property; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.value.WritableBooleanValue; + +abstract public class BooleanProperty extends ReadOnlyBooleanProperty implements Property, WritableBooleanValue +{ + public BooleanProperty(){} + public ObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static BooleanProperty booleanProperty(Property p0){ return null; } + public void bindBidirectional(Property p0){} + public void setValue(Boolean p0){} + public void unbindBidirectional(Property p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/DoubleProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/DoubleProperty.java new file mode 100644 index 00000000000..e69c881f78a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/DoubleProperty.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.beans.property.DoubleProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.Property; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.value.WritableDoubleValue; + +abstract public class DoubleProperty extends ReadOnlyDoubleProperty implements Property, WritableDoubleValue +{ + public DoubleProperty(){} + public ObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static DoubleProperty doubleProperty(Property p0){ return null; } + public void bindBidirectional(Property p0){} + public void setValue(Number p0){} + public void unbindBidirectional(Property p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/IntegerProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/IntegerProperty.java new file mode 100644 index 00000000000..d33c8230365 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/IntegerProperty.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.beans.property.IntegerProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.Property; +import javafx.beans.property.ReadOnlyIntegerProperty; +import javafx.beans.value.WritableIntegerValue; + +abstract public class IntegerProperty extends ReadOnlyIntegerProperty implements Property, WritableIntegerValue +{ + public IntegerProperty(){} + public ObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static IntegerProperty integerProperty(Property p0){ return null; } + public void bindBidirectional(Property p0){} + public void setValue(Number p0){} + public void unbindBidirectional(Property p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ObjectProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ObjectProperty.java new file mode 100644 index 00000000000..56db4fb7af0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ObjectProperty.java @@ -0,0 +1,16 @@ +// Generated automatically from javafx.beans.property.ObjectProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.property.Property; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.value.WritableObjectValue; + +abstract public class ObjectProperty extends ReadOnlyObjectProperty implements WritableObjectValue, javafx.beans.property.Property +{ + public ObjectProperty(){} + public String toString(){ return null; } + public void bindBidirectional(javafx.beans.property.Property p0){} + public void setValue(T p0){} + public void unbindBidirectional(javafx.beans.property.Property p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/Property.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/Property.java new file mode 100644 index 00000000000..13f3b3e2c4b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/Property.java @@ -0,0 +1,16 @@ +// Generated automatically from javafx.beans.property.Property for testing purposes + +package javafx.beans.property; + +import javafx.beans.property.ReadOnlyProperty; +import javafx.beans.value.ObservableValue; +import javafx.beans.value.WritableValue; + +public interface Property extends javafx.beans.property.ReadOnlyProperty, javafx.beans.value.WritableValue +{ + boolean isBound(); + void bind(javafx.beans.value.ObservableValue p0); + void bindBidirectional(Property p0); + void unbind(); + void unbindBidirectional(Property p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanProperty.java new file mode 100644 index 00000000000..d18dde7c3d2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanProperty.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.beans.property.ReadOnlyBooleanProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.binding.BooleanExpression; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyProperty; + +abstract public class ReadOnlyBooleanProperty extends BooleanExpression implements ReadOnlyProperty +{ + public ReadOnlyBooleanProperty(){} + public ReadOnlyObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static ReadOnlyBooleanProperty readOnlyBooleanProperty(ReadOnlyProperty p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanPropertyBase.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanPropertyBase.java new file mode 100644 index 00000000000..aaba27ff4bc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyBooleanPropertyBase.java @@ -0,0 +1,17 @@ +// Generated automatically from javafx.beans.property.ReadOnlyBooleanPropertyBase for testing purposes + +package javafx.beans.property; + +import javafx.beans.InvalidationListener; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.value.ChangeListener; + +abstract public class ReadOnlyBooleanPropertyBase extends ReadOnlyBooleanProperty +{ + protected void fireValueChangedEvent(){} + public ReadOnlyBooleanPropertyBase(){} + public void addListener(ChangeListener p0){} + public void addListener(InvalidationListener p0){} + public void removeListener(ChangeListener p0){} + public void removeListener(InvalidationListener p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyDoubleProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyDoubleProperty.java new file mode 100644 index 00000000000..f05c2edb588 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyDoubleProperty.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.beans.property.ReadOnlyDoubleProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.binding.DoubleExpression; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyProperty; + +abstract public class ReadOnlyDoubleProperty extends DoubleExpression implements ReadOnlyProperty +{ + public ReadOnlyDoubleProperty(){} + public ReadOnlyObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static ReadOnlyDoubleProperty readOnlyDoubleProperty(javafx.beans.property.ReadOnlyProperty p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyIntegerProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyIntegerProperty.java new file mode 100644 index 00000000000..2d65e925e07 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyIntegerProperty.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.beans.property.ReadOnlyIntegerProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.binding.IntegerExpression; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyProperty; + +abstract public class ReadOnlyIntegerProperty extends IntegerExpression implements ReadOnlyProperty +{ + public ReadOnlyIntegerProperty(){} + public ReadOnlyObjectProperty asObject(){ return null; } + public String toString(){ return null; } + public static ReadOnlyIntegerProperty readOnlyIntegerProperty(javafx.beans.property.ReadOnlyProperty p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyObjectProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyObjectProperty.java new file mode 100644 index 00000000000..dc4367f6869 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyObjectProperty.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.beans.property.ReadOnlyObjectProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.binding.ObjectExpression; +import javafx.beans.property.ReadOnlyProperty; + +abstract public class ReadOnlyObjectProperty extends javafx.beans.binding.ObjectExpression implements javafx.beans.property.ReadOnlyProperty +{ + public ReadOnlyObjectProperty(){} + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyProperty.java new file mode 100644 index 00000000000..2122b130fb7 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyProperty.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.beans.property.ReadOnlyProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.value.ObservableValue; + +public interface ReadOnlyProperty extends javafx.beans.value.ObservableValue +{ + Object getBean(); + String getName(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyStringProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyStringProperty.java new file mode 100644 index 00000000000..2a245ee1b0a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/ReadOnlyStringProperty.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.beans.property.ReadOnlyStringProperty for testing purposes + +package javafx.beans.property; + +import javafx.beans.binding.StringExpression; +import javafx.beans.property.ReadOnlyProperty; + +abstract public class ReadOnlyStringProperty extends StringExpression implements ReadOnlyProperty +{ + public ReadOnlyStringProperty(){} + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/property/StringProperty.java b/java/ql/test/stubs/javafx-web/javafx/beans/property/StringProperty.java new file mode 100644 index 00000000000..2b8702bbbf4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/property/StringProperty.java @@ -0,0 +1,21 @@ +// Generated automatically from javafx.beans.property.StringProperty for testing purposes + +package javafx.beans.property; + +import java.text.Format; +import javafx.beans.property.Property; +import javafx.beans.property.ReadOnlyStringProperty; +import javafx.beans.value.WritableStringValue; +import javafx.util.StringConverter; + +abstract public class StringProperty extends ReadOnlyStringProperty implements Property, WritableStringValue +{ + public void bindBidirectional(javafx.beans.property.Property p0, StringConverter p1){} + public String toString(){ return null; } + public StringProperty(){} + public void bindBidirectional(Property p0, Format p1){} + public void bindBidirectional(Property p0){} + public void setValue(String p0){} + public void unbindBidirectional(Object p0){} + public void unbindBidirectional(Property p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ChangeListener.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ChangeListener.java new file mode 100644 index 00000000000..922672e76a3 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ChangeListener.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ChangeListener for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableValue; + +public interface ChangeListener +{ + void changed(javafx.beans.value.ObservableValue p0, T p1, T p2); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableBooleanValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableBooleanValue.java new file mode 100644 index 00000000000..aa0f987cdd0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableBooleanValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableBooleanValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableValue; + +public interface ObservableBooleanValue extends ObservableValue +{ + boolean get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableDoubleValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableDoubleValue.java new file mode 100644 index 00000000000..687e53a65f9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableDoubleValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableDoubleValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableNumberValue; + +public interface ObservableDoubleValue extends ObservableNumberValue +{ + double get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableFloatValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableFloatValue.java new file mode 100644 index 00000000000..a397d00e9be --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableFloatValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableFloatValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableNumberValue; + +public interface ObservableFloatValue extends ObservableNumberValue +{ + float get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableIntegerValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableIntegerValue.java new file mode 100644 index 00000000000..597d2f1a8cc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableIntegerValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableIntegerValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableNumberValue; + +public interface ObservableIntegerValue extends ObservableNumberValue +{ + int get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableLongValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableLongValue.java new file mode 100644 index 00000000000..d665fb71c53 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableLongValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableLongValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableNumberValue; + +public interface ObservableLongValue extends ObservableNumberValue +{ + long get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableNumberValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableNumberValue.java new file mode 100644 index 00000000000..036cabc0d81 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableNumberValue.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.beans.value.ObservableNumberValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableValue; + +public interface ObservableNumberValue extends ObservableValue +{ + double doubleValue(); + float floatValue(); + int intValue(); + long longValue(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableObjectValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableObjectValue.java new file mode 100644 index 00000000000..cdb260b1c2c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableObjectValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.ObservableObjectValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableValue; + +public interface ObservableObjectValue extends javafx.beans.value.ObservableValue +{ + T get(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableStringValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableStringValue.java new file mode 100644 index 00000000000..a7152ace61d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableStringValue.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.beans.value.ObservableStringValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.ObservableObjectValue; + +public interface ObservableStringValue extends ObservableObjectValue +{ +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableValue.java new file mode 100644 index 00000000000..fcfbe2e0ee6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/ObservableValue.java @@ -0,0 +1,18 @@ +// Generated automatically from javafx.beans.value.ObservableValue for testing purposes + +package javafx.beans.value; + +import java.util.function.Function; +import javafx.beans.Observable; +import javafx.beans.value.ChangeListener; + +public interface ObservableValue extends Observable +{ + T getValue(); + default javafx.beans.value.ObservableValue flatMap(java.util.function.Function> p0){ return null; } + default javafx.beans.value.ObservableValue map(java.util.function.Function p0){ return null; } + default ObservableValue orElse(T p0){ return null; } + default ObservableValue when(ObservableValue p0){ return null; } + void addListener(javafx.beans.value.ChangeListener p0); + void removeListener(javafx.beans.value.ChangeListener p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableBooleanValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableBooleanValue.java new file mode 100644 index 00000000000..f26fc72ee96 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableBooleanValue.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.beans.value.WritableBooleanValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableValue; + +public interface WritableBooleanValue extends WritableValue +{ + boolean get(); + void set(boolean p0); + void setValue(Boolean p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableDoubleValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableDoubleValue.java new file mode 100644 index 00000000000..c44f6e2b3d3 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableDoubleValue.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.beans.value.WritableDoubleValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableNumberValue; + +public interface WritableDoubleValue extends WritableNumberValue +{ + double get(); + void set(double p0); + void setValue(Number p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableIntegerValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableIntegerValue.java new file mode 100644 index 00000000000..44348dc480f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableIntegerValue.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.beans.value.WritableIntegerValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableNumberValue; + +public interface WritableIntegerValue extends WritableNumberValue +{ + int get(); + void set(int p0); + void setValue(Number p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableNumberValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableNumberValue.java new file mode 100644 index 00000000000..b063a159332 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableNumberValue.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.beans.value.WritableNumberValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableValue; + +public interface WritableNumberValue extends WritableValue +{ +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableObjectValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableObjectValue.java new file mode 100644 index 00000000000..d5dc3b167cf --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableObjectValue.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.beans.value.WritableObjectValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableValue; + +public interface WritableObjectValue extends javafx.beans.value.WritableValue +{ + T get(); + void set(T p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableStringValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableStringValue.java new file mode 100644 index 00000000000..fe0c3ebf1f2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableStringValue.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.beans.value.WritableStringValue for testing purposes + +package javafx.beans.value; + +import javafx.beans.value.WritableObjectValue; + +public interface WritableStringValue extends WritableObjectValue +{ +} diff --git a/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableValue.java b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableValue.java new file mode 100644 index 00000000000..cdc3fdd3329 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/beans/value/WritableValue.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.beans.value.WritableValue for testing purposes + +package javafx.beans.value; + + +public interface WritableValue +{ + T getValue(); + void setValue(T p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/ListChangeListener.java b/java/ql/test/stubs/javafx-web/javafx/collections/ListChangeListener.java new file mode 100644 index 00000000000..8eb4100f286 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/ListChangeListener.java @@ -0,0 +1,32 @@ +// Generated automatically from javafx.collections.ListChangeListener for testing purposes + +package javafx.collections; + +import java.util.List; +import javafx.collections.ObservableList; + +public interface ListChangeListener +{ + abstract static public class Change + { + protected Change() {} + protected abstract int[] getPermutation(); + public Change(javafx.collections.ObservableList p0){} + public abstract boolean next(); + public abstract int getFrom(); + public abstract int getTo(); + public abstract java.util.List getRemoved(); + public abstract void reset(); + public boolean wasAdded(){ return false; } + public boolean wasPermutated(){ return false; } + public boolean wasRemoved(){ return false; } + public boolean wasReplaced(){ return false; } + public boolean wasUpdated(){ return false; } + public int getAddedSize(){ return 0; } + public int getPermutation(int p0){ return 0; } + public int getRemovedSize(){ return 0; } + public java.util.List getAddedSubList(){ return null; } + public javafx.collections.ObservableList getList(){ return null; } + } + void onChanged(ListChangeListener.Change p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/MapChangeListener.java b/java/ql/test/stubs/javafx-web/javafx/collections/MapChangeListener.java new file mode 100644 index 00000000000..cd7c5bd60c2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/MapChangeListener.java @@ -0,0 +1,21 @@ +// Generated automatically from javafx.collections.MapChangeListener for testing purposes + +package javafx.collections; + +import javafx.collections.ObservableMap; + +public interface MapChangeListener +{ + abstract static public class Change + { + protected Change() {} + public Change(ObservableMap p0){} + public ObservableMap getMap(){ return null; } + public abstract K getKey(); + public abstract V getValueAdded(); + public abstract V getValueRemoved(); + public abstract boolean wasAdded(); + public abstract boolean wasRemoved(); + } + void onChanged(MapChangeListener.Change p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/ObservableList.java b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableList.java new file mode 100644 index 00000000000..2cbfcd07770 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableList.java @@ -0,0 +1,27 @@ +// Generated automatically from javafx.collections.ObservableList for testing purposes + +package javafx.collections; + +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.function.Predicate; +import javafx.beans.Observable; +import javafx.collections.ListChangeListener; +import javafx.collections.transformation.FilteredList; +import javafx.collections.transformation.SortedList; + +public interface ObservableList extends Observable, java.util.List +{ + boolean addAll(E... p0); + boolean removeAll(E... p0); + boolean retainAll(E... p0); + boolean setAll(E... p0); + boolean setAll(java.util.Collection p0); + default javafx.collections.transformation.FilteredList filtered(java.util.function.Predicate p0){ return null; } + default javafx.collections.transformation.SortedList sorted(){ return null; } + default javafx.collections.transformation.SortedList sorted(java.util.Comparator p0){ return null; } + void addListener(javafx.collections.ListChangeListener p0); + void remove(int p0, int p1); + void removeListener(javafx.collections.ListChangeListener p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/ObservableListBase.java b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableListBase.java new file mode 100644 index 00000000000..085ffbf424f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableListBase.java @@ -0,0 +1,36 @@ +// Generated automatically from javafx.collections.ObservableListBase for testing purposes + +package javafx.collections; + +import java.util.AbstractList; +import java.util.Collection; +import java.util.List; +import javafx.beans.InvalidationListener; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; + +abstract public class ObservableListBase extends java.util.AbstractList implements javafx.collections.ObservableList +{ + protected final boolean hasListeners(){ return false; } + protected final void beginChange(){} + protected final void endChange(){} + protected final void fireChange(ListChangeListener.Change p0){} + protected final void nextAdd(int p0, int p1){} + protected final void nextPermutation(int p0, int p1, int[] p2){} + protected final void nextRemove(int p0, E p1){} + protected final void nextRemove(int p0, java.util.List p1){} + protected final void nextReplace(int p0, int p1, java.util.List p2){} + protected final void nextSet(int p0, E p1){} + protected final void nextUpdate(int p0){} + public ObservableListBase(){} + public boolean addAll(E... p0){ return false; } + public boolean removeAll(E... p0){ return false; } + public boolean retainAll(E... p0){ return false; } + public boolean setAll(E... p0){ return false; } + public boolean setAll(java.util.Collection p0){ return false; } + public final void addListener(InvalidationListener p0){} + public final void addListener(javafx.collections.ListChangeListener p0){} + public final void removeListener(InvalidationListener p0){} + public final void removeListener(javafx.collections.ListChangeListener p0){} + public void remove(int p0, int p1){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/ObservableMap.java b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableMap.java new file mode 100644 index 00000000000..c2d059f8f28 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableMap.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.collections.ObservableMap for testing purposes + +package javafx.collections; + +import java.util.Map; +import javafx.beans.Observable; +import javafx.collections.MapChangeListener; + +public interface ObservableMap extends Observable, java.util.Map +{ + void addListener(MapChangeListener p0); + void removeListener(MapChangeListener p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/ObservableSet.java b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableSet.java new file mode 100644 index 00000000000..49cc9e6a214 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/ObservableSet.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.collections.ObservableSet for testing purposes + +package javafx.collections; + +import java.util.Set; +import javafx.beans.Observable; +import javafx.collections.SetChangeListener; + +public interface ObservableSet extends Observable, java.util.Set +{ + void addListener(SetChangeListener p0); + void removeListener(SetChangeListener p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/SetChangeListener.java b/java/ql/test/stubs/javafx-web/javafx/collections/SetChangeListener.java new file mode 100644 index 00000000000..0168ef4d147 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/SetChangeListener.java @@ -0,0 +1,20 @@ +// Generated automatically from javafx.collections.SetChangeListener for testing purposes + +package javafx.collections; + +import javafx.collections.ObservableSet; + +public interface SetChangeListener +{ + abstract static public class Change + { + protected Change() {} + public Change(ObservableSet p0){} + public ObservableSet getSet(){ return null; } + public abstract E getElementAdded(); + public abstract E getElementRemoved(); + public abstract boolean wasAdded(); + public abstract boolean wasRemoved(); + } + void onChanged(SetChangeListener.Change p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/transformation/FilteredList.java b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/FilteredList.java new file mode 100644 index 00000000000..ee83a561cff --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/FilteredList.java @@ -0,0 +1,24 @@ +// Generated automatically from javafx.collections.transformation.FilteredList for testing purposes + +package javafx.collections.transformation; + +import java.util.function.Predicate; +import javafx.beans.property.ObjectProperty; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.transformation.TransformationList; + +public class FilteredList extends javafx.collections.transformation.TransformationList +{ + protected FilteredList() {} + protected void sourceChanged(ListChangeListener.Change p0){} + public E get(int p0){ return null; } + public FilteredList(javafx.collections.ObservableList p0){} + public FilteredList(javafx.collections.ObservableList p0, java.util.function.Predicate p1){} + public final ObjectProperty> predicateProperty(){ return null; } + public final java.util.function.Predicate getPredicate(){ return null; } + public final void setPredicate(java.util.function.Predicate p0){} + public int getSourceIndex(int p0){ return 0; } + public int getViewIndex(int p0){ return 0; } + public int size(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/transformation/SortedList.java b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/SortedList.java new file mode 100644 index 00000000000..87c183fbfed --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/SortedList.java @@ -0,0 +1,24 @@ +// Generated automatically from javafx.collections.transformation.SortedList for testing purposes + +package javafx.collections.transformation; + +import java.util.Comparator; +import javafx.beans.property.ObjectProperty; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.transformation.TransformationList; + +public class SortedList extends javafx.collections.transformation.TransformationList +{ + protected SortedList() {} + protected void sourceChanged(ListChangeListener.Change p0){} + public E get(int p0){ return null; } + public SortedList(javafx.collections.ObservableList p0){} + public SortedList(javafx.collections.ObservableList p0, java.util.Comparator p1){} + public final ObjectProperty> comparatorProperty(){ return null; } + public final java.util.Comparator getComparator(){ return null; } + public final void setComparator(java.util.Comparator p0){} + public int getSourceIndex(int p0){ return 0; } + public int getViewIndex(int p0){ return 0; } + public int size(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/collections/transformation/TransformationList.java b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/TransformationList.java new file mode 100644 index 00000000000..541fac5ff92 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/collections/transformation/TransformationList.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.collections.transformation.TransformationList for testing purposes + +package javafx.collections.transformation; + +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; +import javafx.collections.ObservableListBase; + +abstract public class TransformationList extends javafx.collections.ObservableListBase +{ + protected TransformationList() {} + protected TransformationList(ObservableList p0){} + protected abstract void sourceChanged(ListChangeListener.Change p0); + public abstract int getSourceIndex(int p0); + public abstract int getViewIndex(int p0); + public final ObservableList getSource(){ return null; } + public final boolean isInTransformationChain(ObservableList p0){ return false; } + public final int getSourceIndexFor(ObservableList p0, int p1){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/concurrent/Worker.java b/java/ql/test/stubs/javafx-web/javafx/concurrent/Worker.java new file mode 100644 index 00000000000..f354eaf0cac --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/concurrent/Worker.java @@ -0,0 +1,36 @@ +// Generated automatically from javafx.concurrent.Worker for testing purposes + +package javafx.concurrent; + +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyStringProperty; + +public interface Worker +{ + ReadOnlyBooleanProperty runningProperty(); + ReadOnlyDoubleProperty progressProperty(); + ReadOnlyDoubleProperty totalWorkProperty(); + ReadOnlyDoubleProperty workDoneProperty(); + ReadOnlyObjectProperty exceptionProperty(); + ReadOnlyObjectProperty valueProperty(); + ReadOnlyObjectProperty stateProperty(); + ReadOnlyStringProperty messageProperty(); + ReadOnlyStringProperty titleProperty(); + String getMessage(); + String getTitle(); + Throwable getException(); + V getValue(); + Worker.State getState(); + boolean cancel(); + boolean isRunning(); + double getProgress(); + double getTotalWork(); + double getWorkDone(); + static public enum State + { + CANCELLED, FAILED, READY, RUNNING, SCHEDULED, SUCCEEDED; + private State() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/CssMetaData.java b/java/ql/test/stubs/javafx-web/javafx/css/CssMetaData.java new file mode 100644 index 00000000000..04f4ee2ed3d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/CssMetaData.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.css.CssMetaData for testing purposes + +package javafx.css; + +import java.util.List; +import javafx.css.StyleConverter; +import javafx.css.StyleOrigin; +import javafx.css.Styleable; +import javafx.css.StyleableProperty; + +abstract public class CssMetaData +{ + protected CssMetaData() {} + protected CssMetaData(String p0, StyleConverter p1){} + protected CssMetaData(String p0, StyleConverter p1, V p2){} + protected CssMetaData(String p0, StyleConverter p1, V p2, boolean p3){} + protected CssMetaData(String p0, StyleConverter p1, V p2, boolean p3, List> p4){} + public String toString(){ return null; } + public V getInitialValue(S p0){ return null; } + public abstract StyleableProperty getStyleableProperty(S p0); + public abstract boolean isSettable(S p0); + public boolean equals(Object p0){ return false; } + public final List> getSubProperties(){ return null; } + public final String getProperty(){ return null; } + public final StyleConverter getConverter(){ return null; } + public final boolean isInherits(){ return false; } + public int hashCode(){ return 0; } + public void set(S p0, V p1, StyleOrigin p2){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/ParsedValue.java b/java/ql/test/stubs/javafx-web/javafx/css/ParsedValue.java new file mode 100644 index 00000000000..c84b4c23be2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/ParsedValue.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.css.ParsedValue for testing purposes + +package javafx.css; + +import javafx.css.StyleConverter; +import javafx.scene.text.Font; + +public class ParsedValue +{ + protected ParsedValue() {} + protected ParsedValue(V p0, StyleConverter p1){} + protected final StyleConverter converter = null; + protected final V value = null; + public T convert(Font p0){ return null; } + public boolean isContainsLookups(){ return false; } + public boolean isLookup(){ return false; } + public final StyleConverter getConverter(){ return null; } + public final V getValue(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/PseudoClass.java b/java/ql/test/stubs/javafx-web/javafx/css/PseudoClass.java new file mode 100644 index 00000000000..b82f84e2c90 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/PseudoClass.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.css.PseudoClass for testing purposes + +package javafx.css; + + +abstract public class PseudoClass +{ + public PseudoClass(){} + public abstract String getPseudoClassName(); + public static PseudoClass getPseudoClass(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/StyleConverter.java b/java/ql/test/stubs/javafx-web/javafx/css/StyleConverter.java new file mode 100644 index 00000000000..14b9e1ea1f6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/StyleConverter.java @@ -0,0 +1,48 @@ +// Generated automatically from javafx.css.StyleConverter for testing purposes + +package javafx.css; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.util.List; +import java.util.Map; +import javafx.css.CssMetaData; +import javafx.css.ParsedValue; +import javafx.css.Styleable; +import javafx.geometry.Insets; +import javafx.scene.effect.Effect; +import javafx.scene.paint.Color; +import javafx.scene.paint.Paint; +import javafx.scene.text.Font; +import javafx.util.Duration; + +public class StyleConverter +{ + protected T getCachedValue(ParsedValue p0){ return null; } + protected void cacheValue(ParsedValue p0, Object p1){} + public StyleConverter(){} + public T convert(Map, Object> p0){ return null; } + public T convert(ParsedValue p0, Font p1){ return null; } + public static > StyleConverter getEnumConverter(java.lang.Class p0){ return null; } + public static StyleConverter readBinary(DataInputStream p0, String[] p1){ return null; } + public static StyleConverter getDurationConverter(){ return null; } + public static StyleConverter getSizeConverter(){ return null; } + public static StyleConverter, Paint> getPaintConverter(){ return null; } + public static StyleConverter getEffectConverter(){ return null; } + public static StyleConverter getFontConverter(){ return null; } + public static StyleConverter getInsetsConverter(){ return null; } + public static StyleConverter getUrlConverter(){ return null; } + public static StyleConverter getBooleanConverter(){ return null; } + public static StyleConverter getColorConverter(){ return null; } + public static StyleConverter getStringConverter(){ return null; } + public static void clearCache(){} + public void writeBinary(DataOutputStream p0, StyleConverter.StringStore p1){} + static public class StringStore + { + public StringStore(){} + public final List strings = null; + public int addString(String p0){ return 0; } + public static String[] readBinary(DataInputStream p0){ return null; } + public void writeBinary(DataOutputStream p0){} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/StyleOrigin.java b/java/ql/test/stubs/javafx-web/javafx/css/StyleOrigin.java new file mode 100644 index 00000000000..deb7d0cb2d2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/StyleOrigin.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.css.StyleOrigin for testing purposes + +package javafx.css; + + +public enum StyleOrigin +{ + AUTHOR, INLINE, USER, USER_AGENT; + private StyleOrigin() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/Styleable.java b/java/ql/test/stubs/javafx-web/javafx/css/Styleable.java new file mode 100644 index 00000000000..1a801005a7f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/Styleable.java @@ -0,0 +1,22 @@ +// Generated automatically from javafx.css.Styleable for testing purposes + +package javafx.css; + +import java.util.List; +import javafx.collections.ObservableList; +import javafx.collections.ObservableSet; +import javafx.css.CssMetaData; +import javafx.css.PseudoClass; +import javafx.scene.Node; + +public interface Styleable +{ + List> getCssMetaData(); + ObservableList getStyleClass(); + ObservableSet getPseudoClassStates(); + String getId(); + String getStyle(); + String getTypeSelector(); + Styleable getStyleableParent(); + default Node getStyleableNode(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/css/StyleableProperty.java b/java/ql/test/stubs/javafx-web/javafx/css/StyleableProperty.java new file mode 100644 index 00000000000..da1ddb14913 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/css/StyleableProperty.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.css.StyleableProperty for testing purposes + +package javafx.css; + +import javafx.beans.value.WritableValue; +import javafx.css.CssMetaData; +import javafx.css.StyleOrigin; +import javafx.css.Styleable; + +public interface StyleableProperty extends javafx.beans.value.WritableValue +{ + CssMetaData getCssMetaData(); + StyleOrigin getStyleOrigin(); + void applyStyle(StyleOrigin p0, T p1); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/Event.java b/java/ql/test/stubs/javafx-web/javafx/event/Event.java new file mode 100644 index 00000000000..fec238452c5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/Event.java @@ -0,0 +1,52 @@ +// Generated automatically from javafx.event.Event for testing purposes + +package javafx.event; + +import java.util.EventObject; +import javafx.event.EventTarget; +import javafx.event.EventType; + +public class Event extends EventObject implements Cloneable { + protected Event() { + super(null); + } + + protected EventTarget target = null; + protected EventType eventType = null; + protected boolean consumed = false; + + public Event copyFor(Object p0, EventTarget p1) { + return null; + } + + public Event(EventType p0) { + super(p0); + } + + public Event(Object p0, EventTarget p1, EventType p2) { + super(p0); + } + + public EventTarget getTarget() { + return null; + } + + public EventType getEventType() { + return null; + } + + public Object clone() { + return null; + } + + public boolean isConsumed() { + return false; + } + + public static EventTarget NULL_SOURCE_TARGET = null; + public static EventType ANY = null; + + public static void fireEvent(EventTarget p0, Event p1) {} + + public void consume() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/EventDispatchChain.java b/java/ql/test/stubs/javafx-web/javafx/event/EventDispatchChain.java new file mode 100644 index 00000000000..8ec2590b053 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/EventDispatchChain.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.event.EventDispatchChain for testing purposes + +package javafx.event; + +import javafx.event.Event; +import javafx.event.EventDispatcher; + +public interface EventDispatchChain +{ + Event dispatchEvent(Event p0); + EventDispatchChain append(EventDispatcher p0); + EventDispatchChain prepend(EventDispatcher p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/EventDispatcher.java b/java/ql/test/stubs/javafx-web/javafx/event/EventDispatcher.java new file mode 100644 index 00000000000..47f77def0e3 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/EventDispatcher.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.event.EventDispatcher for testing purposes + +package javafx.event; + +import javafx.event.Event; +import javafx.event.EventDispatchChain; + +public interface EventDispatcher +{ + Event dispatchEvent(Event p0, EventDispatchChain p1); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/EventHandler.java b/java/ql/test/stubs/javafx-web/javafx/event/EventHandler.java new file mode 100644 index 00000000000..0c988576bcf --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/EventHandler.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.event.EventHandler for testing purposes + +package javafx.event; + +import java.util.EventListener; +import javafx.event.Event; + +public interface EventHandler extends EventListener +{ + void handle(T p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/EventTarget.java b/java/ql/test/stubs/javafx-web/javafx/event/EventTarget.java new file mode 100644 index 00000000000..afa13325e8d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/EventTarget.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.event.EventTarget for testing purposes + +package javafx.event; + +import javafx.event.EventDispatchChain; + +public interface EventTarget +{ + EventDispatchChain buildEventDispatchChain(EventDispatchChain p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/event/EventType.java b/java/ql/test/stubs/javafx-web/javafx/event/EventType.java new file mode 100644 index 00000000000..55ec2de476a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/event/EventType.java @@ -0,0 +1,18 @@ +// Generated automatically from javafx.event.EventType for testing purposes + +package javafx.event; + +import java.io.Serializable; +import javafx.event.Event; + +public class EventType implements Serializable +{ + public EventType(){} + public EventType(EventType p0){} + public EventType(EventType p0, String p1){} + public EventType(String p0){} + public String toString(){ return null; } + public final EventType getSuperType(){ return null; } + public final String getName(){ return null; } + public static EventType ROOT = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Bounds.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Bounds.java new file mode 100644 index 00000000000..4d4a4a5cab2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Bounds.java @@ -0,0 +1,35 @@ +// Generated automatically from javafx.geometry.Bounds for testing purposes + +package javafx.geometry; + +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; + +abstract public class Bounds +{ + protected Bounds() {} + protected Bounds(double p0, double p1, double p2, double p3, double p4, double p5){} + public abstract boolean contains(Bounds p0); + public abstract boolean contains(Point2D p0); + public abstract boolean contains(Point3D p0); + public abstract boolean contains(double p0, double p1); + public abstract boolean contains(double p0, double p1, double p2); + public abstract boolean contains(double p0, double p1, double p2, double p3); + public abstract boolean contains(double p0, double p1, double p2, double p3, double p4, double p5); + public abstract boolean intersects(Bounds p0); + public abstract boolean intersects(double p0, double p1, double p2, double p3); + public abstract boolean intersects(double p0, double p1, double p2, double p3, double p4, double p5); + public abstract boolean isEmpty(); + public final double getCenterX(){ return 0; } + public final double getCenterY(){ return 0; } + public final double getCenterZ(){ return 0; } + public final double getDepth(){ return 0; } + public final double getHeight(){ return 0; } + public final double getMaxX(){ return 0; } + public final double getMaxY(){ return 0; } + public final double getMaxZ(){ return 0; } + public final double getMinX(){ return 0; } + public final double getMinY(){ return 0; } + public final double getMinZ(){ return 0; } + public final double getWidth(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Insets.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Insets.java new file mode 100644 index 00000000000..3ac369d4bf9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Insets.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.geometry.Insets for testing purposes + +package javafx.geometry; + + +public class Insets +{ + protected Insets() {} + public Insets(double p0){} + public Insets(double p0, double p1, double p2, double p3){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final double getBottom(){ return 0; } + public final double getLeft(){ return 0; } + public final double getRight(){ return 0; } + public final double getTop(){ return 0; } + public int hashCode(){ return 0; } + public static Insets EMPTY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/NodeOrientation.java b/java/ql/test/stubs/javafx-web/javafx/geometry/NodeOrientation.java new file mode 100644 index 00000000000..143659bc66e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/NodeOrientation.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.geometry.NodeOrientation for testing purposes + +package javafx.geometry; + + +public enum NodeOrientation +{ + INHERIT, LEFT_TO_RIGHT, RIGHT_TO_LEFT; + private NodeOrientation() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Orientation.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Orientation.java new file mode 100644 index 00000000000..3c994d5eeeb --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Orientation.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.geometry.Orientation for testing purposes + +package javafx.geometry; + + +public enum Orientation +{ + HORIZONTAL, VERTICAL; + private Orientation() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Point2D.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Point2D.java new file mode 100644 index 00000000000..e2b3f467133 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Point2D.java @@ -0,0 +1,37 @@ +// Generated automatically from javafx.geometry.Point2D for testing purposes + +package javafx.geometry; + +import javafx.animation.Interpolatable; +import javafx.geometry.Point3D; + +public class Point2D implements Interpolatable +{ + protected Point2D() {} + public Point2D add(Point2D p0){ return null; } + public Point2D add(double p0, double p1){ return null; } + public Point2D interpolate(Point2D p0, double p1){ return null; } + public Point2D midpoint(Point2D p0){ return null; } + public Point2D midpoint(double p0, double p1){ return null; } + public Point2D multiply(double p0){ return null; } + public Point2D normalize(){ return null; } + public Point2D subtract(Point2D p0){ return null; } + public Point2D subtract(double p0, double p1){ return null; } + public Point2D(double p0, double p1){} + public Point3D crossProduct(Point2D p0){ return null; } + public Point3D crossProduct(double p0, double p1){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public double angle(Point2D p0){ return 0; } + public double angle(Point2D p0, Point2D p1){ return 0; } + public double angle(double p0, double p1){ return 0; } + public double distance(Point2D p0){ return 0; } + public double distance(double p0, double p1){ return 0; } + public double dotProduct(Point2D p0){ return 0; } + public double dotProduct(double p0, double p1){ return 0; } + public double magnitude(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public int hashCode(){ return 0; } + public static Point2D ZERO = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Point3D.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Point3D.java new file mode 100644 index 00000000000..1d51d8e70e1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Point3D.java @@ -0,0 +1,37 @@ +// Generated automatically from javafx.geometry.Point3D for testing purposes + +package javafx.geometry; + +import javafx.animation.Interpolatable; + +public class Point3D implements Interpolatable +{ + protected Point3D() {} + public Point3D add(Point3D p0){ return null; } + public Point3D add(double p0, double p1, double p2){ return null; } + public Point3D crossProduct(Point3D p0){ return null; } + public Point3D crossProduct(double p0, double p1, double p2){ return null; } + public Point3D interpolate(Point3D p0, double p1){ return null; } + public Point3D midpoint(Point3D p0){ return null; } + public Point3D midpoint(double p0, double p1, double p2){ return null; } + public Point3D multiply(double p0){ return null; } + public Point3D normalize(){ return null; } + public Point3D subtract(Point3D p0){ return null; } + public Point3D subtract(double p0, double p1, double p2){ return null; } + public Point3D(double p0, double p1, double p2){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public double angle(Point3D p0){ return 0; } + public double angle(Point3D p0, Point3D p1){ return 0; } + public double angle(double p0, double p1, double p2){ return 0; } + public double distance(Point3D p0){ return 0; } + public double distance(double p0, double p1, double p2){ return 0; } + public double dotProduct(Point3D p0){ return 0; } + public double dotProduct(double p0, double p1, double p2){ return 0; } + public double magnitude(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public int hashCode(){ return 0; } + public static Point3D ZERO = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/geometry/Rectangle2D.java b/java/ql/test/stubs/javafx-web/javafx/geometry/Rectangle2D.java new file mode 100644 index 00000000000..36b1b903375 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/geometry/Rectangle2D.java @@ -0,0 +1,27 @@ +// Generated automatically from javafx.geometry.Rectangle2D for testing purposes + +package javafx.geometry; + +import javafx.geometry.Point2D; + +public class Rectangle2D +{ + protected Rectangle2D() {} + public Rectangle2D(double p0, double p1, double p2, double p3){} + public String toString(){ return null; } + public boolean contains(Point2D p0){ return false; } + public boolean contains(Rectangle2D p0){ return false; } + public boolean contains(double p0, double p1){ return false; } + public boolean contains(double p0, double p1, double p2, double p3){ return false; } + public boolean equals(Object p0){ return false; } + public boolean intersects(Rectangle2D p0){ return false; } + public boolean intersects(double p0, double p1, double p2, double p3){ return false; } + public double getHeight(){ return 0; } + public double getMaxX(){ return 0; } + public double getMaxY(){ return 0; } + public double getMinX(){ return 0; } + public double getMinY(){ return 0; } + public double getWidth(){ return 0; } + public int hashCode(){ return 0; } + public static Rectangle2D EMPTY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/Collation.java b/java/ql/test/stubs/javafx-web/javafx/print/Collation.java new file mode 100644 index 00000000000..774a2c35d8c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/Collation.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.print.Collation for testing purposes + +package javafx.print; + + +public enum Collation +{ + COLLATED, UNCOLLATED; + private Collation() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/JobSettings.java b/java/ql/test/stubs/javafx-web/javafx/print/JobSettings.java new file mode 100644 index 00000000000..9e485d38ba1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/JobSettings.java @@ -0,0 +1,54 @@ +// Generated automatically from javafx.print.JobSettings for testing purposes + +package javafx.print; + +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.print.Collation; +import javafx.print.PageLayout; +import javafx.print.PageRange; +import javafx.print.PaperSource; +import javafx.print.PrintColor; +import javafx.print.PrintQuality; +import javafx.print.PrintResolution; +import javafx.print.PrintSides; + +public class JobSettings +{ + protected JobSettings() {} + public String toString(){ return null; } + public final Collation getCollation(){ return null; } + public final IntegerProperty copiesProperty(){ return null; } + public final ObjectProperty pageRangesProperty(){ return null; } + public final ObjectProperty collationProperty(){ return null; } + public final ObjectProperty pageLayoutProperty(){ return null; } + public final ObjectProperty paperSourceProperty(){ return null; } + public final ObjectProperty printColorProperty(){ return null; } + public final ObjectProperty printQualityProperty(){ return null; } + public final ObjectProperty printResolutionProperty(){ return null; } + public final ObjectProperty printSidesProperty(){ return null; } + public final PageLayout getPageLayout(){ return null; } + public final PageRange[] getPageRanges(){ return null; } + public final PaperSource getPaperSource(){ return null; } + public final PrintColor getPrintColor(){ return null; } + public final PrintQuality getPrintQuality(){ return null; } + public final PrintResolution getPrintResolution(){ return null; } + public final PrintSides getPrintSides(){ return null; } + public final String getJobName(){ return null; } + public final String getOutputFile(){ return null; } + public final StringProperty jobNameProperty(){ return null; } + public final StringProperty outputFileProperty(){ return null; } + public final int getCopies(){ return 0; } + public final void setCollation(Collation p0){} + public final void setCopies(int p0){} + public final void setJobName(String p0){} + public final void setOutputFile(String p0){} + public final void setPageLayout(PageLayout p0){} + public final void setPageRanges(PageRange... p0){} + public final void setPaperSource(PaperSource p0){} + public final void setPrintColor(PrintColor p0){} + public final void setPrintQuality(PrintQuality p0){} + public final void setPrintResolution(PrintResolution p0){} + public final void setPrintSides(PrintSides p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PageLayout.java b/java/ql/test/stubs/javafx-web/javafx/print/PageLayout.java new file mode 100644 index 00000000000..81d16c015db --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PageLayout.java @@ -0,0 +1,22 @@ +// Generated automatically from javafx.print.PageLayout for testing purposes + +package javafx.print; + +import javafx.print.PageOrientation; +import javafx.print.Paper; + +public class PageLayout +{ + protected PageLayout() {} + public PageOrientation getPageOrientation(){ return null; } + public Paper getPaper(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public double getBottomMargin(){ return 0; } + public double getLeftMargin(){ return 0; } + public double getPrintableHeight(){ return 0; } + public double getPrintableWidth(){ return 0; } + public double getRightMargin(){ return 0; } + public double getTopMargin(){ return 0; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PageOrientation.java b/java/ql/test/stubs/javafx-web/javafx/print/PageOrientation.java new file mode 100644 index 00000000000..8a1ee2274fd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PageOrientation.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.print.PageOrientation for testing purposes + +package javafx.print; + + +public enum PageOrientation +{ + LANDSCAPE, PORTRAIT, REVERSE_LANDSCAPE, REVERSE_PORTRAIT; + private PageOrientation() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PageRange.java b/java/ql/test/stubs/javafx-web/javafx/print/PageRange.java new file mode 100644 index 00000000000..e8e5221441e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PageRange.java @@ -0,0 +1,16 @@ +// Generated automatically from javafx.print.PageRange for testing purposes + +package javafx.print; + +import javafx.beans.property.ReadOnlyIntegerProperty; + +public class PageRange +{ + protected PageRange() {} + public PageRange(int p0, int p1){} + public String toString(){ return null; } + public final ReadOnlyIntegerProperty endPageProperty(){ return null; } + public final ReadOnlyIntegerProperty startPageProperty(){ return null; } + public final int getEndPage(){ return 0; } + public final int getStartPage(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/Paper.java b/java/ql/test/stubs/javafx-web/javafx/print/Paper.java new file mode 100644 index 00000000000..60a31fe3875 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/Paper.java @@ -0,0 +1,35 @@ +// Generated automatically from javafx.print.Paper for testing purposes + +package javafx.print; + + +public class Paper +{ + protected Paper() {} + public final String getName(){ return null; } + public final String toString(){ return null; } + public final boolean equals(Object p0){ return false; } + public final double getHeight(){ return 0; } + public final double getWidth(){ return 0; } + public final int hashCode(){ return 0; } + public static Paper A0 = null; + public static Paper A1 = null; + public static Paper A2 = null; + public static Paper A3 = null; + public static Paper A4 = null; + public static Paper A5 = null; + public static Paper A6 = null; + public static Paper C = null; + public static Paper DESIGNATED_LONG = null; + public static Paper EXECUTIVE = null; + public static Paper JAPANESE_POSTCARD = null; + public static Paper JIS_B4 = null; + public static Paper JIS_B5 = null; + public static Paper JIS_B6 = null; + public static Paper LEGAL = null; + public static Paper MONARCH_ENVELOPE = null; + public static Paper NA_8X10 = null; + public static Paper NA_LETTER = null; + public static Paper NA_NUMBER_10_ENVELOPE = null; + public static Paper TABLOID = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PaperSource.java b/java/ql/test/stubs/javafx-web/javafx/print/PaperSource.java new file mode 100644 index 00000000000..d3ca53f870d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PaperSource.java @@ -0,0 +1,20 @@ +// Generated automatically from javafx.print.PaperSource for testing purposes + +package javafx.print; + + +public class PaperSource +{ + protected PaperSource() {} + public String getName(){ return null; } + public String toString(){ return null; } + public static PaperSource AUTOMATIC = null; + public static PaperSource BOTTOM = null; + public static PaperSource ENVELOPE = null; + public static PaperSource LARGE_CAPACITY = null; + public static PaperSource MAIN = null; + public static PaperSource MANUAL = null; + public static PaperSource MIDDLE = null; + public static PaperSource SIDE = null; + public static PaperSource TOP = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrintColor.java b/java/ql/test/stubs/javafx-web/javafx/print/PrintColor.java new file mode 100644 index 00000000000..f2317db8eb8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrintColor.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.print.PrintColor for testing purposes + +package javafx.print; + + +public enum PrintColor +{ + COLOR, MONOCHROME; + private PrintColor() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrintQuality.java b/java/ql/test/stubs/javafx-web/javafx/print/PrintQuality.java new file mode 100644 index 00000000000..d0a51cc1551 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrintQuality.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.print.PrintQuality for testing purposes + +package javafx.print; + + +public enum PrintQuality +{ + DRAFT, HIGH, LOW, NORMAL; + private PrintQuality() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrintResolution.java b/java/ql/test/stubs/javafx-web/javafx/print/PrintResolution.java new file mode 100644 index 00000000000..eada0c7fd2c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrintResolution.java @@ -0,0 +1,14 @@ +// Generated automatically from javafx.print.PrintResolution for testing purposes + +package javafx.print; + + +public class PrintResolution +{ + protected PrintResolution() {} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getCrossFeedResolution(){ return 0; } + public int getFeedResolution(){ return 0; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrintSides.java b/java/ql/test/stubs/javafx-web/javafx/print/PrintSides.java new file mode 100644 index 00000000000..edf90c8e64c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrintSides.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.print.PrintSides for testing purposes + +package javafx.print; + + +public enum PrintSides +{ + DUPLEX, ONE_SIDED, TUMBLE; + private PrintSides() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/Printer.java b/java/ql/test/stubs/javafx-web/javafx/print/Printer.java new file mode 100644 index 00000000000..5aed8020880 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/Printer.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.print.Printer for testing purposes + +package javafx.print; + +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.collections.ObservableSet; +import javafx.print.PageLayout; +import javafx.print.PageOrientation; +import javafx.print.Paper; +import javafx.print.PrinterAttributes; + +public class Printer +{ + protected Printer() {} + public PageLayout createPageLayout(Paper p0, PageOrientation p1, Printer.MarginType p2){ return null; } + public PageLayout createPageLayout(Paper p0, PageOrientation p1, double p2, double p3, double p4, double p5){ return null; } + public PageLayout getDefaultPageLayout(){ return null; } + public PrinterAttributes getPrinterAttributes(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public static ObservableSet getAllPrinters(){ return null; } + public static Printer getDefaultPrinter(){ return null; } + public static ReadOnlyObjectProperty defaultPrinterProperty(){ return null; } + static public enum MarginType + { + DEFAULT, EQUAL, EQUAL_OPPOSITES, HARDWARE_MINIMUM; + private MarginType() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrinterAttributes.java b/java/ql/test/stubs/javafx-web/javafx/print/PrinterAttributes.java new file mode 100644 index 00000000000..8d8076f769a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrinterAttributes.java @@ -0,0 +1,37 @@ +// Generated automatically from javafx.print.PrinterAttributes for testing purposes + +package javafx.print; + +import java.util.Set; +import javafx.print.Collation; +import javafx.print.PageOrientation; +import javafx.print.Paper; +import javafx.print.PaperSource; +import javafx.print.PrintColor; +import javafx.print.PrintQuality; +import javafx.print.PrintResolution; +import javafx.print.PrintSides; + +public class PrinterAttributes +{ + protected PrinterAttributes() {} + public Collation getDefaultCollation(){ return null; } + public PageOrientation getDefaultPageOrientation(){ return null; } + public Paper getDefaultPaper(){ return null; } + public PaperSource getDefaultPaperSource(){ return null; } + public PrintColor getDefaultPrintColor(){ return null; } + public PrintQuality getDefaultPrintQuality(){ return null; } + public PrintResolution getDefaultPrintResolution(){ return null; } + public PrintSides getDefaultPrintSides(){ return null; } + public Set getSupportedCollations(){ return null; } + public Set getSupportedPageOrientations(){ return null; } + public Set getSupportedPapers(){ return null; } + public Set getSupportedPaperSources(){ return null; } + public Set getSupportedPrintColors(){ return null; } + public Set getSupportedPrintQuality(){ return null; } + public Set getSupportedPrintResolutions(){ return null; } + public Set getSupportedPrintSides(){ return null; } + public boolean supportsPageRanges(){ return false; } + public int getDefaultCopies(){ return 0; } + public int getMaxCopies(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/print/PrinterJob.java b/java/ql/test/stubs/javafx-web/javafx/print/PrinterJob.java new file mode 100644 index 00000000000..6df822d963f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/print/PrinterJob.java @@ -0,0 +1,36 @@ +// Generated automatically from javafx.print.PrinterJob for testing purposes + +package javafx.print; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.print.JobSettings; +import javafx.print.PageLayout; +import javafx.print.Printer; +import javafx.scene.Node; +import javafx.stage.Window; + +public class PrinterJob +{ + protected PrinterJob() {} + public JobSettings getJobSettings(){ return null; } + public String toString(){ return null; } + public boolean endJob(){ return false; } + public boolean printPage(Node p0){ return false; } + public boolean printPage(PageLayout p0, Node p1){ return false; } + public boolean showPageSetupDialog(Window p0){ return false; } + public boolean showPrintDialog(Window p0){ return false; } + public final ObjectProperty printerProperty(){ return null; } + public final Printer getPrinter(){ return null; } + public final PrinterJob.JobStatus getJobStatus(){ return null; } + public final ReadOnlyObjectProperty jobStatusProperty(){ return null; } + public final void setPrinter(Printer p0){} + public static PrinterJob createPrinterJob(){ return null; } + public static PrinterJob createPrinterJob(Printer p0){ return null; } + public void cancelJob(){} + static public enum JobStatus + { + CANCELED, DONE, ERROR, NOT_STARTED, PRINTING; + private JobStatus() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAction.java b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAction.java new file mode 100644 index 00000000000..89154d00ccd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAction.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.AccessibleAction for testing purposes + +package javafx.scene; + + +public enum AccessibleAction +{ + BLOCK_DECREMENT, BLOCK_INCREMENT, COLLAPSE, DECREMENT, EXPAND, FIRE, INCREMENT, REQUEST_FOCUS, SET_SELECTED_ITEMS, SET_TEXT, SET_TEXT_SELECTION, SET_VALUE, SHOW_ITEM, SHOW_MENU, SHOW_TEXT_RANGE; + private AccessibleAction() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAttribute.java b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAttribute.java new file mode 100644 index 00000000000..ac27dfef6b1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleAttribute.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.scene.AccessibleAttribute for testing purposes + +package javafx.scene; + + +public enum AccessibleAttribute +{ + ACCELERATOR, BOUNDS, BOUNDS_FOR_RANGE, CARET_OFFSET, CELL_AT_ROW_COLUMN, CHILDREN, COLUMN_AT_INDEX, COLUMN_COUNT, COLUMN_INDEX, CONTENTS, DATE, DISABLED, DISCLOSURE_LEVEL, EDITABLE, EXPANDED, FOCUSED, FOCUS_ITEM, FOCUS_NODE, FONT, HEADER, HELP, HORIZONTAL_SCROLLBAR, INDETERMINATE, INDEX, ITEM_AT_INDEX, ITEM_COUNT, LABELED_BY, LEAF, LINE_END, LINE_FOR_OFFSET, LINE_START, MAX_VALUE, MIN_VALUE, MNEMONIC, MULTIPLE_SELECTION, NODE_AT_POINT, OFFSET_AT_POINT, ORIENTATION, OVERFLOW_BUTTON, PARENT, PARENT_MENU, ROLE, ROLE_DESCRIPTION, ROW_AT_INDEX, ROW_COUNT, ROW_INDEX, SCENE, SELECTED, SELECTED_ITEMS, SELECTION_END, SELECTION_START, SUBMENU, TEXT, TREE_ITEM_AT_INDEX, TREE_ITEM_COUNT, TREE_ITEM_PARENT, VALUE, VERTICAL_SCROLLBAR, VISIBLE, VISITED; + private AccessibleAttribute() {} + public Class getReturnType(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleRole.java b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleRole.java new file mode 100644 index 00000000000..5eaeb704487 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/AccessibleRole.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.AccessibleRole for testing purposes + +package javafx.scene; + + +public enum AccessibleRole +{ + BUTTON, CHECK_BOX, CHECK_MENU_ITEM, COMBO_BOX, CONTEXT_MENU, DATE_PICKER, DECREMENT_BUTTON, DIALOG, HYPERLINK, IMAGE_VIEW, INCREMENT_BUTTON, LIST_ITEM, LIST_VIEW, MENU, MENU_BAR, MENU_BUTTON, MENU_ITEM, NODE, PAGE_ITEM, PAGINATION, PARENT, PASSWORD_FIELD, PROGRESS_INDICATOR, RADIO_BUTTON, RADIO_MENU_ITEM, SCROLL_BAR, SCROLL_PANE, SLIDER, SPINNER, SPLIT_MENU_BUTTON, TABLE_CELL, TABLE_COLUMN, TABLE_ROW, TABLE_VIEW, TAB_ITEM, TAB_PANE, TEXT, TEXT_AREA, TEXT_FIELD, THUMB, TITLED_PANE, TOGGLE_BUTTON, TOOLTIP, TOOL_BAR, TREE_ITEM, TREE_TABLE_CELL, TREE_TABLE_ROW, TREE_TABLE_VIEW, TREE_VIEW; + private AccessibleRole() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/CacheHint.java b/java/ql/test/stubs/javafx-web/javafx/scene/CacheHint.java new file mode 100644 index 00000000000..1cd6cf4a095 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/CacheHint.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.CacheHint for testing purposes + +package javafx.scene; + + +public enum CacheHint +{ + DEFAULT, QUALITY, ROTATE, SCALE, SCALE_AND_ROTATE, SPEED; + private CacheHint() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/Camera.java b/java/ql/test/stubs/javafx-web/javafx/scene/Camera.java new file mode 100644 index 00000000000..08c4d8b8592 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/Camera.java @@ -0,0 +1,17 @@ +// Generated automatically from javafx.scene.Camera for testing purposes + +package javafx.scene; + +import javafx.beans.property.DoubleProperty; +import javafx.scene.Node; + +abstract public class Camera extends Node +{ + protected Camera(){} + public final DoubleProperty farClipProperty(){ return null; } + public final DoubleProperty nearClipProperty(){ return null; } + public final double getFarClip(){ return 0; } + public final double getNearClip(){ return 0; } + public final void setFarClip(double p0){} + public final void setNearClip(double p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/Cursor.java b/java/ql/test/stubs/javafx-web/javafx/scene/Cursor.java new file mode 100644 index 00000000000..de75b547da6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/Cursor.java @@ -0,0 +1,30 @@ +// Generated automatically from javafx.scene.Cursor for testing purposes + +package javafx.scene; + + +abstract public class Cursor +{ + public String toString(){ return null; } + public static Cursor CLOSED_HAND = null; + public static Cursor CROSSHAIR = null; + public static Cursor DEFAULT = null; + public static Cursor DISAPPEAR = null; + public static Cursor E_RESIZE = null; + public static Cursor HAND = null; + public static Cursor H_RESIZE = null; + public static Cursor MOVE = null; + public static Cursor NE_RESIZE = null; + public static Cursor NONE = null; + public static Cursor NW_RESIZE = null; + public static Cursor N_RESIZE = null; + public static Cursor OPEN_HAND = null; + public static Cursor SE_RESIZE = null; + public static Cursor SW_RESIZE = null; + public static Cursor S_RESIZE = null; + public static Cursor TEXT = null; + public static Cursor V_RESIZE = null; + public static Cursor WAIT = null; + public static Cursor W_RESIZE = null; + public static Cursor cursor(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/DepthTest.java b/java/ql/test/stubs/javafx-web/javafx/scene/DepthTest.java new file mode 100644 index 00000000000..4d624bd3b7f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/DepthTest.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.DepthTest for testing purposes + +package javafx.scene; + + +public enum DepthTest +{ + DISABLE, ENABLE, INHERIT; + private DepthTest() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/Node.java b/java/ql/test/stubs/javafx-web/javafx/scene/Node.java new file mode 100644 index 00000000000..693d13192ab --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/Node.java @@ -0,0 +1,406 @@ +// Generated automatically from javafx.scene.Node for testing purposes + +package javafx.scene; + +import java.util.List; +import java.util.Set; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyBooleanPropertyBase; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.StringProperty; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; +import javafx.collections.ObservableSet; +import javafx.css.CssMetaData; +import javafx.css.PseudoClass; +import javafx.css.Styleable; +import javafx.event.Event; +import javafx.event.EventDispatchChain; +import javafx.event.EventDispatcher; +import javafx.event.EventHandler; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.geometry.Bounds; +import javafx.geometry.NodeOrientation; +import javafx.geometry.Orientation; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.AccessibleAction; +import javafx.scene.AccessibleAttribute; +import javafx.scene.AccessibleRole; +import javafx.scene.CacheHint; +import javafx.scene.Cursor; +import javafx.scene.DepthTest; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.SnapshotParameters; +import javafx.scene.SnapshotResult; +import javafx.scene.effect.BlendMode; +import javafx.scene.effect.Effect; +import javafx.scene.image.WritableImage; +import javafx.scene.input.ContextMenuEvent; +import javafx.scene.input.DragEvent; +import javafx.scene.input.Dragboard; +import javafx.scene.input.InputMethodEvent; +import javafx.scene.input.InputMethodRequests; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.MouseDragEvent; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.RotateEvent; +import javafx.scene.input.ScrollEvent; +import javafx.scene.input.SwipeEvent; +import javafx.scene.input.TouchEvent; +import javafx.scene.input.TransferMode; +import javafx.scene.input.ZoomEvent; +import javafx.scene.transform.Transform; +import javafx.util.Callback; + +abstract public class Node implements EventTarget, Styleable +{ + protected Boolean getInitialFocusTraversable(){ return null; } + protected Cursor getInitialCursor(){ return null; } + protected Node(){} + protected final void setEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + protected final void setDisabled(boolean p0){} + protected final void setFocused(boolean p0){} + protected final void setHover(boolean p0){} + protected final void setPressed(boolean p0){} + public Bounds localToParent(Bounds p0){ return null; } + public Bounds localToScene(Bounds p0){ return null; } + public Bounds localToScene(Bounds p0, boolean p1){ return null; } + public Bounds localToScreen(Bounds p0){ return null; } + public Bounds parentToLocal(Bounds p0){ return null; } + public Bounds sceneToLocal(Bounds p0){ return null; } + public Bounds sceneToLocal(Bounds p0, boolean p1){ return null; } + public Bounds screenToLocal(Bounds p0){ return null; } + public Dragboard startDragAndDrop(TransferMode... p0){ return null; } + public EventDispatchChain buildEventDispatchChain(EventDispatchChain p0){ return null; } + public List> getCssMetaData(){ return null; } + public Node lookup(String p0){ return null; } + public Object getUserData(){ return null; } + public Object queryAccessibleAttribute(AccessibleAttribute p0, Object... p1){ return null; } + public Orientation getContentBias(){ return null; } + public Point2D localToParent(Point2D p0){ return null; } + public Point2D localToParent(double p0, double p1){ return null; } + public Point2D localToScene(Point2D p0){ return null; } + public Point2D localToScene(Point2D p0, boolean p1){ return null; } + public Point2D localToScene(double p0, double p1){ return null; } + public Point2D localToScene(double p0, double p1, boolean p2){ return null; } + public Point2D localToScreen(Point2D p0){ return null; } + public Point2D localToScreen(Point3D p0){ return null; } + public Point2D localToScreen(double p0, double p1){ return null; } + public Point2D localToScreen(double p0, double p1, double p2){ return null; } + public Point2D parentToLocal(Point2D p0){ return null; } + public Point2D parentToLocal(double p0, double p1){ return null; } + public Point2D sceneToLocal(Point2D p0){ return null; } + public Point2D sceneToLocal(Point2D p0, boolean p1){ return null; } + public Point2D sceneToLocal(double p0, double p1){ return null; } + public Point2D sceneToLocal(double p0, double p1, boolean p2){ return null; } + public Point2D screenToLocal(Point2D p0){ return null; } + public Point2D screenToLocal(double p0, double p1){ return null; } + public Point3D localToParent(Point3D p0){ return null; } + public Point3D localToParent(double p0, double p1, double p2){ return null; } + public Point3D localToScene(Point3D p0){ return null; } + public Point3D localToScene(Point3D p0, boolean p1){ return null; } + public Point3D localToScene(double p0, double p1, double p2){ return null; } + public Point3D localToScene(double p0, double p1, double p2, boolean p3){ return null; } + public Point3D parentToLocal(Point3D p0){ return null; } + public Point3D parentToLocal(double p0, double p1, double p2){ return null; } + public Point3D sceneToLocal(Point3D p0){ return null; } + public Point3D sceneToLocal(double p0, double p1, double p2){ return null; } + public Set lookupAll(String p0){ return null; } + public String getTypeSelector(){ return null; } + public String toString(){ return null; } + public Styleable getStyleableParent(){ return null; } + public WritableImage snapshot(SnapshotParameters p0, WritableImage p1){ return null; } + public boolean contains(Point2D p0){ return false; } + public boolean contains(double p0, double p1){ return false; } + public boolean hasProperties(){ return false; } + public boolean intersects(Bounds p0){ return false; } + public boolean intersects(double p0, double p1, double p2, double p3){ return false; } + public boolean isResizable(){ return false; } + public boolean usesMirroring(){ return false; } + public double computeAreaInScreen(){ return 0; } + public double getBaselineOffset(){ return 0; } + public double maxHeight(double p0){ return 0; } + public double maxWidth(double p0){ return 0; } + public double minHeight(double p0){ return 0; } + public double minWidth(double p0){ return 0; } + public double prefHeight(double p0){ return 0; } + public double prefWidth(double p0){ return 0; } + public final void addEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void addEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final AccessibleRole getAccessibleRole(){ return null; } + public final BlendMode getBlendMode(){ return null; } + public final BooleanProperty cacheProperty(){ return null; } + public final BooleanProperty disableProperty(){ return null; } + public final BooleanProperty focusTraversableProperty(){ return null; } + public final BooleanProperty managedProperty(){ return null; } + public final BooleanProperty mouseTransparentProperty(){ return null; } + public final BooleanProperty pickOnBoundsProperty(){ return null; } + public final BooleanProperty visibleProperty(){ return null; } + public final Bounds getBoundsInLocal(){ return null; } + public final Bounds getBoundsInParent(){ return null; } + public final Bounds getLayoutBounds(){ return null; } + public final CacheHint getCacheHint(){ return null; } + public final Cursor getCursor(){ return null; } + public final DepthTest getDepthTest(){ return null; } + public final DoubleProperty layoutXProperty(){ return null; } + public final DoubleProperty layoutYProperty(){ return null; } + public final DoubleProperty opacityProperty(){ return null; } + public final DoubleProperty rotateProperty(){ return null; } + public final DoubleProperty scaleXProperty(){ return null; } + public final DoubleProperty scaleYProperty(){ return null; } + public final DoubleProperty scaleZProperty(){ return null; } + public final DoubleProperty translateXProperty(){ return null; } + public final DoubleProperty translateYProperty(){ return null; } + public final DoubleProperty translateZProperty(){ return null; } + public final DoubleProperty viewOrderProperty(){ return null; } + public final Effect getEffect(){ return null; } + public final EventDispatcher getEventDispatcher(){ return null; } + public final EventHandler getOnContextMenuRequested(){ return null; } + public final EventHandler getOnDragDone(){ return null; } + public final EventHandler getOnDragDropped(){ return null; } + public final EventHandler getOnDragEntered(){ return null; } + public final EventHandler getOnDragExited(){ return null; } + public final EventHandler getOnDragOver(){ return null; } + public final EventHandler getOnInputMethodTextChanged(){ return null; } + public final EventHandler getOnKeyPressed(){ return null; } + public final EventHandler getOnKeyReleased(){ return null; } + public final EventHandler getOnKeyTyped(){ return null; } + public final EventHandler getOnMouseDragEntered(){ return null; } + public final EventHandler getOnMouseDragExited(){ return null; } + public final EventHandler getOnMouseDragOver(){ return null; } + public final EventHandler getOnMouseDragReleased(){ return null; } + public final EventHandler getOnDragDetected(){ return null; } + public final EventHandler getOnMouseClicked(){ return null; } + public final EventHandler getOnMouseDragged(){ return null; } + public final EventHandler getOnMouseEntered(){ return null; } + public final EventHandler getOnMouseExited(){ return null; } + public final EventHandler getOnMouseMoved(){ return null; } + public final EventHandler getOnMousePressed(){ return null; } + public final EventHandler getOnMouseReleased(){ return null; } + public final EventHandler getOnRotate(){ return null; } + public final EventHandler getOnRotationFinished(){ return null; } + public final EventHandler getOnRotationStarted(){ return null; } + public final EventHandler getOnScroll(){ return null; } + public final EventHandler getOnScrollFinished(){ return null; } + public final EventHandler getOnScrollStarted(){ return null; } + public final EventHandler getOnSwipeDown(){ return null; } + public final EventHandler getOnSwipeLeft(){ return null; } + public final EventHandler getOnSwipeRight(){ return null; } + public final EventHandler getOnSwipeUp(){ return null; } + public final EventHandler getOnTouchMoved(){ return null; } + public final EventHandler getOnTouchPressed(){ return null; } + public final EventHandler getOnTouchReleased(){ return null; } + public final EventHandler getOnTouchStationary(){ return null; } + public final EventHandler getOnZoom(){ return null; } + public final EventHandler getOnZoomFinished(){ return null; } + public final EventHandler getOnZoomStarted(){ return null; } + public final InputMethodRequests getInputMethodRequests(){ return null; } + public final Node getClip(){ return null; } + public final NodeOrientation getEffectiveNodeOrientation(){ return null; } + public final NodeOrientation getNodeOrientation(){ return null; } + public final ObjectProperty accessibleRoleProperty(){ return null; } + public final ObjectProperty blendModeProperty(){ return null; } + public final ObjectProperty cacheHintProperty(){ return null; } + public final ObjectProperty cursorProperty(){ return null; } + public final ObjectProperty depthTestProperty(){ return null; } + public final ObjectProperty effectProperty(){ return null; } + public final ObjectProperty eventDispatcherProperty(){ return null; } + public final ObjectProperty> onContextMenuRequestedProperty(){ return null; } + public final ObjectProperty> onDragDoneProperty(){ return null; } + public final ObjectProperty> onDragDroppedProperty(){ return null; } + public final ObjectProperty> onDragEnteredProperty(){ return null; } + public final ObjectProperty> onDragExitedProperty(){ return null; } + public final ObjectProperty> onDragOverProperty(){ return null; } + public final ObjectProperty> onInputMethodTextChangedProperty(){ return null; } + public final ObjectProperty> onKeyPressedProperty(){ return null; } + public final ObjectProperty> onKeyReleasedProperty(){ return null; } + public final ObjectProperty> onKeyTypedProperty(){ return null; } + public final ObjectProperty> onMouseDragEnteredProperty(){ return null; } + public final ObjectProperty> onMouseDragExitedProperty(){ return null; } + public final ObjectProperty> onMouseDragOverProperty(){ return null; } + public final ObjectProperty> onMouseDragReleasedProperty(){ return null; } + public final ObjectProperty> onDragDetectedProperty(){ return null; } + public final ObjectProperty> onMouseClickedProperty(){ return null; } + public final ObjectProperty> onMouseDraggedProperty(){ return null; } + public final ObjectProperty> onMouseEnteredProperty(){ return null; } + public final ObjectProperty> onMouseExitedProperty(){ return null; } + public final ObjectProperty> onMouseMovedProperty(){ return null; } + public final ObjectProperty> onMousePressedProperty(){ return null; } + public final ObjectProperty> onMouseReleasedProperty(){ return null; } + public final ObjectProperty> onRotateProperty(){ return null; } + public final ObjectProperty> onRotationFinishedProperty(){ return null; } + public final ObjectProperty> onRotationStartedProperty(){ return null; } + public final ObjectProperty> onScrollFinishedProperty(){ return null; } + public final ObjectProperty> onScrollProperty(){ return null; } + public final ObjectProperty> onScrollStartedProperty(){ return null; } + public final ObjectProperty> onSwipeDownProperty(){ return null; } + public final ObjectProperty> onSwipeLeftProperty(){ return null; } + public final ObjectProperty> onSwipeRightProperty(){ return null; } + public final ObjectProperty> onSwipeUpProperty(){ return null; } + public final ObjectProperty> onTouchMovedProperty(){ return null; } + public final ObjectProperty> onTouchPressedProperty(){ return null; } + public final ObjectProperty> onTouchReleasedProperty(){ return null; } + public final ObjectProperty> onTouchStationaryProperty(){ return null; } + public final ObjectProperty> onZoomFinishedProperty(){ return null; } + public final ObjectProperty> onZoomProperty(){ return null; } + public final ObjectProperty> onZoomStartedProperty(){ return null; } + public final ObjectProperty inputMethodRequestsProperty(){ return null; } + public final ObjectProperty clipProperty(){ return null; } + public final ObjectProperty nodeOrientationProperty(){ return null; } + public final ObjectProperty rotationAxisProperty(){ return null; } + public final ObjectProperty accessibleHelpProperty(){ return null; } + public final ObjectProperty accessibleRoleDescriptionProperty(){ return null; } + public final ObjectProperty accessibleTextProperty(){ return null; } + public final ObservableList getStyleClass(){ return null; } + public final ObservableList getTransforms(){ return null; } + public final ObservableMap getProperties(){ return null; } + public final ObservableSet getPseudoClassStates(){ return null; } + public final Parent getParent(){ return null; } + public final Point3D getRotationAxis(){ return null; } + public final ReadOnlyBooleanProperty disabledProperty(){ return null; } + public final ReadOnlyBooleanProperty focusVisibleProperty(){ return null; } + public final ReadOnlyBooleanProperty focusWithinProperty(){ return null; } + public final ReadOnlyBooleanProperty focusedProperty(){ return null; } + public final ReadOnlyBooleanProperty hoverProperty(){ return null; } + public final ReadOnlyBooleanProperty pressedProperty(){ return null; } + public final ReadOnlyObjectProperty boundsInLocalProperty(){ return null; } + public final ReadOnlyObjectProperty boundsInParentProperty(){ return null; } + public final ReadOnlyObjectProperty layoutBoundsProperty(){ return null; } + public final ReadOnlyObjectProperty effectiveNodeOrientationProperty(){ return null; } + public final ReadOnlyObjectProperty parentProperty(){ return null; } + public final ReadOnlyObjectProperty sceneProperty(){ return null; } + public final ReadOnlyObjectProperty localToParentTransformProperty(){ return null; } + public final ReadOnlyObjectProperty localToSceneTransformProperty(){ return null; } + public final Scene getScene(){ return null; } + public final String getAccessibleHelp(){ return null; } + public final String getAccessibleRoleDescription(){ return null; } + public final String getAccessibleText(){ return null; } + public final String getId(){ return null; } + public final String getStyle(){ return null; } + public final StringProperty idProperty(){ return null; } + public final StringProperty styleProperty(){ return null; } + public final Transform getLocalToParentTransform(){ return null; } + public final Transform getLocalToSceneTransform(){ return null; } + public final boolean isCache(){ return false; } + public final boolean isDisable(){ return false; } + public final boolean isDisabled(){ return false; } + public final boolean isFocusTraversable(){ return false; } + public final boolean isFocusVisible(){ return false; } + public final boolean isFocusWithin(){ return false; } + public final boolean isFocused(){ return false; } + public final boolean isHover(){ return false; } + public final boolean isManaged(){ return false; } + public final boolean isMouseTransparent(){ return false; } + public final boolean isPickOnBounds(){ return false; } + public final boolean isPressed(){ return false; } + public final boolean isVisible(){ return false; } + public final double getLayoutX(){ return 0; } + public final double getLayoutY(){ return 0; } + public final double getOpacity(){ return 0; } + public final double getRotate(){ return 0; } + public final double getScaleX(){ return 0; } + public final double getScaleY(){ return 0; } + public final double getScaleZ(){ return 0; } + public final double getTranslateX(){ return 0; } + public final double getTranslateY(){ return 0; } + public final double getTranslateZ(){ return 0; } + public final double getViewOrder(){ return 0; } + public final void applyCss(){} + public final void autosize(){} + public final void fireEvent(Event p0){} + public final void notifyAccessibleAttributeChanged(AccessibleAttribute p0){} + public final void pseudoClassStateChanged(PseudoClass p0, boolean p1){} + public final void setAccessibleHelp(String p0){} + public final void setAccessibleRole(AccessibleRole p0){} + public final void setAccessibleRoleDescription(String p0){} + public final void setAccessibleText(String p0){} + public final void setBlendMode(BlendMode p0){} + public final void setCache(boolean p0){} + public final void setCacheHint(CacheHint p0){} + public final void setClip(Node p0){} + public final void setCursor(Cursor p0){} + public final void setDepthTest(DepthTest p0){} + public final void setDisable(boolean p0){} + public final void setEffect(Effect p0){} + public final void setEventDispatcher(EventDispatcher p0){} + public final void setFocusTraversable(boolean p0){} + public final void setId(String p0){} + public final void setInputMethodRequests(InputMethodRequests p0){} + public final void setLayoutX(double p0){} + public final void setLayoutY(double p0){} + public final void setManaged(boolean p0){} + public final void setMouseTransparent(boolean p0){} + public final void setNodeOrientation(NodeOrientation p0){} + public final void setOnContextMenuRequested(EventHandler p0){} + public final void setOnDragDetected(EventHandler p0){} + public final void setOnDragDone(EventHandler p0){} + public final void setOnDragDropped(EventHandler p0){} + public final void setOnDragEntered(EventHandler p0){} + public final void setOnDragExited(EventHandler p0){} + public final void setOnDragOver(EventHandler p0){} + public final void setOnInputMethodTextChanged(EventHandler p0){} + public final void setOnKeyPressed(EventHandler p0){} + public final void setOnKeyReleased(EventHandler p0){} + public final void setOnKeyTyped(EventHandler p0){} + public final void setOnMouseClicked(EventHandler p0){} + public final void setOnMouseDragEntered(EventHandler p0){} + public final void setOnMouseDragExited(EventHandler p0){} + public final void setOnMouseDragOver(EventHandler p0){} + public final void setOnMouseDragReleased(EventHandler p0){} + public final void setOnMouseDragged(EventHandler p0){} + public final void setOnMouseEntered(EventHandler p0){} + public final void setOnMouseExited(EventHandler p0){} + public final void setOnMouseMoved(EventHandler p0){} + public final void setOnMousePressed(EventHandler p0){} + public final void setOnMouseReleased(EventHandler p0){} + public final void setOnRotate(EventHandler p0){} + public final void setOnRotationFinished(EventHandler p0){} + public final void setOnRotationStarted(EventHandler p0){} + public final void setOnScroll(EventHandler p0){} + public final void setOnScrollFinished(EventHandler p0){} + public final void setOnScrollStarted(EventHandler p0){} + public final void setOnSwipeDown(EventHandler p0){} + public final void setOnSwipeLeft(EventHandler p0){} + public final void setOnSwipeRight(EventHandler p0){} + public final void setOnSwipeUp(EventHandler p0){} + public final void setOnTouchMoved(EventHandler p0){} + public final void setOnTouchPressed(EventHandler p0){} + public final void setOnTouchReleased(EventHandler p0){} + public final void setOnTouchStationary(EventHandler p0){} + public final void setOnZoom(EventHandler p0){} + public final void setOnZoomFinished(EventHandler p0){} + public final void setOnZoomStarted(EventHandler p0){} + public final void setOpacity(double p0){} + public final void setPickOnBounds(boolean p0){} + public final void setRotate(double p0){} + public final void setRotationAxis(Point3D p0){} + public final void setScaleX(double p0){} + public final void setScaleY(double p0){} + public final void setScaleZ(double p0){} + public final void setStyle(String p0){} + public final void setTranslateX(double p0){} + public final void setTranslateY(double p0){} + public final void setTranslateZ(double p0){} + public final void setViewOrder(double p0){} + public final void setVisible(boolean p0){} + public static List> getClassCssMetaData(){ return null; } + public static double BASELINE_OFFSET_SAME_AS_HEIGHT = 0; + public void executeAccessibleAction(AccessibleAction p0, Object... p1){} + public void relocate(double p0, double p1){} + public void requestFocus(){} + public void resize(double p0, double p1){} + public void resizeRelocate(double p0, double p1, double p2, double p3){} + public void setUserData(Object p0){} + public void snapshot(Callback p0, SnapshotParameters p1, WritableImage p2){} + public void startFullDrag(){} + public void toBack(){} + public void toFront(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/Parent.java b/java/ql/test/stubs/javafx-web/javafx/scene/Parent.java new file mode 100644 index 00000000000..f702c6f4e70 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/Parent.java @@ -0,0 +1,37 @@ +// Generated automatically from javafx.scene.Parent for testing purposes + +package javafx.scene; + +import java.util.List; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.collections.ObservableList; +import javafx.scene.AccessibleAttribute; +import javafx.scene.Node; + +abstract public class Parent extends Node +{ + protected java.util.List getManagedChildren(){ return null; } + protected ObservableList getChildren(){ return null; } + protected Parent(){} + protected double computeMinHeight(double p0){ return 0; } + protected double computeMinWidth(double p0){ return 0; } + protected double computePrefHeight(double p0){ return 0; } + protected double computePrefWidth(double p0){ return 0; } + protected final void requestParentLayout(){} + protected final void setNeedsLayout(boolean p0){} + protected void layoutChildren(){} + protected void updateBounds(){} + public Node lookup(String p0){ return null; } + public Object queryAccessibleAttribute(AccessibleAttribute p0, Object... p1){ return null; } + public ObservableList getChildrenUnmodifiable(){ return null; } + public double getBaselineOffset(){ return 0; } + public double minHeight(double p0){ return 0; } + public double minWidth(double p0){ return 0; } + public double prefHeight(double p0){ return 0; } + public double prefWidth(double p0){ return 0; } + public final ObservableList getStylesheets(){ return null; } + public final ReadOnlyBooleanProperty needsLayoutProperty(){ return null; } + public final boolean isNeedsLayout(){ return false; } + public final void layout(){} + public void requestLayout(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/Scene.java b/java/ql/test/stubs/javafx-web/javafx/scene/Scene.java new file mode 100644 index 00000000000..cde4aa15e69 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/Scene.java @@ -0,0 +1,233 @@ +// Generated automatically from javafx.scene.Scene for testing purposes + +package javafx.scene; + +import com.sun.javafx.tk.TKClipboard; +import com.sun.javafx.tk.TKDragGestureListener; +import com.sun.javafx.tk.TKPulseListener; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; +import javafx.event.Event; +import javafx.event.EventDispatchChain; +import javafx.event.EventDispatcher; +import javafx.event.EventHandler; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.geometry.NodeOrientation; +import javafx.scene.Camera; +import javafx.scene.Cursor; +import javafx.scene.Node; +import javafx.scene.Parent; +import javafx.scene.SceneAntialiasing; +import javafx.scene.SnapshotResult; +import javafx.scene.image.WritableImage; +import javafx.scene.input.ContextMenuEvent; +import javafx.scene.input.DragEvent; +import javafx.scene.input.Dragboard; +import javafx.scene.input.InputMethodEvent; +import javafx.scene.input.KeyCombination; +import javafx.scene.input.KeyEvent; +import javafx.scene.input.Mnemonic; +import javafx.scene.input.MouseDragEvent; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.RotateEvent; +import javafx.scene.input.ScrollEvent; +import javafx.scene.input.SwipeEvent; +import javafx.scene.input.TouchEvent; +import javafx.scene.input.TransferMode; +import javafx.scene.input.ZoomEvent; +import javafx.scene.paint.Paint; +import javafx.stage.Window; +import javafx.util.Callback; + +public class Scene implements EventTarget +{ + protected Scene() {} + protected final void setEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public Dragboard startDragAndDrop(TransferMode... p0){ return null; } + public EventDispatchChain buildEventDispatchChain(EventDispatchChain p0){ return null; } + public Node lookup(String p0){ return null; } + public Object getUserData(){ return null; } + public ObservableMap> getMnemonics(){ return null; } + public ObservableMap getAccelerators(){ return null; } + public Scene(Parent p0){} + public Scene(Parent p0, Paint p1){} + public Scene(Parent p0, double p1, double p2){} + public Scene(Parent p0, double p1, double p2, Paint p3){} + public Scene(Parent p0, double p1, double p2, boolean p3){} + public Scene(Parent p0, double p1, double p2, boolean p3, SceneAntialiasing p4){} + public WritableImage snapshot(WritableImage p0){ return null; } + public boolean hasProperties(){ return false; } + public final void addEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void addEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final Camera getCamera(){ return null; } + public final Cursor getCursor(){ return null; } + public final EventDispatcher getEventDispatcher(){ return null; } + public final EventHandler getOnContextMenuRequested(){ return null; } + public final EventHandler getOnDragDone(){ return null; } + public final EventHandler getOnDragDropped(){ return null; } + public final EventHandler getOnDragEntered(){ return null; } + public final EventHandler getOnDragExited(){ return null; } + public final EventHandler getOnDragOver(){ return null; } + public final EventHandler getOnInputMethodTextChanged(){ return null; } + public final EventHandler getOnKeyPressed(){ return null; } + public final EventHandler getOnKeyReleased(){ return null; } + public final EventHandler getOnKeyTyped(){ return null; } + public final EventHandler getOnMouseDragEntered(){ return null; } + public final EventHandler getOnMouseDragExited(){ return null; } + public final EventHandler getOnMouseDragOver(){ return null; } + public final EventHandler getOnMouseDragReleased(){ return null; } + public final EventHandler getOnDragDetected(){ return null; } + public final EventHandler getOnMouseClicked(){ return null; } + public final EventHandler getOnMouseDragged(){ return null; } + public final EventHandler getOnMouseEntered(){ return null; } + public final EventHandler getOnMouseExited(){ return null; } + public final EventHandler getOnMouseMoved(){ return null; } + public final EventHandler getOnMousePressed(){ return null; } + public final EventHandler getOnMouseReleased(){ return null; } + public final EventHandler getOnRotate(){ return null; } + public final EventHandler getOnRotationFinished(){ return null; } + public final EventHandler getOnRotationStarted(){ return null; } + public final EventHandler getOnScroll(){ return null; } + public final EventHandler getOnScrollFinished(){ return null; } + public final EventHandler getOnScrollStarted(){ return null; } + public final EventHandler getOnSwipeDown(){ return null; } + public final EventHandler getOnSwipeLeft(){ return null; } + public final EventHandler getOnSwipeRight(){ return null; } + public final EventHandler getOnSwipeUp(){ return null; } + public final EventHandler getOnTouchMoved(){ return null; } + public final EventHandler getOnTouchPressed(){ return null; } + public final EventHandler getOnTouchReleased(){ return null; } + public final EventHandler getOnTouchStationary(){ return null; } + public final EventHandler getOnZoom(){ return null; } + public final EventHandler getOnZoomFinished(){ return null; } + public final EventHandler getOnZoomStarted(){ return null; } + public final Node getFocusOwner(){ return null; } + public final NodeOrientation getEffectiveNodeOrientation(){ return null; } + public final NodeOrientation getNodeOrientation(){ return null; } + public final ObjectProperty cameraProperty(){ return null; } + public final ObjectProperty cursorProperty(){ return null; } + public final ObjectProperty eventDispatcherProperty(){ return null; } + public final ObjectProperty> onContextMenuRequestedProperty(){ return null; } + public final ObjectProperty> onDragDoneProperty(){ return null; } + public final ObjectProperty> onDragDroppedProperty(){ return null; } + public final ObjectProperty> onDragEnteredProperty(){ return null; } + public final ObjectProperty> onDragExitedProperty(){ return null; } + public final ObjectProperty> onDragOverProperty(){ return null; } + public final ObjectProperty> onInputMethodTextChangedProperty(){ return null; } + public final ObjectProperty> onKeyPressedProperty(){ return null; } + public final ObjectProperty> onKeyReleasedProperty(){ return null; } + public final ObjectProperty> onKeyTypedProperty(){ return null; } + public final ObjectProperty> onMouseDragEnteredProperty(){ return null; } + public final ObjectProperty> onMouseDragExitedProperty(){ return null; } + public final ObjectProperty> onMouseDragOverProperty(){ return null; } + public final ObjectProperty> onMouseDragReleasedProperty(){ return null; } + public final ObjectProperty> onDragDetectedProperty(){ return null; } + public final ObjectProperty> onMouseClickedProperty(){ return null; } + public final ObjectProperty> onMouseDraggedProperty(){ return null; } + public final ObjectProperty> onMouseEnteredProperty(){ return null; } + public final ObjectProperty> onMouseExitedProperty(){ return null; } + public final ObjectProperty> onMouseMovedProperty(){ return null; } + public final ObjectProperty> onMousePressedProperty(){ return null; } + public final ObjectProperty> onMouseReleasedProperty(){ return null; } + public final ObjectProperty> onRotateProperty(){ return null; } + public final ObjectProperty> onRotationFinishedProperty(){ return null; } + public final ObjectProperty> onRotationStartedProperty(){ return null; } + public final ObjectProperty> onScrollFinishedProperty(){ return null; } + public final ObjectProperty> onScrollProperty(){ return null; } + public final ObjectProperty> onScrollStartedProperty(){ return null; } + public final ObjectProperty> onSwipeDownProperty(){ return null; } + public final ObjectProperty> onSwipeLeftProperty(){ return null; } + public final ObjectProperty> onSwipeRightProperty(){ return null; } + public final ObjectProperty> onSwipeUpProperty(){ return null; } + public final ObjectProperty> onTouchMovedProperty(){ return null; } + public final ObjectProperty> onTouchPressedProperty(){ return null; } + public final ObjectProperty> onTouchReleasedProperty(){ return null; } + public final ObjectProperty> onTouchStationaryProperty(){ return null; } + public final ObjectProperty> onZoomFinishedProperty(){ return null; } + public final ObjectProperty> onZoomProperty(){ return null; } + public final ObjectProperty> onZoomStartedProperty(){ return null; } + public final ObjectProperty nodeOrientationProperty(){ return null; } + public final ObjectProperty fillProperty(){ return null; } + public final ObjectProperty rootProperty(){ return null; } + public final ObjectProperty userAgentStylesheetProperty(){ return null; } + public final ObservableList getStylesheets(){ return null; } + public final ObservableMap getProperties(){ return null; } + public final Paint getFill(){ return null; } + public final Parent getRoot(){ return null; } + public final ReadOnlyDoubleProperty heightProperty(){ return null; } + public final ReadOnlyDoubleProperty widthProperty(){ return null; } + public final ReadOnlyDoubleProperty xProperty(){ return null; } + public final ReadOnlyDoubleProperty yProperty(){ return null; } + public final ReadOnlyObjectProperty focusOwnerProperty(){ return null; } + public final ReadOnlyObjectProperty effectiveNodeOrientationProperty(){ return null; } + public final ReadOnlyObjectProperty windowProperty(){ return null; } + public final SceneAntialiasing getAntiAliasing(){ return null; } + public final String getUserAgentStylesheet(){ return null; } + public final Window getWindow(){ return null; } + public final boolean isDepthBuffer(){ return false; } + public final double getHeight(){ return 0; } + public final double getWidth(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final void addPostLayoutPulseListener(Runnable p0){} + public final void addPreLayoutPulseListener(Runnable p0){} + public final void removePostLayoutPulseListener(Runnable p0){} + public final void removePreLayoutPulseListener(Runnable p0){} + public final void setCamera(Camera p0){} + public final void setCursor(Cursor p0){} + public final void setEventDispatcher(EventDispatcher p0){} + public final void setFill(Paint p0){} + public final void setNodeOrientation(NodeOrientation p0){} + public final void setOnContextMenuRequested(EventHandler p0){} + public final void setOnDragDetected(EventHandler p0){} + public final void setOnDragDone(EventHandler p0){} + public final void setOnDragDropped(EventHandler p0){} + public final void setOnDragEntered(EventHandler p0){} + public final void setOnDragExited(EventHandler p0){} + public final void setOnDragOver(EventHandler p0){} + public final void setOnInputMethodTextChanged(EventHandler p0){} + public final void setOnKeyPressed(EventHandler p0){} + public final void setOnKeyReleased(EventHandler p0){} + public final void setOnKeyTyped(EventHandler p0){} + public final void setOnMouseClicked(EventHandler p0){} + public final void setOnMouseDragEntered(EventHandler p0){} + public final void setOnMouseDragExited(EventHandler p0){} + public final void setOnMouseDragOver(EventHandler p0){} + public final void setOnMouseDragReleased(EventHandler p0){} + public final void setOnMouseDragged(EventHandler p0){} + public final void setOnMouseEntered(EventHandler p0){} + public final void setOnMouseExited(EventHandler p0){} + public final void setOnMouseMoved(EventHandler p0){} + public final void setOnMousePressed(EventHandler p0){} + public final void setOnMouseReleased(EventHandler p0){} + public final void setOnRotate(EventHandler p0){} + public final void setOnRotationFinished(EventHandler p0){} + public final void setOnRotationStarted(EventHandler p0){} + public final void setOnScroll(EventHandler p0){} + public final void setOnScrollFinished(EventHandler p0){} + public final void setOnScrollStarted(EventHandler p0){} + public final void setOnSwipeDown(EventHandler p0){} + public final void setOnSwipeLeft(EventHandler p0){} + public final void setOnSwipeRight(EventHandler p0){} + public final void setOnSwipeUp(EventHandler p0){} + public final void setOnTouchMoved(EventHandler p0){} + public final void setOnTouchPressed(EventHandler p0){} + public final void setOnTouchReleased(EventHandler p0){} + public final void setOnTouchStationary(EventHandler p0){} + public final void setOnZoom(EventHandler p0){} + public final void setOnZoomFinished(EventHandler p0){} + public final void setOnZoomStarted(EventHandler p0){} + public final void setRoot(Parent p0){} + public final void setUserAgentStylesheet(String p0){} + public void addMnemonic(Mnemonic p0){} + public void removeMnemonic(Mnemonic p0){} + public void setUserData(Object p0){} + public void snapshot(Callback p0, WritableImage p1){} + public void startFullDrag(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/SceneAntialiasing.java b/java/ql/test/stubs/javafx-web/javafx/scene/SceneAntialiasing.java new file mode 100644 index 00000000000..fc24f3f34ad --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/SceneAntialiasing.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.scene.SceneAntialiasing for testing purposes + +package javafx.scene; + + +public class SceneAntialiasing +{ + protected SceneAntialiasing() {} + public String toString(){ return null; } + public static SceneAntialiasing BALANCED = null; + public static SceneAntialiasing DISABLED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotParameters.java b/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotParameters.java new file mode 100644 index 00000000000..49abb2ce4cd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotParameters.java @@ -0,0 +1,23 @@ +// Generated automatically from javafx.scene.SnapshotParameters for testing purposes + +package javafx.scene; + +import javafx.geometry.Rectangle2D; +import javafx.scene.Camera; +import javafx.scene.paint.Paint; +import javafx.scene.transform.Transform; + +public class SnapshotParameters +{ + public Camera getCamera(){ return null; } + public Paint getFill(){ return null; } + public Rectangle2D getViewport(){ return null; } + public SnapshotParameters(){} + public Transform getTransform(){ return null; } + public boolean isDepthBuffer(){ return false; } + public void setCamera(Camera p0){} + public void setDepthBuffer(boolean p0){} + public void setFill(Paint p0){} + public void setTransform(Transform p0){} + public void setViewport(Rectangle2D p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotResult.java b/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotResult.java new file mode 100644 index 00000000000..cd3ed405f43 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/SnapshotResult.java @@ -0,0 +1,14 @@ +// Generated automatically from javafx.scene.SnapshotResult for testing purposes + +package javafx.scene; + +import javafx.scene.SnapshotParameters; +import javafx.scene.image.WritableImage; + +public class SnapshotResult +{ + protected SnapshotResult() {} + public Object getSource(){ return null; } + public SnapshotParameters getSnapshotParameters(){ return null; } + public WritableImage getImage(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/effect/BlendMode.java b/java/ql/test/stubs/javafx-web/javafx/scene/effect/BlendMode.java new file mode 100644 index 00000000000..e9f9dfa4245 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/effect/BlendMode.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.effect.BlendMode for testing purposes + +package javafx.scene.effect; + + +public enum BlendMode +{ + ADD, BLUE, COLOR_BURN, COLOR_DODGE, DARKEN, DIFFERENCE, EXCLUSION, GREEN, HARD_LIGHT, LIGHTEN, MULTIPLY, OVERLAY, RED, SCREEN, SOFT_LIGHT, SRC_ATOP, SRC_OVER; + private BlendMode() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/effect/Effect.java b/java/ql/test/stubs/javafx-web/javafx/scene/effect/Effect.java new file mode 100644 index 00000000000..fa10876cd28 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/effect/Effect.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.scene.effect.Effect for testing purposes + +package javafx.scene.effect; + + +abstract public class Effect +{ + protected Effect(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/Image.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/Image.java new file mode 100644 index 00000000000..2e367c28f05 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/Image.java @@ -0,0 +1,38 @@ +// Generated automatically from javafx.scene.image.Image for testing purposes + +package javafx.scene.image; + +import java.io.InputStream; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.scene.image.PixelReader; + +public class Image +{ + protected Image() {} + public Image(InputStream p0){} + public Image(InputStream p0, double p1, double p2, boolean p3, boolean p4){} + public Image(String p0){} + public Image(String p0, boolean p1){} + public Image(String p0, double p1, double p2, boolean p3, boolean p4){} + public Image(String p0, double p1, double p2, boolean p3, boolean p4, boolean p5){} + public final Exception getException(){ return null; } + public final PixelReader getPixelReader(){ return null; } + public final ReadOnlyBooleanProperty errorProperty(){ return null; } + public final ReadOnlyDoubleProperty heightProperty(){ return null; } + public final ReadOnlyDoubleProperty progressProperty(){ return null; } + public final ReadOnlyDoubleProperty widthProperty(){ return null; } + public final ReadOnlyObjectProperty exceptionProperty(){ return null; } + public final String getUrl(){ return null; } + public final boolean isBackgroundLoading(){ return false; } + public final boolean isError(){ return false; } + public final boolean isPreserveRatio(){ return false; } + public final boolean isSmooth(){ return false; } + public final double getHeight(){ return 0; } + public final double getProgress(){ return 0; } + public final double getRequestedHeight(){ return 0; } + public final double getRequestedWidth(){ return 0; } + public final double getWidth(){ return 0; } + public void cancel(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelBuffer.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelBuffer.java new file mode 100644 index 00000000000..bfb39a69668 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelBuffer.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.scene.image.PixelBuffer for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import javafx.geometry.Rectangle2D; +import javafx.scene.image.PixelFormat; +import javafx.util.Callback; + +public class PixelBuffer +{ + protected PixelBuffer() {} + public PixelBuffer(int p0, int p1, T p2, javafx.scene.image.PixelFormat p3){} + public T getBuffer(){ return null; } + public int getHeight(){ return 0; } + public int getWidth(){ return 0; } + public javafx.scene.image.PixelFormat getPixelFormat(){ return null; } + public void updateBuffer(Callback, Rectangle2D> p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelFormat.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelFormat.java new file mode 100644 index 00000000000..6aee71ccfd4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelFormat.java @@ -0,0 +1,29 @@ +// Generated automatically from javafx.scene.image.PixelFormat for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import javafx.scene.image.WritablePixelFormat; + +abstract public class PixelFormat +{ + protected PixelFormat() {} + public PixelFormat.Type getType(){ return null; } + public abstract boolean isPremultiplied(); + public abstract boolean isWritable(); + public abstract int getArgb(T p0, int p1, int p2, int p3); + public static PixelFormat createByteIndexedInstance(int[] p0){ return null; } + public static PixelFormat createByteIndexedPremultipliedInstance(int[] p0){ return null; } + public static PixelFormat getByteRgbInstance(){ return null; } + public static WritablePixelFormat getByteBgraInstance(){ return null; } + public static WritablePixelFormat getByteBgraPreInstance(){ return null; } + public static WritablePixelFormat getIntArgbInstance(){ return null; } + public static WritablePixelFormat getIntArgbPreInstance(){ return null; } + static public enum Type + { + BYTE_BGRA, BYTE_BGRA_PRE, BYTE_INDEXED, BYTE_RGB, INT_ARGB, INT_ARGB_PRE; + private Type() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelReader.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelReader.java new file mode 100644 index 00000000000..48591ae90ef --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelReader.java @@ -0,0 +1,20 @@ +// Generated automatically from javafx.scene.image.PixelReader for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import javafx.scene.image.PixelFormat; +import javafx.scene.image.WritablePixelFormat; +import javafx.scene.paint.Color; + +public interface PixelReader +{ + void getPixels(int p0, int p1, int p2, int p3, javafx.scene.image.WritablePixelFormat p4, T p5, int p6); + Color getColor(int p0, int p1); + PixelFormat getPixelFormat(); + int getArgb(int p0, int p1); + void getPixels(int p0, int p1, int p2, int p3, WritablePixelFormat p4, byte[] p5, int p6, int p7); + void getPixels(int p0, int p1, int p2, int p3, WritablePixelFormat p4, int[] p5, int p6, int p7); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelWriter.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelWriter.java new file mode 100644 index 00000000000..22df63d9ed2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/PixelWriter.java @@ -0,0 +1,21 @@ +// Generated automatically from javafx.scene.image.PixelWriter for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import javafx.scene.image.PixelFormat; +import javafx.scene.image.PixelReader; +import javafx.scene.paint.Color; + +public interface PixelWriter +{ + void setPixels(int p0, int p1, int p2, int p3, javafx.scene.image.PixelFormat p4, T p5, int p6); + PixelFormat getPixelFormat(); + void setArgb(int p0, int p1, int p2); + void setColor(int p0, int p1, Color p2); + void setPixels(int p0, int p1, int p2, int p3, PixelFormat p4, byte[] p5, int p6, int p7); + void setPixels(int p0, int p1, int p2, int p3, PixelFormat p4, int[] p5, int p6, int p7); + void setPixels(int p0, int p1, int p2, int p3, PixelReader p4, int p5, int p6); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/WritableImage.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/WritableImage.java new file mode 100644 index 00000000000..c01e0763a84 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/WritableImage.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.scene.image.WritableImage for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import javafx.scene.image.Image; +import javafx.scene.image.PixelBuffer; +import javafx.scene.image.PixelReader; +import javafx.scene.image.PixelWriter; + +public class WritableImage extends Image +{ + protected WritableImage() {} + public WritableImage(PixelBuffer p0){} + public WritableImage(PixelReader p0, int p1, int p2){} + public WritableImage(PixelReader p0, int p1, int p2, int p3, int p4){} + public WritableImage(int p0, int p1){} + public final PixelWriter getPixelWriter(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/image/WritablePixelFormat.java b/java/ql/test/stubs/javafx-web/javafx/scene/image/WritablePixelFormat.java new file mode 100644 index 00000000000..1d748267ef2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/image/WritablePixelFormat.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.scene.image.WritablePixelFormat for testing purposes + +package javafx.scene.image; + +import java.nio.Buffer; +import javafx.scene.image.PixelFormat; + +abstract public class WritablePixelFormat extends javafx.scene.image.PixelFormat +{ + protected WritablePixelFormat() {} + public abstract void setArgb(T p0, int p1, int p2, int p3, int p4); + public boolean isWritable(){ return false; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/Clipboard.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/Clipboard.java new file mode 100644 index 00000000000..f6919f62bcd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/Clipboard.java @@ -0,0 +1,33 @@ +// Generated automatically from javafx.scene.input.Clipboard for testing purposes + +package javafx.scene.input; + +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javafx.scene.image.Image; +import javafx.scene.input.DataFormat; + +public class Clipboard +{ + protected Clipboard() {} + public final Image getImage(){ return null; } + public final List getFiles(){ return null; } + public final Object getContent(DataFormat p0){ return null; } + public final Set getContentTypes(){ return null; } + public final String getHtml(){ return null; } + public final String getRtf(){ return null; } + public final String getString(){ return null; } + public final String getUrl(){ return null; } + public final boolean hasContent(DataFormat p0){ return false; } + public final boolean hasFiles(){ return false; } + public final boolean hasHtml(){ return false; } + public final boolean hasImage(){ return false; } + public final boolean hasRtf(){ return false; } + public final boolean hasString(){ return false; } + public final boolean hasUrl(){ return false; } + public final boolean setContent(Map p0){ return false; } + public final void clear(){} + public static Clipboard getSystemClipboard(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/ContextMenuEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/ContextMenuEvent.java new file mode 100644 index 00000000000..c702b64e0e9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/ContextMenuEvent.java @@ -0,0 +1,30 @@ +// Generated automatically from javafx.scene.input.ContextMenuEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.PickResult; + +public class ContextMenuEvent extends InputEvent +{ + protected ContextMenuEvent() {} + public ContextMenuEvent copyFor(Object p0, EventTarget p1){ return null; } + public ContextMenuEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, PickResult p6){} + public ContextMenuEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, PickResult p8){} + public EventType getEventType(){ return null; } + public String toString(){ return null; } + public boolean isKeyboardTrigger(){ return false; } + public final PickResult getPickResult(){ return null; } + public final double getSceneX(){ return 0; } + public final double getSceneY(){ return 0; } + public final double getScreenX(){ return 0; } + public final double getScreenY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public static EventType ANY = null; + public static EventType CONTEXT_MENU_REQUESTED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/DataFormat.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/DataFormat.java new file mode 100644 index 00000000000..ed69da87620 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/DataFormat.java @@ -0,0 +1,22 @@ +// Generated automatically from javafx.scene.input.DataFormat for testing purposes + +package javafx.scene.input; + +import java.util.Set; + +public class DataFormat +{ + protected DataFormat() {} + public DataFormat(String... p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final Set getIdentifiers(){ return null; } + public int hashCode(){ return 0; } + public static DataFormat FILES = null; + public static DataFormat HTML = null; + public static DataFormat IMAGE = null; + public static DataFormat PLAIN_TEXT = null; + public static DataFormat RTF = null; + public static DataFormat URL = null; + public static DataFormat lookupMimeType(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/DragEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/DragEvent.java new file mode 100644 index 00000000000..12cbdd2a777 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/DragEvent.java @@ -0,0 +1,48 @@ +// Generated automatically from javafx.scene.input.DragEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.Dragboard; +import javafx.scene.input.InputEvent; +import javafx.scene.input.PickResult; +import javafx.scene.input.TransferMode; + +public class DragEvent extends InputEvent +{ + protected DragEvent() {} + public DragEvent copyFor(Object p0, EventTarget p1){ return null; } + public DragEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public DragEvent copyFor(Object p0, EventTarget p1, Object p2, Object p3, EventType p4){ return null; } + public DragEvent(EventType p0, Dragboard p1, double p2, double p3, double p4, double p5, TransferMode p6, Object p7, Object p8, PickResult p9){} + public DragEvent(Object p0, EventTarget p1, EventType p2, Dragboard p3, double p4, double p5, double p6, double p7, TransferMode p8, Object p9, Object p10, PickResult p11){} + public EventType getEventType(){ return null; } + public boolean isDropCompleted(){ return false; } + public final Dragboard getDragboard(){ return null; } + public final Object getAcceptingObject(){ return null; } + public final Object getGestureSource(){ return null; } + public final Object getGestureTarget(){ return null; } + public final PickResult getPickResult(){ return null; } + public final TransferMode getAcceptedTransferMode(){ return null; } + public final TransferMode getTransferMode(){ return null; } + public final boolean isAccepted(){ return false; } + public final double getSceneX(){ return 0; } + public final double getSceneY(){ return 0; } + public final double getScreenX(){ return 0; } + public final double getScreenY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public static EventType ANY = null; + public static EventType DRAG_DONE = null; + public static EventType DRAG_DROPPED = null; + public static EventType DRAG_ENTERED = null; + public static EventType DRAG_ENTERED_TARGET = null; + public static EventType DRAG_EXITED = null; + public static EventType DRAG_EXITED_TARGET = null; + public static EventType DRAG_OVER = null; + public void acceptTransferModes(TransferMode... p0){} + public void setDropCompleted(boolean p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/Dragboard.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/Dragboard.java new file mode 100644 index 00000000000..0ed168a2c56 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/Dragboard.java @@ -0,0 +1,21 @@ +// Generated automatically from javafx.scene.input.Dragboard for testing purposes + +package javafx.scene.input; + +import java.util.Set; +import javafx.scene.image.Image; +import javafx.scene.input.Clipboard; +import javafx.scene.input.TransferMode; + +public class Dragboard extends Clipboard +{ + protected Dragboard() {} + public Image getDragView(){ return null; } + public double getDragViewOffsetX(){ return 0; } + public double getDragViewOffsetY(){ return 0; } + public final Set getTransferModes(){ return null; } + public void setDragView(Image p0){} + public void setDragView(Image p0, double p1, double p2){} + public void setDragViewOffsetX(double p0){} + public void setDragViewOffsetY(double p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/GestureEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/GestureEvent.java new file mode 100644 index 00000000000..dd89f9f8910 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/GestureEvent.java @@ -0,0 +1,37 @@ +// Generated automatically from javafx.scene.input.GestureEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.PickResult; + +public class GestureEvent extends InputEvent +{ + protected GestureEvent() {} + protected GestureEvent(EventType p0){} + protected GestureEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, boolean p10, PickResult p11){} + protected GestureEvent(Object p0, EventTarget p1, EventType p2){} + protected GestureEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, PickResult p13){} + public EventType getEventType(){ return null; } + public GestureEvent copyFor(Object p0, EventTarget p1){ return null; } + public String toString(){ return null; } + public boolean isInertia(){ return false; } + public final PickResult getPickResult(){ return null; } + public final boolean isAltDown(){ return false; } + public final boolean isControlDown(){ return false; } + public final boolean isDirect(){ return false; } + public final boolean isMetaDown(){ return false; } + public final boolean isShiftDown(){ return false; } + public final boolean isShortcutDown(){ return false; } + public final double getSceneX(){ return 0; } + public final double getSceneY(){ return 0; } + public final double getScreenX(){ return 0; } + public final double getScreenY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public static EventType ANY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/InputEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputEvent.java new file mode 100644 index 00000000000..6fe35500c56 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputEvent.java @@ -0,0 +1,16 @@ +// Generated automatically from javafx.scene.input.InputEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; + +public class InputEvent extends Event +{ + protected InputEvent() {} + public EventType getEventType(){ return null; } + public InputEvent(EventType p0){} + public InputEvent(Object p0, EventTarget p1, EventType p2){} + public static EventType ANY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodEvent.java new file mode 100644 index 00000000000..4df57f1f09f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodEvent.java @@ -0,0 +1,26 @@ +// Generated automatically from javafx.scene.input.InputMethodEvent for testing purposes + +package javafx.scene.input; + +import java.util.List; +import javafx.collections.ObservableList; +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.InputMethodTextRun; + +public class InputMethodEvent extends InputEvent +{ + protected InputMethodEvent() {} + public EventType getEventType(){ return null; } + public InputMethodEvent copyFor(Object p0, EventTarget p1){ return null; } + public InputMethodEvent(EventType p0, List p1, String p2, int p3){} + public InputMethodEvent(Object p0, EventTarget p1, EventType p2, List p3, String p4, int p5){} + public String toString(){ return null; } + public final ObservableList getComposed(){ return null; } + public final String getCommitted(){ return null; } + public final int getCaretPosition(){ return 0; } + public static EventType ANY = null; + public static EventType INPUT_METHOD_TEXT_CHANGED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodHighlight.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodHighlight.java new file mode 100644 index 00000000000..18ef7f1e178 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodHighlight.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.input.InputMethodHighlight for testing purposes + +package javafx.scene.input; + + +public enum InputMethodHighlight +{ + SELECTED_CONVERTED, SELECTED_RAW, UNSELECTED_CONVERTED, UNSELECTED_RAW; + private InputMethodHighlight() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodRequests.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodRequests.java new file mode 100644 index 00000000000..63cc3e0b393 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodRequests.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.scene.input.InputMethodRequests for testing purposes + +package javafx.scene.input; + +import javafx.geometry.Point2D; + +public interface InputMethodRequests +{ + Point2D getTextLocation(int p0); + String getSelectedText(); + int getLocationOffset(int p0, int p1); + void cancelLatestCommittedText(); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodTextRun.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodTextRun.java new file mode 100644 index 00000000000..8ee0aaa95ae --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/InputMethodTextRun.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.scene.input.InputMethodTextRun for testing purposes + +package javafx.scene.input; + +import java.io.Serializable; +import javafx.scene.input.InputMethodHighlight; + +public class InputMethodTextRun implements Serializable +{ + protected InputMethodTextRun() {} + public InputMethodTextRun(String p0, InputMethodHighlight p1){} + public String toString(){ return null; } + public final InputMethodHighlight getHighlight(){ return null; } + public final String getText(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCode.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCode.java new file mode 100644 index 00000000000..beef42511d9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCode.java @@ -0,0 +1,23 @@ +// Generated automatically from javafx.scene.input.KeyCode for testing purposes + +package javafx.scene.input; + + +public enum KeyCode +{ + A, ACCEPT, ADD, AGAIN, ALL_CANDIDATES, ALPHANUMERIC, ALT, ALT_GRAPH, AMPERSAND, ASTERISK, AT, B, BACK_QUOTE, BACK_SLASH, BACK_SPACE, BEGIN, BRACELEFT, BRACERIGHT, C, CANCEL, CAPS, CHANNEL_DOWN, CHANNEL_UP, CIRCUMFLEX, CLEAR, CLOSE_BRACKET, CODE_INPUT, COLON, COLORED_KEY_0, COLORED_KEY_1, COLORED_KEY_2, COLORED_KEY_3, COMMA, COMMAND, COMPOSE, CONTEXT_MENU, CONTROL, CONVERT, COPY, CUT, D, DEAD_ABOVEDOT, DEAD_ABOVERING, DEAD_ACUTE, DEAD_BREVE, DEAD_CARON, DEAD_CEDILLA, DEAD_CIRCUMFLEX, DEAD_DIAERESIS, DEAD_DOUBLEACUTE, DEAD_GRAVE, DEAD_IOTA, DEAD_MACRON, DEAD_OGONEK, DEAD_SEMIVOICED_SOUND, DEAD_TILDE, DEAD_VOICED_SOUND, DECIMAL, DELETE, DIGIT0, DIGIT1, DIGIT2, DIGIT3, DIGIT4, DIGIT5, DIGIT6, DIGIT7, DIGIT8, DIGIT9, DIVIDE, DOLLAR, DOWN, E, EJECT_TOGGLE, END, ENTER, EQUALS, ESCAPE, EURO_SIGN, EXCLAMATION_MARK, F, F1, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F2, F20, F21, F22, F23, F24, F3, F4, F5, F6, F7, F8, F9, FAST_FWD, FINAL, FIND, FULL_WIDTH, G, GAME_A, GAME_B, GAME_C, GAME_D, GREATER, H, HALF_WIDTH, HELP, HIRAGANA, HOME, I, INFO, INPUT_METHOD_ON_OFF, INSERT, INVERTED_EXCLAMATION_MARK, J, JAPANESE_HIRAGANA, JAPANESE_KATAKANA, JAPANESE_ROMAN, K, KANA, KANA_LOCK, KANJI, KATAKANA, KP_DOWN, KP_LEFT, KP_RIGHT, KP_UP, L, LEFT, LEFT_PARENTHESIS, LESS, M, META, MINUS, MODECHANGE, MULTIPLY, MUTE, N, NONCONVERT, NUMBER_SIGN, NUMPAD0, NUMPAD1, NUMPAD2, NUMPAD3, NUMPAD4, NUMPAD5, NUMPAD6, NUMPAD7, NUMPAD8, NUMPAD9, NUM_LOCK, O, OPEN_BRACKET, P, PAGE_DOWN, PAGE_UP, PASTE, PAUSE, PERIOD, PLAY, PLUS, POUND, POWER, PREVIOUS_CANDIDATE, PRINTSCREEN, PROPS, Q, QUOTE, QUOTEDBL, R, RECORD, REWIND, RIGHT, RIGHT_PARENTHESIS, ROMAN_CHARACTERS, S, SCROLL_LOCK, SEMICOLON, SEPARATOR, SHIFT, SHORTCUT, SLASH, SOFTKEY_0, SOFTKEY_1, SOFTKEY_2, SOFTKEY_3, SOFTKEY_4, SOFTKEY_5, SOFTKEY_6, SOFTKEY_7, SOFTKEY_8, SOFTKEY_9, SPACE, STAR, STOP, SUBTRACT, T, TAB, TRACK_NEXT, TRACK_PREV, U, UNDEFINED, UNDERSCORE, UNDO, UP, V, VOLUME_DOWN, VOLUME_UP, W, WINDOWS, X, Y, Z; + private KeyCode() {} + public final String getChar(){ return null; } + public final String getName(){ return null; } + public final boolean isArrowKey(){ return false; } + public final boolean isDigitKey(){ return false; } + public final boolean isFunctionKey(){ return false; } + public final boolean isKeypadKey(){ return false; } + public final boolean isLetterKey(){ return false; } + public final boolean isMediaKey(){ return false; } + public final boolean isModifierKey(){ return false; } + public final boolean isNavigationKey(){ return false; } + public final boolean isWhitespaceKey(){ return false; } + public final int getCode(){ return 0; } + public static KeyCode getKeyCode(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCombination.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCombination.java new file mode 100644 index 00000000000..15557be4a2c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyCombination.java @@ -0,0 +1,49 @@ +// Generated automatically from javafx.scene.input.KeyCombination for testing purposes + +package javafx.scene.input; + +import javafx.scene.input.KeyCode; +import javafx.scene.input.KeyEvent; + +abstract public class KeyCombination +{ + protected KeyCombination() {} + protected KeyCombination(KeyCombination.Modifier... p0){} + protected KeyCombination(KeyCombination.ModifierValue p0, KeyCombination.ModifierValue p1, KeyCombination.ModifierValue p2, KeyCombination.ModifierValue p3, KeyCombination.ModifierValue p4){} + public String getDisplayText(){ return null; } + public String getName(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean match(KeyEvent p0){ return false; } + public final KeyCombination.ModifierValue getAlt(){ return null; } + public final KeyCombination.ModifierValue getControl(){ return null; } + public final KeyCombination.ModifierValue getMeta(){ return null; } + public final KeyCombination.ModifierValue getShift(){ return null; } + public final KeyCombination.ModifierValue getShortcut(){ return null; } + public int hashCode(){ return 0; } + public static KeyCombination NO_MATCH = null; + public static KeyCombination keyCombination(String p0){ return null; } + public static KeyCombination valueOf(String p0){ return null; } + public static KeyCombination.Modifier ALT_ANY = null; + public static KeyCombination.Modifier ALT_DOWN = null; + public static KeyCombination.Modifier CONTROL_ANY = null; + public static KeyCombination.Modifier CONTROL_DOWN = null; + public static KeyCombination.Modifier META_ANY = null; + public static KeyCombination.Modifier META_DOWN = null; + public static KeyCombination.Modifier SHIFT_ANY = null; + public static KeyCombination.Modifier SHIFT_DOWN = null; + public static KeyCombination.Modifier SHORTCUT_ANY = null; + public static KeyCombination.Modifier SHORTCUT_DOWN = null; + static public class Modifier + { + protected Modifier() {} + public KeyCode getKey(){ return null; } + public KeyCombination.ModifierValue getValue(){ return null; } + public String toString(){ return null; } + } + static public enum ModifierValue + { + ANY, DOWN, UP; + private ModifierValue() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyEvent.java new file mode 100644 index 00000000000..eee4eea3d02 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/KeyEvent.java @@ -0,0 +1,33 @@ +// Generated automatically from javafx.scene.input.KeyEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.KeyCode; + +public class KeyEvent extends InputEvent +{ + protected KeyEvent() {} + public EventType getEventType(){ return null; } + public KeyEvent copyFor(Object p0, EventTarget p1){ return null; } + public KeyEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public KeyEvent(EventType p0, String p1, String p2, KeyCode p3, boolean p4, boolean p5, boolean p6, boolean p7){} + public KeyEvent(Object p0, EventTarget p1, EventType p2, String p3, String p4, KeyCode p5, boolean p6, boolean p7, boolean p8, boolean p9){} + public String toString(){ return null; } + public final KeyCode getCode(){ return null; } + public final String getCharacter(){ return null; } + public final String getText(){ return null; } + public final boolean isAltDown(){ return false; } + public final boolean isControlDown(){ return false; } + public final boolean isMetaDown(){ return false; } + public final boolean isShiftDown(){ return false; } + public final boolean isShortcutDown(){ return false; } + public static EventType ANY = null; + public static EventType KEY_PRESSED = null; + public static EventType KEY_RELEASED = null; + public static EventType KEY_TYPED = null; + public static String CHAR_UNDEFINED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/Mnemonic.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/Mnemonic.java new file mode 100644 index 00000000000..78a4a43f0d8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/Mnemonic.java @@ -0,0 +1,17 @@ +// Generated automatically from javafx.scene.input.Mnemonic for testing purposes + +package javafx.scene.input; + +import javafx.scene.Node; +import javafx.scene.input.KeyCombination; + +public class Mnemonic +{ + protected Mnemonic() {} + public KeyCombination getKeyCombination(){ return null; } + public Mnemonic(Node p0, KeyCombination p1){} + public Node getNode(){ return null; } + public void fire(){} + public void setKeyCombination(KeyCombination p0){} + public void setNode(Node p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseButton.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseButton.java new file mode 100644 index 00000000000..ee534db97cc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseButton.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.input.MouseButton for testing purposes + +package javafx.scene.input; + + +public enum MouseButton +{ + BACK, FORWARD, MIDDLE, NONE, PRIMARY, SECONDARY; + private MouseButton() {} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseDragEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseDragEvent.java new file mode 100644 index 00000000000..aec5cc71277 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseDragEvent.java @@ -0,0 +1,30 @@ +// Generated automatically from javafx.scene.input.MouseDragEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseEvent; +import javafx.scene.input.PickResult; + +public class MouseDragEvent extends MouseEvent +{ + protected MouseDragEvent() {} + public EventType getEventType(){ return null; } + public MouseDragEvent copyFor(Object p0, EventTarget p1){ return null; } + public MouseDragEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public MouseDragEvent(EventType p0, double p1, double p2, double p3, double p4, MouseButton p5, int p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, PickResult p16, Object p17){} + public MouseDragEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, MouseButton p7, int p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, boolean p17, PickResult p18, Object p19){} + public MouseDragEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, MouseButton p7, int p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, boolean p17, boolean p18, boolean p19, PickResult p20, Object p21){} + public Object getGestureSource(){ return null; } + public String toString(){ return null; } + public static EventType ANY = null; + public static EventType MOUSE_DRAG_ENTERED = null; + public static EventType MOUSE_DRAG_ENTERED_TARGET = null; + public static EventType MOUSE_DRAG_EXITED = null; + public static EventType MOUSE_DRAG_EXITED_TARGET = null; + public static EventType MOUSE_DRAG_OVER = null; + public static EventType MOUSE_DRAG_RELEASED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseEvent.java new file mode 100644 index 00000000000..2aa1552d9b5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/MouseEvent.java @@ -0,0 +1,61 @@ +// Generated automatically from javafx.scene.input.MouseEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.MouseButton; +import javafx.scene.input.MouseDragEvent; +import javafx.scene.input.PickResult; + +public class MouseEvent extends InputEvent +{ + protected MouseEvent() {} + public EventType getEventType(){ return null; } + public MouseEvent copyFor(Object p0, EventTarget p1){ return null; } + public MouseEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public MouseEvent(EventType p0, double p1, double p2, double p3, double p4, MouseButton p5, int p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, PickResult p17){} + public MouseEvent(EventType p0, double p1, double p2, double p3, double p4, MouseButton p5, int p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, boolean p17, boolean p18, PickResult p19){} + public MouseEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, MouseButton p7, int p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, boolean p17, boolean p18, PickResult p19){} + public MouseEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, MouseButton p7, int p8, boolean p9, boolean p10, boolean p11, boolean p12, boolean p13, boolean p14, boolean p15, boolean p16, boolean p17, boolean p18, boolean p19, boolean p20, PickResult p21){} + public String toString(){ return null; } + public boolean isDragDetect(){ return false; } + public boolean isSynthesized(){ return false; } + public final MouseButton getButton(){ return null; } + public final PickResult getPickResult(){ return null; } + public final boolean isAltDown(){ return false; } + public final boolean isBackButtonDown(){ return false; } + public final boolean isControlDown(){ return false; } + public final boolean isForwardButtonDown(){ return false; } + public final boolean isMetaDown(){ return false; } + public final boolean isMiddleButtonDown(){ return false; } + public final boolean isPopupTrigger(){ return false; } + public final boolean isPrimaryButtonDown(){ return false; } + public final boolean isSecondaryButtonDown(){ return false; } + public final boolean isShiftDown(){ return false; } + public final boolean isShortcutDown(){ return false; } + public final boolean isStillSincePress(){ return false; } + public final double getSceneX(){ return 0; } + public final double getSceneY(){ return 0; } + public final double getScreenX(){ return 0; } + public final double getScreenY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public final int getClickCount(){ return 0; } + public static EventType ANY = null; + public static EventType DRAG_DETECTED = null; + public static EventType MOUSE_CLICKED = null; + public static EventType MOUSE_DRAGGED = null; + public static EventType MOUSE_ENTERED = null; + public static EventType MOUSE_ENTERED_TARGET = null; + public static EventType MOUSE_EXITED = null; + public static EventType MOUSE_EXITED_TARGET = null; + public static EventType MOUSE_MOVED = null; + public static EventType MOUSE_PRESSED = null; + public static EventType MOUSE_RELEASED = null; + public static MouseDragEvent copyForMouseDragEvent(MouseEvent p0, Object p1, EventTarget p2, EventType p3, Object p4, PickResult p5){ return null; } + public void setDragDetect(boolean p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/PickResult.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/PickResult.java new file mode 100644 index 00000000000..90aeabfa936 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/PickResult.java @@ -0,0 +1,25 @@ +// Generated automatically from javafx.scene.input.PickResult for testing purposes + +package javafx.scene.input; + +import javafx.event.EventTarget; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.Node; + +public class PickResult +{ + protected PickResult() {} + public PickResult(EventTarget p0, double p1, double p2){} + public PickResult(Node p0, Point3D p1, double p2){} + public PickResult(Node p0, Point3D p1, double p2, int p3, Point2D p4){} + public PickResult(Node p0, Point3D p1, double p2, int p3, Point3D p4, Point2D p5){} + public String toString(){ return null; } + public final Node getIntersectedNode(){ return null; } + public final Point2D getIntersectedTexCoord(){ return null; } + public final Point3D getIntersectedNormal(){ return null; } + public final Point3D getIntersectedPoint(){ return null; } + public final double getIntersectedDistance(){ return 0; } + public final int getIntersectedFace(){ return 0; } + public static int FACE_UNDEFINED = 0; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/RotateEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/RotateEvent.java new file mode 100644 index 00000000000..501d004b5ff --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/RotateEvent.java @@ -0,0 +1,26 @@ +// Generated automatically from javafx.scene.input.RotateEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.GestureEvent; +import javafx.scene.input.PickResult; + +public class RotateEvent extends GestureEvent +{ + protected RotateEvent() {} + public EventType getEventType(){ return null; } + public RotateEvent copyFor(Object p0, EventTarget p1){ return null; } + public RotateEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public RotateEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, boolean p10, double p11, double p12, PickResult p13){} + public RotateEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, double p13, double p14, PickResult p15){} + public String toString(){ return null; } + public double getAngle(){ return 0; } + public double getTotalAngle(){ return 0; } + public static EventType ANY = null; + public static EventType ROTATE = null; + public static EventType ROTATION_FINISHED = null; + public static EventType ROTATION_STARTED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/ScrollEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/ScrollEvent.java new file mode 100644 index 00000000000..de34b90cbe8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/ScrollEvent.java @@ -0,0 +1,46 @@ +// Generated automatically from javafx.scene.input.ScrollEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.GestureEvent; +import javafx.scene.input.PickResult; + +public class ScrollEvent extends GestureEvent +{ + protected ScrollEvent() {} + public EventType getEventType(){ return null; } + public ScrollEvent copyFor(Object p0, EventTarget p1){ return null; } + public ScrollEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public ScrollEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, boolean p10, double p11, double p12, double p13, double p14, ScrollEvent.HorizontalTextScrollUnits p15, double p16, ScrollEvent.VerticalTextScrollUnits p17, double p18, int p19, PickResult p20){} + public ScrollEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, boolean p10, double p11, double p12, double p13, double p14, double p15, double p16, ScrollEvent.HorizontalTextScrollUnits p17, double p18, ScrollEvent.VerticalTextScrollUnits p19, double p20, int p21, PickResult p22){} + public ScrollEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, double p13, double p14, double p15, double p16, ScrollEvent.HorizontalTextScrollUnits p17, double p18, ScrollEvent.VerticalTextScrollUnits p19, double p20, int p21, PickResult p22){} + public ScrollEvent.HorizontalTextScrollUnits getTextDeltaXUnits(){ return null; } + public ScrollEvent.VerticalTextScrollUnits getTextDeltaYUnits(){ return null; } + public String toString(){ return null; } + public double getDeltaX(){ return 0; } + public double getDeltaY(){ return 0; } + public double getMultiplierX(){ return 0; } + public double getMultiplierY(){ return 0; } + public double getTextDeltaX(){ return 0; } + public double getTextDeltaY(){ return 0; } + public double getTotalDeltaX(){ return 0; } + public double getTotalDeltaY(){ return 0; } + public int getTouchCount(){ return 0; } + public static EventType ANY = null; + public static EventType SCROLL = null; + public static EventType SCROLL_FINISHED = null; + public static EventType SCROLL_STARTED = null; + static public enum HorizontalTextScrollUnits + { + CHARACTERS, NONE; + private HorizontalTextScrollUnits() {} + } + static public enum VerticalTextScrollUnits + { + LINES, NONE, PAGES; + private VerticalTextScrollUnits() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/SwipeEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/SwipeEvent.java new file mode 100644 index 00000000000..7e2545f2897 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/SwipeEvent.java @@ -0,0 +1,26 @@ +// Generated automatically from javafx.scene.input.SwipeEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.GestureEvent; +import javafx.scene.input.PickResult; + +public class SwipeEvent extends GestureEvent +{ + protected SwipeEvent() {} + public EventType getEventType(){ return null; } + public String toString(){ return null; } + public SwipeEvent copyFor(Object p0, EventTarget p1){ return null; } + public SwipeEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public SwipeEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, int p10, PickResult p11){} + public SwipeEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, int p12, PickResult p13){} + public int getTouchCount(){ return 0; } + public static EventType ANY = null; + public static EventType SWIPE_DOWN = null; + public static EventType SWIPE_LEFT = null; + public static EventType SWIPE_RIGHT = null; + public static EventType SWIPE_UP = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchEvent.java new file mode 100644 index 00000000000..20fc62821d1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchEvent.java @@ -0,0 +1,34 @@ +// Generated automatically from javafx.scene.input.TouchEvent for testing purposes + +package javafx.scene.input; + +import java.util.List; +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.InputEvent; +import javafx.scene.input.TouchPoint; + +public class TouchEvent extends InputEvent +{ + protected TouchEvent() {} + public EventType getEventType(){ return null; } + public List getTouchPoints(){ return null; } + public String toString(){ return null; } + public TouchEvent copyFor(Object p0, EventTarget p1){ return null; } + public TouchEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public TouchEvent(EventType p0, TouchPoint p1, List p2, int p3, boolean p4, boolean p5, boolean p6, boolean p7){} + public TouchEvent(Object p0, EventTarget p1, EventType p2, TouchPoint p3, List p4, int p5, boolean p6, boolean p7, boolean p8, boolean p9){} + public TouchPoint getTouchPoint(){ return null; } + public final boolean isAltDown(){ return false; } + public final boolean isControlDown(){ return false; } + public final boolean isMetaDown(){ return false; } + public final boolean isShiftDown(){ return false; } + public final int getEventSetId(){ return 0; } + public int getTouchCount(){ return 0; } + public static EventType ANY = null; + public static EventType TOUCH_MOVED = null; + public static EventType TOUCH_PRESSED = null; + public static EventType TOUCH_RELEASED = null; + public static EventType TOUCH_STATIONARY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchPoint.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchPoint.java new file mode 100644 index 00000000000..08a21c1e6d4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/TouchPoint.java @@ -0,0 +1,35 @@ +// Generated automatically from javafx.scene.input.TouchPoint for testing purposes + +package javafx.scene.input; + +import java.io.Serializable; +import javafx.event.EventTarget; +import javafx.scene.input.PickResult; + +public class TouchPoint implements Serializable +{ + protected TouchPoint() {} + public EventTarget getGrabbed(){ return null; } + public EventTarget getTarget(){ return null; } + public String toString(){ return null; } + public TouchPoint(int p0, TouchPoint.State p1, double p2, double p3, double p4, double p5, EventTarget p6, PickResult p7){} + public boolean belongsTo(EventTarget p0){ return false; } + public final PickResult getPickResult(){ return null; } + public final TouchPoint.State getState(){ return null; } + public final double getSceneX(){ return 0; } + public final double getSceneY(){ return 0; } + public final double getScreenX(){ return 0; } + public final double getScreenY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public final int getId(){ return 0; } + public void grab(){} + public void grab(EventTarget p0){} + public void ungrab(){} + static public enum State + { + MOVED, PRESSED, RELEASED, STATIONARY; + private State() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/TransferMode.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/TransferMode.java new file mode 100644 index 00000000000..9c2075cd936 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/TransferMode.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.scene.input.TransferMode for testing purposes + +package javafx.scene.input; + + +public enum TransferMode +{ + COPY, LINK, MOVE; + private TransferMode() {} + public static TransferMode[] ANY = null; + public static TransferMode[] COPY_OR_MOVE = null; + public static TransferMode[] NONE = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/input/ZoomEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/input/ZoomEvent.java new file mode 100644 index 00000000000..bd7fe470544 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/input/ZoomEvent.java @@ -0,0 +1,26 @@ +// Generated automatically from javafx.scene.input.ZoomEvent for testing purposes + +package javafx.scene.input; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.input.GestureEvent; +import javafx.scene.input.PickResult; + +public class ZoomEvent extends GestureEvent +{ + protected ZoomEvent() {} + public EventType getEventType(){ return null; } + public String toString(){ return null; } + public ZoomEvent copyFor(Object p0, EventTarget p1){ return null; } + public ZoomEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public ZoomEvent(EventType p0, double p1, double p2, double p3, double p4, boolean p5, boolean p6, boolean p7, boolean p8, boolean p9, boolean p10, double p11, double p12, PickResult p13){} + public ZoomEvent(Object p0, EventTarget p1, EventType p2, double p3, double p4, double p5, double p6, boolean p7, boolean p8, boolean p9, boolean p10, boolean p11, boolean p12, double p13, double p14, PickResult p15){} + public double getTotalZoomFactor(){ return 0; } + public double getZoomFactor(){ return 0; } + public static EventType ANY = null; + public static EventType ZOOM = null; + public static EventType ZOOM_FINISHED = null; + public static EventType ZOOM_STARTED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/paint/Color.java b/java/ql/test/stubs/javafx-web/javafx/scene/paint/Color.java new file mode 100644 index 00000000000..0c8193004bd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/paint/Color.java @@ -0,0 +1,192 @@ +// Generated automatically from javafx.scene.paint.Color for testing purposes + +package javafx.scene.paint; + +import javafx.animation.Interpolatable; +import javafx.scene.paint.Paint; + +public class Color extends Paint implements Interpolatable +{ + protected Color() {} + public Color brighter(){ return null; } + public Color darker(){ return null; } + public Color deriveColor(double p0, double p1, double p2, double p3){ return null; } + public Color desaturate(){ return null; } + public Color grayscale(){ return null; } + public Color interpolate(Color p0, double p1){ return null; } + public Color invert(){ return null; } + public Color saturate(){ return null; } + public Color(double p0, double p1, double p2, double p3){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public double getBrightness(){ return 0; } + public double getHue(){ return 0; } + public double getSaturation(){ return 0; } + public final boolean isOpaque(){ return false; } + public final double getBlue(){ return 0; } + public final double getGreen(){ return 0; } + public final double getOpacity(){ return 0; } + public final double getRed(){ return 0; } + public int hashCode(){ return 0; } + public static Color ALICEBLUE = null; + public static Color ANTIQUEWHITE = null; + public static Color AQUA = null; + public static Color AQUAMARINE = null; + public static Color AZURE = null; + public static Color BEIGE = null; + public static Color BISQUE = null; + public static Color BLACK = null; + public static Color BLANCHEDALMOND = null; + public static Color BLUE = null; + public static Color BLUEVIOLET = null; + public static Color BROWN = null; + public static Color BURLYWOOD = null; + public static Color CADETBLUE = null; + public static Color CHARTREUSE = null; + public static Color CHOCOLATE = null; + public static Color CORAL = null; + public static Color CORNFLOWERBLUE = null; + public static Color CORNSILK = null; + public static Color CRIMSON = null; + public static Color CYAN = null; + public static Color DARKBLUE = null; + public static Color DARKCYAN = null; + public static Color DARKGOLDENROD = null; + public static Color DARKGRAY = null; + public static Color DARKGREEN = null; + public static Color DARKGREY = null; + public static Color DARKKHAKI = null; + public static Color DARKMAGENTA = null; + public static Color DARKOLIVEGREEN = null; + public static Color DARKORANGE = null; + public static Color DARKORCHID = null; + public static Color DARKRED = null; + public static Color DARKSALMON = null; + public static Color DARKSEAGREEN = null; + public static Color DARKSLATEBLUE = null; + public static Color DARKSLATEGRAY = null; + public static Color DARKSLATEGREY = null; + public static Color DARKTURQUOISE = null; + public static Color DARKVIOLET = null; + public static Color DEEPPINK = null; + public static Color DEEPSKYBLUE = null; + public static Color DIMGRAY = null; + public static Color DIMGREY = null; + public static Color DODGERBLUE = null; + public static Color FIREBRICK = null; + public static Color FLORALWHITE = null; + public static Color FORESTGREEN = null; + public static Color FUCHSIA = null; + public static Color GAINSBORO = null; + public static Color GHOSTWHITE = null; + public static Color GOLD = null; + public static Color GOLDENROD = null; + public static Color GRAY = null; + public static Color GREEN = null; + public static Color GREENYELLOW = null; + public static Color GREY = null; + public static Color HONEYDEW = null; + public static Color HOTPINK = null; + public static Color INDIANRED = null; + public static Color INDIGO = null; + public static Color IVORY = null; + public static Color KHAKI = null; + public static Color LAVENDER = null; + public static Color LAVENDERBLUSH = null; + public static Color LAWNGREEN = null; + public static Color LEMONCHIFFON = null; + public static Color LIGHTBLUE = null; + public static Color LIGHTCORAL = null; + public static Color LIGHTCYAN = null; + public static Color LIGHTGOLDENRODYELLOW = null; + public static Color LIGHTGRAY = null; + public static Color LIGHTGREEN = null; + public static Color LIGHTGREY = null; + public static Color LIGHTPINK = null; + public static Color LIGHTSALMON = null; + public static Color LIGHTSEAGREEN = null; + public static Color LIGHTSKYBLUE = null; + public static Color LIGHTSLATEGRAY = null; + public static Color LIGHTSLATEGREY = null; + public static Color LIGHTSTEELBLUE = null; + public static Color LIGHTYELLOW = null; + public static Color LIME = null; + public static Color LIMEGREEN = null; + public static Color LINEN = null; + public static Color MAGENTA = null; + public static Color MAROON = null; + public static Color MEDIUMAQUAMARINE = null; + public static Color MEDIUMBLUE = null; + public static Color MEDIUMORCHID = null; + public static Color MEDIUMPURPLE = null; + public static Color MEDIUMSEAGREEN = null; + public static Color MEDIUMSLATEBLUE = null; + public static Color MEDIUMSPRINGGREEN = null; + public static Color MEDIUMTURQUOISE = null; + public static Color MEDIUMVIOLETRED = null; + public static Color MIDNIGHTBLUE = null; + public static Color MINTCREAM = null; + public static Color MISTYROSE = null; + public static Color MOCCASIN = null; + public static Color NAVAJOWHITE = null; + public static Color NAVY = null; + public static Color OLDLACE = null; + public static Color OLIVE = null; + public static Color OLIVEDRAB = null; + public static Color ORANGE = null; + public static Color ORANGERED = null; + public static Color ORCHID = null; + public static Color PALEGOLDENROD = null; + public static Color PALEGREEN = null; + public static Color PALETURQUOISE = null; + public static Color PALEVIOLETRED = null; + public static Color PAPAYAWHIP = null; + public static Color PEACHPUFF = null; + public static Color PERU = null; + public static Color PINK = null; + public static Color PLUM = null; + public static Color POWDERBLUE = null; + public static Color PURPLE = null; + public static Color RED = null; + public static Color ROSYBROWN = null; + public static Color ROYALBLUE = null; + public static Color SADDLEBROWN = null; + public static Color SALMON = null; + public static Color SANDYBROWN = null; + public static Color SEAGREEN = null; + public static Color SEASHELL = null; + public static Color SIENNA = null; + public static Color SILVER = null; + public static Color SKYBLUE = null; + public static Color SLATEBLUE = null; + public static Color SLATEGRAY = null; + public static Color SLATEGREY = null; + public static Color SNOW = null; + public static Color SPRINGGREEN = null; + public static Color STEELBLUE = null; + public static Color TAN = null; + public static Color TEAL = null; + public static Color THISTLE = null; + public static Color TOMATO = null; + public static Color TRANSPARENT = null; + public static Color TURQUOISE = null; + public static Color VIOLET = null; + public static Color WHEAT = null; + public static Color WHITE = null; + public static Color WHITESMOKE = null; + public static Color YELLOW = null; + public static Color YELLOWGREEN = null; + public static Color color(double p0, double p1, double p2){ return null; } + public static Color color(double p0, double p1, double p2, double p3){ return null; } + public static Color gray(double p0){ return null; } + public static Color gray(double p0, double p1){ return null; } + public static Color grayRgb(int p0){ return null; } + public static Color grayRgb(int p0, double p1){ return null; } + public static Color hsb(double p0, double p1, double p2){ return null; } + public static Color hsb(double p0, double p1, double p2, double p3){ return null; } + public static Color rgb(int p0, int p1, int p2){ return null; } + public static Color rgb(int p0, int p1, int p2, double p3){ return null; } + public static Color valueOf(String p0){ return null; } + public static Color web(String p0){ return null; } + public static Color web(String p0, double p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/paint/Paint.java b/java/ql/test/stubs/javafx-web/javafx/scene/paint/Paint.java new file mode 100644 index 00000000000..acfb631309f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/paint/Paint.java @@ -0,0 +1,10 @@ +// Generated automatically from javafx.scene.paint.Paint for testing purposes + +package javafx.scene.paint; + + +abstract public class Paint +{ + public abstract boolean isOpaque(); + public static Paint valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/text/Font.java b/java/ql/test/stubs/javafx-web/javafx/scene/text/Font.java new file mode 100644 index 00000000000..a8319a5a648 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/text/Font.java @@ -0,0 +1,36 @@ +// Generated automatically from javafx.scene.text.Font for testing purposes + +package javafx.scene.text; + +import java.io.InputStream; +import java.util.List; +import javafx.scene.text.FontPosture; +import javafx.scene.text.FontWeight; + +public class Font +{ + protected Font() {} + public Font(String p0, double p1){} + public Font(double p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final String getFamily(){ return null; } + public final String getName(){ return null; } + public final String getStyle(){ return null; } + public final double getSize(){ return 0; } + public int hashCode(){ return 0; } + public static Font font(String p0){ return null; } + public static Font font(String p0, FontPosture p1, double p2){ return null; } + public static Font font(String p0, FontWeight p1, FontPosture p2, double p3){ return null; } + public static Font font(String p0, FontWeight p1, double p2){ return null; } + public static Font font(String p0, double p1){ return null; } + public static Font font(double p0){ return null; } + public static Font getDefault(){ return null; } + public static Font loadFont(InputStream p0, double p1){ return null; } + public static Font loadFont(String p0, double p1){ return null; } + public static Font[] loadFonts(InputStream p0, double p1){ return null; } + public static Font[] loadFonts(String p0, double p1){ return null; } + public static List getFamilies(){ return null; } + public static List getFontNames(){ return null; } + public static List getFontNames(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/text/FontPosture.java b/java/ql/test/stubs/javafx-web/javafx/scene/text/FontPosture.java new file mode 100644 index 00000000000..4916e6e0f24 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/text/FontPosture.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.scene.text.FontPosture for testing purposes + +package javafx.scene.text; + + +public enum FontPosture +{ + ITALIC, REGULAR; + private FontPosture() {} + public static FontPosture findByName(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/text/FontWeight.java b/java/ql/test/stubs/javafx-web/javafx/scene/text/FontWeight.java new file mode 100644 index 00000000000..9babffe0202 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/text/FontWeight.java @@ -0,0 +1,13 @@ +// Generated automatically from javafx.scene.text.FontWeight for testing purposes + +package javafx.scene.text; + + +public enum FontWeight +{ + BLACK, BOLD, EXTRA_BOLD, EXTRA_LIGHT, LIGHT, MEDIUM, NORMAL, SEMI_BOLD, THIN; + private FontWeight() {} + public int getWeight(){ return 0; } + public static FontWeight findByName(String p0){ return null; } + public static FontWeight findByWeight(int p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Affine.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Affine.java new file mode 100644 index 00000000000..aabe869c990 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Affine.java @@ -0,0 +1,116 @@ +// Generated automatically from javafx.scene.transform.Affine for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.DoubleProperty; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.MatrixType; +import javafx.scene.transform.Transform; + +public class Affine extends Transform +{ + public Affine clone(){ return null; } + public Affine createInverse(){ return null; } + public Affine(){} + public Affine(Transform p0){} + public Affine(double p0, double p1, double p2, double p3, double p4, double p5){} + public Affine(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11){} + public Affine(double[] p0, MatrixType p1, int p2){} + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public String toString(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public double determinant(){ return 0; } + public final DoubleProperty mxxProperty(){ return null; } + public final DoubleProperty mxyProperty(){ return null; } + public final DoubleProperty mxzProperty(){ return null; } + public final DoubleProperty myxProperty(){ return null; } + public final DoubleProperty myyProperty(){ return null; } + public final DoubleProperty myzProperty(){ return null; } + public final DoubleProperty mzxProperty(){ return null; } + public final DoubleProperty mzyProperty(){ return null; } + public final DoubleProperty mzzProperty(){ return null; } + public final DoubleProperty txProperty(){ return null; } + public final DoubleProperty tyProperty(){ return null; } + public final DoubleProperty tzProperty(){ return null; } + public final double getMxx(){ return 0; } + public final double getMxy(){ return 0; } + public final double getMxz(){ return 0; } + public final double getMyx(){ return 0; } + public final double getMyy(){ return 0; } + public final double getMyz(){ return 0; } + public final double getMzx(){ return 0; } + public final double getMzy(){ return 0; } + public final double getMzz(){ return 0; } + public final double getTx(){ return 0; } + public final double getTy(){ return 0; } + public final double getTz(){ return 0; } + public final void setMxx(double p0){} + public final void setMxy(double p0){} + public final void setMxz(double p0){} + public final void setMyx(double p0){} + public final void setMyy(double p0){} + public final void setMyz(double p0){} + public final void setMzx(double p0){} + public final void setMzy(double p0){} + public final void setMzz(double p0){} + public final void setTx(double p0){} + public final void setTy(double p0){} + public final void setTz(double p0){} + public void append(Transform p0){} + public void append(double p0, double p1, double p2, double p3, double p4, double p5){} + public void append(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11){} + public void append(double[] p0, MatrixType p1, int p2){} + public void appendRotation(double p0){} + public void appendRotation(double p0, Point2D p1){} + public void appendRotation(double p0, Point3D p1, Point3D p2){} + public void appendRotation(double p0, double p1, double p2){} + public void appendRotation(double p0, double p1, double p2, double p3, Point3D p4){} + public void appendRotation(double p0, double p1, double p2, double p3, double p4, double p5, double p6){} + public void appendScale(double p0, double p1){} + public void appendScale(double p0, double p1, Point2D p2){} + public void appendScale(double p0, double p1, double p2){} + public void appendScale(double p0, double p1, double p2, Point3D p3){} + public void appendScale(double p0, double p1, double p2, double p3){} + public void appendScale(double p0, double p1, double p2, double p3, double p4, double p5){} + public void appendShear(double p0, double p1){} + public void appendShear(double p0, double p1, Point2D p2){} + public void appendShear(double p0, double p1, double p2, double p3){} + public void appendTranslation(double p0, double p1){} + public void appendTranslation(double p0, double p1, double p2){} + public void invert(){} + public void prepend(Transform p0){} + public void prepend(double p0, double p1, double p2, double p3, double p4, double p5){} + public void prepend(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11){} + public void prepend(double[] p0, MatrixType p1, int p2){} + public void prependRotation(double p0){} + public void prependRotation(double p0, Point2D p1){} + public void prependRotation(double p0, Point3D p1, Point3D p2){} + public void prependRotation(double p0, double p1, double p2){} + public void prependRotation(double p0, double p1, double p2, double p3, Point3D p4){} + public void prependRotation(double p0, double p1, double p2, double p3, double p4, double p5, double p6){} + public void prependScale(double p0, double p1){} + public void prependScale(double p0, double p1, Point2D p2){} + public void prependScale(double p0, double p1, double p2){} + public void prependScale(double p0, double p1, double p2, Point3D p3){} + public void prependScale(double p0, double p1, double p2, double p3){} + public void prependScale(double p0, double p1, double p2, double p3, double p4, double p5){} + public void prependShear(double p0, double p1){} + public void prependShear(double p0, double p1, Point2D p2){} + public void prependShear(double p0, double p1, double p2, double p3){} + public void prependTranslation(double p0, double p1){} + public void prependTranslation(double p0, double p1, double p2){} + public void setElement(MatrixType p0, int p1, int p2, double p3){} + public void setToIdentity(){} + public void setToTransform(Transform p0){} + public void setToTransform(double p0, double p1, double p2, double p3, double p4, double p5){} + public void setToTransform(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11){} + public void setToTransform(double[] p0, MatrixType p1, int p2){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/MatrixType.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/MatrixType.java new file mode 100644 index 00000000000..d9d0619c5b1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/MatrixType.java @@ -0,0 +1,14 @@ +// Generated automatically from javafx.scene.transform.MatrixType for testing purposes + +package javafx.scene.transform; + + +public enum MatrixType +{ + MT_2D_2x3, MT_2D_3x3, MT_3D_3x4, MT_3D_4x4; + private MatrixType() {} + public boolean is2D(){ return false; } + public int columns(){ return 0; } + public int elements(){ return 0; } + public int rows(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Rotate.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Rotate.java new file mode 100644 index 00000000000..f13d97ff389 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Rotate.java @@ -0,0 +1,62 @@ +// Generated automatically from javafx.scene.transform.Rotate for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.Transform; + +public class Rotate extends Transform +{ + protected void transformChanged(){} + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public Rotate clone(){ return null; } + public Rotate(){} + public Rotate(double p0){} + public Rotate(double p0, Point3D p1){} + public Rotate(double p0, double p1, double p2){} + public Rotate(double p0, double p1, double p2, double p3){} + public Rotate(double p0, double p1, double p2, double p3, Point3D p4){} + public String toString(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public Transform createInverse(){ return null; } + public double getMxx(){ return 0; } + public double getMxy(){ return 0; } + public double getMxz(){ return 0; } + public double getMyx(){ return 0; } + public double getMyy(){ return 0; } + public double getMyz(){ return 0; } + public double getMzx(){ return 0; } + public double getMzy(){ return 0; } + public double getMzz(){ return 0; } + public double getTx(){ return 0; } + public double getTy(){ return 0; } + public double getTz(){ return 0; } + public final DoubleProperty angleProperty(){ return null; } + public final DoubleProperty pivotXProperty(){ return null; } + public final DoubleProperty pivotYProperty(){ return null; } + public final DoubleProperty pivotZProperty(){ return null; } + public final ObjectProperty axisProperty(){ return null; } + public final Point3D getAxis(){ return null; } + public final double getAngle(){ return 0; } + public final double getPivotX(){ return 0; } + public final double getPivotY(){ return 0; } + public final double getPivotZ(){ return 0; } + public final void setAngle(double p0){} + public final void setAxis(Point3D p0){} + public final void setPivotX(double p0){} + public final void setPivotY(double p0){} + public final void setPivotZ(double p0){} + public static Point3D X_AXIS = null; + public static Point3D Y_AXIS = null; + public static Point3D Z_AXIS = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Scale.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Scale.java new file mode 100644 index 00000000000..be3dd62baa9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Scale.java @@ -0,0 +1,53 @@ +// Generated automatically from javafx.scene.transform.Scale for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.DoubleProperty; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.Transform; + +public class Scale extends Transform +{ + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public Scale clone(){ return null; } + public Scale createInverse(){ return null; } + public Scale(){} + public Scale(double p0, double p1){} + public Scale(double p0, double p1, double p2){} + public Scale(double p0, double p1, double p2, double p3){} + public Scale(double p0, double p1, double p2, double p3, double p4, double p5){} + public String toString(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public double getMxx(){ return 0; } + public double getMyy(){ return 0; } + public double getMzz(){ return 0; } + public double getTx(){ return 0; } + public double getTy(){ return 0; } + public double getTz(){ return 0; } + public final DoubleProperty pivotXProperty(){ return null; } + public final DoubleProperty pivotYProperty(){ return null; } + public final DoubleProperty pivotZProperty(){ return null; } + public final DoubleProperty xProperty(){ return null; } + public final DoubleProperty yProperty(){ return null; } + public final DoubleProperty zProperty(){ return null; } + public final double getPivotX(){ return 0; } + public final double getPivotY(){ return 0; } + public final double getPivotZ(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public final void setPivotX(double p0){} + public final void setPivotY(double p0){} + public final void setPivotZ(double p0){} + public final void setX(double p0){} + public final void setY(double p0){} + public final void setZ(double p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Shear.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Shear.java new file mode 100644 index 00000000000..3bf3e2ea2dd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Shear.java @@ -0,0 +1,43 @@ +// Generated automatically from javafx.scene.transform.Shear for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.DoubleProperty; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.Transform; + +public class Shear extends Transform +{ + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public Shear clone(){ return null; } + public Shear(){} + public Shear(double p0, double p1){} + public Shear(double p0, double p1, double p2, double p3){} + public String toString(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public Transform createInverse(){ return null; } + public double getMxy(){ return 0; } + public double getMyx(){ return 0; } + public double getTx(){ return 0; } + public double getTy(){ return 0; } + public final DoubleProperty pivotXProperty(){ return null; } + public final DoubleProperty pivotYProperty(){ return null; } + public final DoubleProperty xProperty(){ return null; } + public final DoubleProperty yProperty(){ return null; } + public final double getPivotX(){ return 0; } + public final double getPivotY(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final void setPivotX(double p0){} + public final void setPivotY(double p0){} + public final void setX(double p0){} + public final void setY(double p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Transform.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Transform.java new file mode 100644 index 00000000000..2c4ac734a25 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Transform.java @@ -0,0 +1,93 @@ +// Generated automatically from javafx.scene.transform.Transform for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.event.Event; +import javafx.event.EventDispatchChain; +import javafx.event.EventHandler; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.geometry.Bounds; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.Affine; +import javafx.scene.transform.MatrixType; +import javafx.scene.transform.Rotate; +import javafx.scene.transform.Scale; +import javafx.scene.transform.Shear; +import javafx.scene.transform.TransformChangedEvent; +import javafx.scene.transform.Translate; + +abstract public class Transform implements Cloneable, EventTarget +{ + protected void transformChanged(){} + public Bounds inverseTransform(Bounds p0){ return null; } + public Bounds transform(Bounds p0){ return null; } + public EventDispatchChain buildEventDispatchChain(EventDispatchChain p0){ return null; } + public Point2D deltaTransform(Point2D p0){ return null; } + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(Point2D p0){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(Point2D p0){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(Point2D p0){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(Point3D p0){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(Point3D p0){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(Point3D p0){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(Point3D p0){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public Transform clone(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public Transform createInverse(){ return null; } + public Transform(){} + public boolean similarTo(Transform p0, Bounds p1, double p2){ return false; } + public double determinant(){ return 0; } + public double getElement(MatrixType p0, int p1, int p2){ return 0; } + public double getMxx(){ return 0; } + public double getMxy(){ return 0; } + public double getMxz(){ return 0; } + public double getMyx(){ return 0; } + public double getMyy(){ return 0; } + public double getMyz(){ return 0; } + public double getMzx(){ return 0; } + public double getMzy(){ return 0; } + public double getMzz(){ return 0; } + public double getTx(){ return 0; } + public double getTy(){ return 0; } + public double getTz(){ return 0; } + public double[] column(MatrixType p0, int p1){ return null; } + public double[] column(MatrixType p0, int p1, double[] p2){ return null; } + public double[] row(MatrixType p0, int p1){ return null; } + public double[] row(MatrixType p0, int p1, double[] p2){ return null; } + public double[] toArray(MatrixType p0){ return null; } + public double[] toArray(MatrixType p0, double[] p1){ return null; } + public final void addEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void addEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final EventHandler getOnTransformChanged(){ return null; } + public final ObjectProperty> onTransformChangedProperty(){ return null; } + public final ReadOnlyBooleanProperty identityProperty(){ return null; } + public final ReadOnlyBooleanProperty type2DProperty(){ return null; } + public final boolean isIdentity(){ return false; } + public final boolean isType2D(){ return false; } + public final void setOnTransformChanged(EventHandler p0){} + public static Affine affine(double p0, double p1, double p2, double p3, double p4, double p5){ return null; } + public static Affine affine(double p0, double p1, double p2, double p3, double p4, double p5, double p6, double p7, double p8, double p9, double p10, double p11){ return null; } + public static Rotate rotate(double p0, double p1, double p2){ return null; } + public static Scale scale(double p0, double p1){ return null; } + public static Scale scale(double p0, double p1, double p2, double p3){ return null; } + public static Shear shear(double p0, double p1){ return null; } + public static Shear shear(double p0, double p1, double p2, double p3){ return null; } + public static Translate translate(double p0, double p1){ return null; } + public void inverseTransform2DPoints(double[] p0, int p1, double[] p2, int p3, int p4){} + public void inverseTransform3DPoints(double[] p0, int p1, double[] p2, int p3, int p4){} + public void transform2DPoints(double[] p0, int p1, double[] p2, int p3, int p4){} + public void transform3DPoints(double[] p0, int p1, double[] p2, int p3, int p4){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/TransformChangedEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/TransformChangedEvent.java new file mode 100644 index 00000000000..99d09a029c1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/TransformChangedEvent.java @@ -0,0 +1,15 @@ +// Generated automatically from javafx.scene.transform.TransformChangedEvent for testing purposes + +package javafx.scene.transform; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; + +public class TransformChangedEvent extends Event +{ + public TransformChangedEvent(){} + public TransformChangedEvent(Object p0, EventTarget p1){} + public static EventType ANY = null; + public static EventType TRANSFORM_CHANGED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/transform/Translate.java b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Translate.java new file mode 100644 index 00000000000..1051a35b7b5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/transform/Translate.java @@ -0,0 +1,43 @@ +// Generated automatically from javafx.scene.transform.Translate for testing purposes + +package javafx.scene.transform; + +import javafx.beans.property.DoubleProperty; +import javafx.geometry.Point2D; +import javafx.geometry.Point3D; +import javafx.scene.transform.Transform; + +public class Translate extends Transform +{ + public Point2D deltaTransform(Point2D p0){ return null; } + public Point2D deltaTransform(double p0, double p1){ return null; } + public Point2D inverseDeltaTransform(Point2D p0){ return null; } + public Point2D inverseDeltaTransform(double p0, double p1){ return null; } + public Point2D inverseTransform(double p0, double p1){ return null; } + public Point2D transform(double p0, double p1){ return null; } + public Point3D deltaTransform(Point3D p0){ return null; } + public Point3D deltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseDeltaTransform(Point3D p0){ return null; } + public Point3D inverseDeltaTransform(double p0, double p1, double p2){ return null; } + public Point3D inverseTransform(double p0, double p1, double p2){ return null; } + public Point3D transform(double p0, double p1, double p2){ return null; } + public String toString(){ return null; } + public Transform createConcatenation(Transform p0){ return null; } + public Translate clone(){ return null; } + public Translate createInverse(){ return null; } + public Translate(){} + public Translate(double p0, double p1){} + public Translate(double p0, double p1, double p2){} + public double getTx(){ return 0; } + public double getTy(){ return 0; } + public double getTz(){ return 0; } + public final DoubleProperty xProperty(){ return null; } + public final DoubleProperty yProperty(){ return null; } + public final DoubleProperty zProperty(){ return null; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final double getZ(){ return 0; } + public final void setX(double p0){} + public final void setY(double p0){} + public final void setZ(double p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/PopupFeatures.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/PopupFeatures.java new file mode 100644 index 00000000000..0841b1e85a0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/PopupFeatures.java @@ -0,0 +1,14 @@ +// Generated automatically from javafx.scene.web.PopupFeatures for testing purposes + +package javafx.scene.web; + + +public class PopupFeatures +{ + protected PopupFeatures() {} + public PopupFeatures(boolean p0, boolean p1, boolean p2, boolean p3){} + public final boolean hasMenu(){ return false; } + public final boolean hasStatus(){ return false; } + public final boolean hasToolbar(){ return false; } + public final boolean isResizable(){ return false; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/PromptData.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/PromptData.java new file mode 100644 index 00000000000..18cee457f60 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/PromptData.java @@ -0,0 +1,12 @@ +// Generated automatically from javafx.scene.web.PromptData for testing purposes + +package javafx.scene.web; + + +public class PromptData +{ + protected PromptData() {} + public PromptData(String p0, String p1){} + public final String getDefaultValue(){ return null; } + public final String getMessage(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEngine.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEngine.java new file mode 100644 index 00000000000..638f381fd49 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEngine.java @@ -0,0 +1,78 @@ +// Generated automatically from javafx.scene.web.WebEngine for testing purposes + +package javafx.scene.web; + +import java.io.File; +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.beans.property.ReadOnlyStringProperty; +import javafx.beans.property.StringProperty; +import javafx.concurrent.Worker; +import javafx.event.Event; +import javafx.event.EventHandler; +import javafx.geometry.Rectangle2D; +import javafx.print.PrinterJob; +import javafx.scene.web.PopupFeatures; +import javafx.scene.web.PromptData; +import javafx.scene.web.WebErrorEvent; +import javafx.scene.web.WebEvent; +import javafx.scene.web.WebHistory; +import javafx.util.Callback; +import org.w3c.dom.Document; + +public class WebEngine +{ + public Object executeScript(String p0){ return null; } + public WebEngine(){} + public WebEngine(String p0){} + public WebHistory getHistory(){ return null; } + public final BooleanProperty javaScriptEnabledProperty(){ return null; } + public final Callback getCreatePopupHandler(){ return null; } + public final Callback getPromptHandler(){ return null; } + public final Callback getConfirmHandler(){ return null; } + public final Document getDocument(){ return null; } + public final EventHandler getOnError(){ return null; } + public final EventHandler> getOnVisibilityChanged(){ return null; } + public final EventHandler> getOnResized(){ return null; } + public final EventHandler> getOnAlert(){ return null; } + public final EventHandler> getOnStatusChanged(){ return null; } + public final File getUserDataDirectory(){ return null; } + public final ObjectProperty> createPopupHandlerProperty(){ return null; } + public final ObjectProperty> promptHandlerProperty(){ return null; } + public final ObjectProperty> confirmHandlerProperty(){ return null; } + public final ObjectProperty> onErrorProperty(){ return null; } + public final ObjectProperty>> onVisibilityChangedProperty(){ return null; } + public final ObjectProperty>> onResizedProperty(){ return null; } + public final ObjectProperty>> onAlertProperty(){ return null; } + public final ObjectProperty>> onStatusChangedProperty(){ return null; } + public final ObjectProperty userDataDirectoryProperty(){ return null; } + public final ReadOnlyObjectProperty documentProperty(){ return null; } + public final ReadOnlyStringProperty locationProperty(){ return null; } + public final ReadOnlyStringProperty titleProperty(){ return null; } + public final String getLocation(){ return null; } + public final String getTitle(){ return null; } + public final String getUserAgent(){ return null; } + public final String getUserStyleSheetLocation(){ return null; } + public final StringProperty userAgentProperty(){ return null; } + public final StringProperty userStyleSheetLocationProperty(){ return null; } + public final Worker getLoadWorker(){ return null; } + public final boolean isJavaScriptEnabled(){ return false; } + public final void setConfirmHandler(Callback p0){} + public final void setCreatePopupHandler(Callback p0){} + public final void setJavaScriptEnabled(boolean p0){} + public final void setOnAlert(EventHandler> p0){} + public final void setOnError(EventHandler p0){} + public final void setOnResized(EventHandler> p0){} + public final void setOnStatusChanged(EventHandler> p0){} + public final void setOnVisibilityChanged(EventHandler> p0){} + public final void setPromptHandler(Callback p0){} + public final void setUserAgent(String p0){} + public final void setUserDataDirectory(File p0){} + public final void setUserStyleSheetLocation(String p0){} + public void load(String p0){} + public void loadContent(String p0){} + public void loadContent(String p0, String p1){} + public void print(PrinterJob p0){} + public void reload(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/WebErrorEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebErrorEvent.java new file mode 100644 index 00000000000..99f56e8fa55 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebErrorEvent.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.scene.web.WebErrorEvent for testing purposes + +package javafx.scene.web; + +import javafx.event.Event; +import javafx.event.EventType; + +public class WebErrorEvent extends Event +{ + protected WebErrorEvent() {} + public String getMessage(){ return null; } + public String toString(){ return null; } + public Throwable getException(){ return null; } + public WebErrorEvent(Object p0, EventType p1, String p2, Throwable p3){} + public static EventType ANY = null; + public static EventType USER_DATA_DIRECTORY_ALREADY_IN_USE = null; + public static EventType USER_DATA_DIRECTORY_IO_ERROR = null; + public static EventType USER_DATA_DIRECTORY_SECURITY_ERROR = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEvent.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEvent.java new file mode 100644 index 00000000000..971cf8f5426 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebEvent.java @@ -0,0 +1,19 @@ +// Generated automatically from javafx.scene.web.WebEvent for testing purposes + +package javafx.scene.web; + +import javafx.event.Event; +import javafx.event.EventType; + +public class WebEvent extends Event +{ + protected WebEvent() {} + public String toString(){ return null; } + public T getData(){ return null; } + public WebEvent(Object p0, EventType p1, T p2){} + public static EventType ALERT = null; + public static EventType ANY = null; + public static EventType RESIZED = null; + public static EventType STATUS_CHANGED = null; + public static EventType VISIBILITY_CHANGED = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/scene/web/WebHistory.java b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebHistory.java new file mode 100644 index 00000000000..40e59ffdab0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/scene/web/WebHistory.java @@ -0,0 +1,30 @@ +// Generated automatically from javafx.scene.web.WebHistory for testing purposes + +package javafx.scene.web; + +import javafx.beans.property.IntegerProperty; +import javafx.beans.property.ReadOnlyIntegerProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.collections.ObservableList; + +public class WebHistory +{ + protected WebHistory() {} + public IntegerProperty maxSizeProperty(){ return null; } + public ObservableList getEntries(){ return null; } + public ReadOnlyIntegerProperty currentIndexProperty(){ return null; } + public class Entry + { + protected Entry() {} + public ReadOnlyObjectProperty titleProperty(){ return null; } + public ReadOnlyObjectProperty lastVisitedDateProperty(){ return null; } + public String getTitle(){ return null; } + public String getUrl(){ return null; } + public String toString(){ return null; } + public java.util.Date getLastVisitedDate(){ return null; } + } + public int getCurrentIndex(){ return 0; } + public int getMaxSize(){ return 0; } + public void go(int p0){} + public void setMaxSize(int p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/stage/Window.java b/java/ql/test/stubs/javafx-web/javafx/stage/Window.java new file mode 100644 index 00000000000..958b5648bf0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/stage/Window.java @@ -0,0 +1,95 @@ +// Generated automatically from javafx.stage.Window for testing purposes + +package javafx.stage; + +import javafx.beans.property.BooleanProperty; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.ObjectProperty; +import javafx.beans.property.ReadOnlyBooleanProperty; +import javafx.beans.property.ReadOnlyDoubleProperty; +import javafx.beans.property.ReadOnlyObjectProperty; +import javafx.collections.ObservableList; +import javafx.collections.ObservableMap; +import javafx.event.Event; +import javafx.event.EventDispatchChain; +import javafx.event.EventDispatcher; +import javafx.event.EventHandler; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.scene.Scene; +import javafx.stage.WindowEvent; + +public class Window implements EventTarget +{ + protected Window(){} + protected final void setEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + protected void setScene(Scene p0){} + protected void show(){} + public EventDispatchChain buildEventDispatchChain(EventDispatchChain p0){ return null; } + public Object getUserData(){ return null; } + public boolean hasProperties(){ return false; } + public final void addEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void addEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventFilter(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final void removeEventHandler(javafx.event.EventType p0, javafx.event.EventHandler p1){} + public final BooleanProperty forceIntegerRenderScaleProperty(){ return null; } + public final DoubleProperty opacityProperty(){ return null; } + public final DoubleProperty renderScaleXProperty(){ return null; } + public final DoubleProperty renderScaleYProperty(){ return null; } + public final EventDispatcher getEventDispatcher(){ return null; } + public final EventHandler getOnCloseRequest(){ return null; } + public final EventHandler getOnHidden(){ return null; } + public final EventHandler getOnHiding(){ return null; } + public final EventHandler getOnShowing(){ return null; } + public final EventHandler getOnShown(){ return null; } + public final ObjectProperty eventDispatcherProperty(){ return null; } + public final ObjectProperty> onCloseRequestProperty(){ return null; } + public final ObjectProperty> onHiddenProperty(){ return null; } + public final ObjectProperty> onHidingProperty(){ return null; } + public final ObjectProperty> onShowingProperty(){ return null; } + public final ObjectProperty> onShownProperty(){ return null; } + public final ObservableMap getProperties(){ return null; } + public final ReadOnlyBooleanProperty focusedProperty(){ return null; } + public final ReadOnlyBooleanProperty showingProperty(){ return null; } + public final ReadOnlyDoubleProperty heightProperty(){ return null; } + public final ReadOnlyDoubleProperty outputScaleXProperty(){ return null; } + public final ReadOnlyDoubleProperty outputScaleYProperty(){ return null; } + public final ReadOnlyDoubleProperty widthProperty(){ return null; } + public final ReadOnlyDoubleProperty xProperty(){ return null; } + public final ReadOnlyDoubleProperty yProperty(){ return null; } + public final ReadOnlyObjectProperty sceneProperty(){ return null; } + public final Scene getScene(){ return null; } + public final boolean isFocused(){ return false; } + public final boolean isForceIntegerRenderScale(){ return false; } + public final boolean isShowing(){ return false; } + public final double getHeight(){ return 0; } + public final double getOpacity(){ return 0; } + public final double getOutputScaleX(){ return 0; } + public final double getOutputScaleY(){ return 0; } + public final double getRenderScaleX(){ return 0; } + public final double getRenderScaleY(){ return 0; } + public final double getWidth(){ return 0; } + public final double getX(){ return 0; } + public final double getY(){ return 0; } + public final void fireEvent(Event p0){} + public final void requestFocus(){} + public final void setEventDispatcher(EventDispatcher p0){} + public final void setForceIntegerRenderScale(boolean p0){} + public final void setHeight(double p0){} + public final void setOnCloseRequest(EventHandler p0){} + public final void setOnHidden(EventHandler p0){} + public final void setOnHiding(EventHandler p0){} + public final void setOnShowing(EventHandler p0){} + public final void setOnShown(EventHandler p0){} + public final void setOpacity(double p0){} + public final void setRenderScaleX(double p0){} + public final void setRenderScaleY(double p0){} + public final void setWidth(double p0){} + public final void setX(double p0){} + public final void setY(double p0){} + public static ObservableList getWindows(){ return null; } + public void centerOnScreen(){} + public void hide(){} + public void setUserData(Object p0){} + public void sizeToScene(){} +} diff --git a/java/ql/test/stubs/javafx-web/javafx/stage/WindowEvent.java b/java/ql/test/stubs/javafx-web/javafx/stage/WindowEvent.java new file mode 100644 index 00000000000..895955e52f7 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/stage/WindowEvent.java @@ -0,0 +1,24 @@ +// Generated automatically from javafx.stage.WindowEvent for testing purposes + +package javafx.stage; + +import javafx.event.Event; +import javafx.event.EventTarget; +import javafx.event.EventType; +import javafx.stage.Window; + +public class WindowEvent extends Event +{ + protected WindowEvent() {} + public EventType getEventType(){ return null; } + public String toString(){ return null; } + public WindowEvent copyFor(Object p0, EventTarget p1){ return null; } + public WindowEvent copyFor(Object p0, EventTarget p1, EventType p2){ return null; } + public WindowEvent(Window p0, EventType p1){} + public static EventType ANY = null; + public static EventType WINDOW_CLOSE_REQUEST = null; + public static EventType WINDOW_HIDDEN = null; + public static EventType WINDOW_HIDING = null; + public static EventType WINDOW_SHOWING = null; + public static EventType WINDOW_SHOWN = null; +} diff --git a/java/ql/test/stubs/javafx-web/javafx/util/Callback.java b/java/ql/test/stubs/javafx-web/javafx/util/Callback.java new file mode 100644 index 00000000000..6a2369c9806 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/util/Callback.java @@ -0,0 +1,9 @@ +// Generated automatically from javafx.util.Callback for testing purposes + +package javafx.util; + + +public interface Callback +{ + R call(P p0); +} diff --git a/java/ql/test/stubs/javafx-web/javafx/util/Duration.java b/java/ql/test/stubs/javafx-web/javafx/util/Duration.java new file mode 100644 index 00000000000..30b60c08618 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/util/Duration.java @@ -0,0 +1,41 @@ +// Generated automatically from javafx.util.Duration for testing purposes + +package javafx.util; + +import java.io.Serializable; + +public class Duration implements Serializable, java.lang.Comparable +{ + protected Duration() {} + public Duration add(Duration p0){ return null; } + public Duration divide(Duration p0){ return null; } + public Duration divide(double p0){ return null; } + public Duration multiply(Duration p0){ return null; } + public Duration multiply(double p0){ return null; } + public Duration negate(){ return null; } + public Duration subtract(Duration p0){ return null; } + public Duration(double p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean greaterThan(Duration p0){ return false; } + public boolean greaterThanOrEqualTo(Duration p0){ return false; } + public boolean isIndefinite(){ return false; } + public boolean isUnknown(){ return false; } + public boolean lessThan(Duration p0){ return false; } + public boolean lessThanOrEqualTo(Duration p0){ return false; } + public double toHours(){ return 0; } + public double toMillis(){ return 0; } + public double toMinutes(){ return 0; } + public double toSeconds(){ return 0; } + public int compareTo(Duration p0){ return 0; } + public int hashCode(){ return 0; } + public static Duration INDEFINITE = null; + public static Duration ONE = null; + public static Duration UNKNOWN = null; + public static Duration ZERO = null; + public static Duration hours(double p0){ return null; } + public static Duration millis(double p0){ return null; } + public static Duration minutes(double p0){ return null; } + public static Duration seconds(double p0){ return null; } + public static Duration valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/util/Pair.java b/java/ql/test/stubs/javafx-web/javafx/util/Pair.java new file mode 100644 index 00000000000..86d76d98cf6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/util/Pair.java @@ -0,0 +1,16 @@ +// Generated automatically from javafx.util.Pair for testing purposes + +package javafx.util; + +import java.io.Serializable; + +public class Pair implements Serializable +{ + protected Pair() {} + public K getKey(){ return null; } + public Pair(K p0, V p1){} + public String toString(){ return null; } + public V getValue(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javafx/util/StringConverter.java b/java/ql/test/stubs/javafx-web/javafx/util/StringConverter.java new file mode 100644 index 00000000000..7a89a4cb5df --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javafx/util/StringConverter.java @@ -0,0 +1,11 @@ +// Generated automatically from javafx.util.StringConverter for testing purposes + +package javafx.util; + + +abstract public class StringConverter +{ + public StringConverter(){} + public abstract String toString(T p0); + public abstract T fromString(String p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ServerSocketFactory.java b/java/ql/test/stubs/javafx-web/javax/net/ServerSocketFactory.java new file mode 100644 index 00000000000..2f4732a4ec0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ServerSocketFactory.java @@ -0,0 +1,16 @@ +// Generated automatically from javax.net.ServerSocketFactory for testing purposes + +package javax.net; + +import java.net.InetAddress; +import java.net.ServerSocket; + +abstract public class ServerSocketFactory +{ + protected ServerSocketFactory(){} + public ServerSocket createServerSocket(){ return null; } + public abstract ServerSocket createServerSocket(int p0); + public abstract ServerSocket createServerSocket(int p0, int p1); + public abstract ServerSocket createServerSocket(int p0, int p1, InetAddress p2); + public static ServerSocketFactory getDefault(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/SocketFactory.java b/java/ql/test/stubs/javafx-web/javax/net/SocketFactory.java new file mode 100644 index 00000000000..ddab28a7fc8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/SocketFactory.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.net.SocketFactory for testing purposes + +package javax.net; + +import java.net.InetAddress; +import java.net.Socket; + +abstract public class SocketFactory +{ + protected SocketFactory(){} + public Socket createSocket(){ return null; } + public abstract Socket createSocket(InetAddress p0, int p1); + public abstract Socket createSocket(InetAddress p0, int p1, InetAddress p2, int p3); + public abstract Socket createSocket(String p0, int p1); + public abstract Socket createSocket(String p0, int p1, InetAddress p2, int p3); + public static SocketFactory getDefault(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/HostnameVerifier.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/HostnameVerifier.java new file mode 100644 index 00000000000..891b2623061 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/HostnameVerifier.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.net.ssl.HostnameVerifier for testing purposes + +package javax.net.ssl; + +import javax.net.ssl.SSLSession; + +public interface HostnameVerifier +{ + boolean verify(String p0, SSLSession p1); +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/KeyManager.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/KeyManager.java new file mode 100644 index 00000000000..f7333612723 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/KeyManager.java @@ -0,0 +1,8 @@ +// Generated automatically from javax.net.ssl.KeyManager for testing purposes + +package javax.net.ssl; + + +public interface KeyManager +{ +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIMatcher.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIMatcher.java new file mode 100644 index 00000000000..4a346519f18 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIMatcher.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.net.ssl.SNIMatcher for testing purposes + +package javax.net.ssl; + +import javax.net.ssl.SNIServerName; + +abstract public class SNIMatcher +{ + protected SNIMatcher() {} + protected SNIMatcher(int p0){} + public abstract boolean matches(SNIServerName p0); + public final int getType(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIServerName.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIServerName.java new file mode 100644 index 00000000000..119f884b2e6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SNIServerName.java @@ -0,0 +1,15 @@ +// Generated automatically from javax.net.ssl.SNIServerName for testing purposes + +package javax.net.ssl; + + +abstract public class SNIServerName +{ + protected SNIServerName() {} + protected SNIServerName(int p0, byte[] p1){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final byte[] getEncoded(){ return null; } + public final int getType(){ return 0; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContext.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContext.java new file mode 100644 index 00000000000..4bd93e3b71d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContext.java @@ -0,0 +1,36 @@ +// Generated automatically from javax.net.ssl.SSLContext for testing purposes + +package javax.net.ssl; + +import java.security.Provider; +import java.security.SecureRandom; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLContextSpi; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; + +public class SSLContext +{ + protected SSLContext() {} + protected SSLContext(SSLContextSpi p0, Provider p1, String p2){} + public final Provider getProvider(){ return null; } + public final SSLEngine createSSLEngine(){ return null; } + public final SSLEngine createSSLEngine(String p0, int p1){ return null; } + public final SSLParameters getDefaultSSLParameters(){ return null; } + public final SSLParameters getSupportedSSLParameters(){ return null; } + public final SSLServerSocketFactory getServerSocketFactory(){ return null; } + public final SSLSessionContext getClientSessionContext(){ return null; } + public final SSLSessionContext getServerSessionContext(){ return null; } + public final SSLSocketFactory getSocketFactory(){ return null; } + public final String getProtocol(){ return null; } + public final void init(KeyManager[] p0, TrustManager[] p1, SecureRandom p2){} + public static SSLContext getDefault(){ return null; } + public static SSLContext getInstance(String p0){ return null; } + public static SSLContext getInstance(String p0, Provider p1){ return null; } + public static SSLContext getInstance(String p0, String p1){ return null; } + public static void setDefault(SSLContext p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContextSpi.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContextSpi.java new file mode 100644 index 00000000000..0229edd6d42 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLContextSpi.java @@ -0,0 +1,26 @@ +// Generated automatically from javax.net.ssl.SSLContextSpi for testing purposes + +package javax.net.ssl; + +import java.security.SecureRandom; +import javax.net.ssl.KeyManager; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; + +abstract public class SSLContextSpi +{ + protected SSLParameters engineGetDefaultSSLParameters(){ return null; } + protected SSLParameters engineGetSupportedSSLParameters(){ return null; } + protected abstract SSLEngine engineCreateSSLEngine(); + protected abstract SSLEngine engineCreateSSLEngine(String p0, int p1); + protected abstract SSLServerSocketFactory engineGetServerSocketFactory(); + protected abstract SSLSessionContext engineGetClientSessionContext(); + protected abstract SSLSessionContext engineGetServerSessionContext(); + protected abstract SSLSocketFactory engineGetSocketFactory(); + protected abstract void engineInit(KeyManager[] p0, TrustManager[] p1, SecureRandom p2); + public SSLContextSpi(){} +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngine.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngine.java new file mode 100644 index 00000000000..aae661e6263 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngine.java @@ -0,0 +1,53 @@ +// Generated automatically from javax.net.ssl.SSLEngine for testing purposes + +package javax.net.ssl; + +import java.nio.ByteBuffer; +import java.util.List; +import java.util.function.BiFunction; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; + +abstract public class SSLEngine +{ + protected SSLEngine(){} + protected SSLEngine(String p0, int p1){} + public BiFunction, String> getHandshakeApplicationProtocolSelector(){ return null; } + public SSLEngineResult unwrap(ByteBuffer p0, ByteBuffer p1){ return null; } + public SSLEngineResult unwrap(ByteBuffer p0, ByteBuffer[] p1){ return null; } + public SSLEngineResult wrap(ByteBuffer p0, ByteBuffer p1){ return null; } + public SSLEngineResult wrap(ByteBuffer[] p0, ByteBuffer p1){ return null; } + public SSLParameters getSSLParameters(){ return null; } + public SSLSession getHandshakeSession(){ return null; } + public String getApplicationProtocol(){ return null; } + public String getHandshakeApplicationProtocol(){ return null; } + public String getPeerHost(){ return null; } + public abstract Runnable getDelegatedTask(); + public abstract SSLEngineResult unwrap(ByteBuffer p0, ByteBuffer[] p1, int p2, int p3); + public abstract SSLEngineResult wrap(ByteBuffer[] p0, int p1, int p2, ByteBuffer p3); + public abstract SSLEngineResult.HandshakeStatus getHandshakeStatus(); + public abstract SSLSession getSession(); + public abstract String[] getEnabledCipherSuites(); + public abstract String[] getEnabledProtocols(); + public abstract String[] getSupportedCipherSuites(); + public abstract String[] getSupportedProtocols(); + public abstract boolean getEnableSessionCreation(); + public abstract boolean getNeedClientAuth(); + public abstract boolean getUseClientMode(); + public abstract boolean getWantClientAuth(); + public abstract boolean isInboundDone(); + public abstract boolean isOutboundDone(); + public abstract void beginHandshake(); + public abstract void closeInbound(); + public abstract void closeOutbound(); + public abstract void setEnableSessionCreation(boolean p0); + public abstract void setEnabledCipherSuites(String[] p0); + public abstract void setEnabledProtocols(String[] p0); + public abstract void setNeedClientAuth(boolean p0); + public abstract void setUseClientMode(boolean p0); + public abstract void setWantClientAuth(boolean p0); + public int getPeerPort(){ return 0; } + public void setHandshakeApplicationProtocolSelector(BiFunction, String> p0){} + public void setSSLParameters(SSLParameters p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngineResult.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngineResult.java new file mode 100644 index 00000000000..cb8cc4ed682 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLEngineResult.java @@ -0,0 +1,27 @@ +// Generated automatically from javax.net.ssl.SSLEngineResult for testing purposes + +package javax.net.ssl; + + +public class SSLEngineResult +{ + protected SSLEngineResult() {} + public SSLEngineResult(SSLEngineResult.Status p0, SSLEngineResult.HandshakeStatus p1, int p2, int p3){} + public SSLEngineResult(SSLEngineResult.Status p0, SSLEngineResult.HandshakeStatus p1, int p2, int p3, long p4){} + public String toString(){ return null; } + public final SSLEngineResult.HandshakeStatus getHandshakeStatus(){ return null; } + public final SSLEngineResult.Status getStatus(){ return null; } + public final int bytesConsumed(){ return 0; } + public final int bytesProduced(){ return 0; } + public final long sequenceNumber(){ return 0; } + static public enum HandshakeStatus + { + FINISHED, NEED_TASK, NEED_UNWRAP, NEED_UNWRAP_AGAIN, NEED_WRAP, NOT_HANDSHAKING; + private HandshakeStatus() {} + } + static public enum Status + { + BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED, OK; + private Status() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLParameters.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLParameters.java new file mode 100644 index 00000000000..a586964dc6c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLParameters.java @@ -0,0 +1,42 @@ +// Generated automatically from javax.net.ssl.SSLParameters for testing purposes + +package javax.net.ssl; + +import java.security.AlgorithmConstraints; +import java.util.Collection; +import java.util.List; +import javax.net.ssl.SNIMatcher; +import javax.net.ssl.SNIServerName; + +public class SSLParameters +{ + public AlgorithmConstraints getAlgorithmConstraints(){ return null; } + public SSLParameters(){} + public SSLParameters(String[] p0){} + public SSLParameters(String[] p0, String[] p1){} + public String getEndpointIdentificationAlgorithm(){ return null; } + public String[] getApplicationProtocols(){ return null; } + public String[] getCipherSuites(){ return null; } + public String[] getProtocols(){ return null; } + public String[] getSignatureSchemes(){ return null; } + public boolean getEnableRetransmissions(){ return false; } + public boolean getNeedClientAuth(){ return false; } + public boolean getWantClientAuth(){ return false; } + public final Collection getSNIMatchers(){ return null; } + public final List getServerNames(){ return null; } + public final boolean getUseCipherSuitesOrder(){ return false; } + public final void setSNIMatchers(Collection p0){} + public final void setServerNames(List p0){} + public final void setUseCipherSuitesOrder(boolean p0){} + public int getMaximumPacketSize(){ return 0; } + public void setAlgorithmConstraints(AlgorithmConstraints p0){} + public void setApplicationProtocols(String[] p0){} + public void setCipherSuites(String[] p0){} + public void setEnableRetransmissions(boolean p0){} + public void setEndpointIdentificationAlgorithm(String p0){} + public void setMaximumPacketSize(int p0){} + public void setNeedClientAuth(boolean p0){} + public void setProtocols(String[] p0){} + public void setSignatureSchemes(String[] p0){} + public void setWantClientAuth(boolean p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLServerSocketFactory.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLServerSocketFactory.java new file mode 100644 index 00000000000..9a76e454b3d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLServerSocketFactory.java @@ -0,0 +1,13 @@ +// Generated automatically from javax.net.ssl.SSLServerSocketFactory for testing purposes + +package javax.net.ssl; + +import javax.net.ServerSocketFactory; + +abstract public class SSLServerSocketFactory extends ServerSocketFactory +{ + protected SSLServerSocketFactory(){} + public abstract String[] getDefaultCipherSuites(); + public abstract String[] getSupportedCipherSuites(); + public static ServerSocketFactory getDefault(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSession.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSession.java new file mode 100644 index 00000000000..293ec637b63 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSession.java @@ -0,0 +1,33 @@ +// Generated automatically from javax.net.ssl.SSLSession for testing purposes + +package javax.net.ssl; + +import java.security.Principal; +import java.security.cert.Certificate; +import javax.net.ssl.SSLSessionContext; +import javax.security.cert.X509Certificate; + +public interface SSLSession +{ + Certificate[] getLocalCertificates(); + Certificate[] getPeerCertificates(); + Object getValue(String p0); + Principal getLocalPrincipal(); + Principal getPeerPrincipal(); + SSLSessionContext getSessionContext(); + String getCipherSuite(); + String getPeerHost(); + String getProtocol(); + String[] getValueNames(); + boolean isValid(); + byte[] getId(); + default X509Certificate[] getPeerCertificateChain(){ return null; } + int getApplicationBufferSize(); + int getPacketBufferSize(); + int getPeerPort(); + long getCreationTime(); + long getLastAccessedTime(); + void invalidate(); + void putValue(String p0, Object p1); + void removeValue(String p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSessionContext.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSessionContext.java new file mode 100644 index 00000000000..c0d9c6ef650 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSessionContext.java @@ -0,0 +1,16 @@ +// Generated automatically from javax.net.ssl.SSLSessionContext for testing purposes + +package javax.net.ssl; + +import java.util.Enumeration; +import javax.net.ssl.SSLSession; + +public interface SSLSessionContext +{ + Enumeration getIds(); + SSLSession getSession(byte[] p0); + int getSessionCacheSize(); + int getSessionTimeout(); + void setSessionCacheSize(int p0); + void setSessionTimeout(int p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSocketFactory.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSocketFactory.java new file mode 100644 index 00000000000..47c40526842 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/SSLSocketFactory.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.net.ssl.SSLSocketFactory for testing purposes + +package javax.net.ssl; + +import java.io.InputStream; +import java.net.Socket; +import javax.net.SocketFactory; + +abstract public class SSLSocketFactory extends SocketFactory +{ + public SSLSocketFactory(){} + public Socket createSocket(Socket p0, InputStream p1, boolean p2){ return null; } + public abstract Socket createSocket(Socket p0, String p1, int p2, boolean p3); + public abstract String[] getDefaultCipherSuites(); + public abstract String[] getSupportedCipherSuites(); + public static SocketFactory getDefault(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/net/ssl/TrustManager.java b/java/ql/test/stubs/javafx-web/javax/net/ssl/TrustManager.java new file mode 100644 index 00000000000..6698b99ac42 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/net/ssl/TrustManager.java @@ -0,0 +1,8 @@ +// Generated automatically from javax.net.ssl.TrustManager for testing purposes + +package javax.net.ssl; + + +public interface TrustManager +{ +} diff --git a/java/ql/test/stubs/javafx-web/javax/security/cert/Certificate.java b/java/ql/test/stubs/javafx-web/javax/security/cert/Certificate.java new file mode 100644 index 00000000000..56545088a1b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/security/cert/Certificate.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.security.cert.Certificate for testing purposes + +package javax.security.cert; + +import java.security.PublicKey; + +abstract public class Certificate +{ + public Certificate(){} + public abstract PublicKey getPublicKey(); + public abstract String toString(); + public abstract byte[] getEncoded(); + public abstract void verify(PublicKey p0); + public abstract void verify(PublicKey p0, String p1); + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/security/cert/X509Certificate.java b/java/ql/test/stubs/javafx-web/javax/security/cert/X509Certificate.java new file mode 100644 index 00000000000..1ec662982d1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/security/cert/X509Certificate.java @@ -0,0 +1,26 @@ +// Generated automatically from javax.security.cert.X509Certificate for testing purposes + +package javax.security.cert; + +import java.io.InputStream; +import java.math.BigInteger; +import java.security.Principal; +import javax.security.cert.Certificate; + +abstract public class X509Certificate extends Certificate +{ + public X509Certificate(){} + public abstract BigInteger getSerialNumber(); + public abstract Principal getIssuerDN(); + public abstract Principal getSubjectDN(); + public abstract String getSigAlgName(); + public abstract String getSigAlgOID(); + public abstract byte[] getSigAlgParams(); + public abstract int getVersion(); + public abstract java.util.Date getNotAfter(); + public abstract java.util.Date getNotBefore(); + public abstract void checkValidity(); + public abstract void checkValidity(java.util.Date p0); + public static X509Certificate getInstance(InputStream p0){ return null; } + public static X509Certificate getInstance(byte[] p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/sql/CommonDataSource.java b/java/ql/test/stubs/javafx-web/javax/sql/CommonDataSource.java new file mode 100644 index 00000000000..cdc814157ce --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/sql/CommonDataSource.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.sql.CommonDataSource for testing purposes + +package javax.sql; + +import java.io.PrintWriter; +import java.sql.ShardingKeyBuilder; +import java.util.logging.Logger; + +public interface CommonDataSource +{ + Logger getParentLogger(); + PrintWriter getLogWriter(); + default ShardingKeyBuilder createShardingKeyBuilder(){ return null; } + int getLoginTimeout(); + void setLogWriter(PrintWriter p0); + void setLoginTimeout(int p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/sql/DataSource.java b/java/ql/test/stubs/javafx-web/javax/sql/DataSource.java new file mode 100644 index 00000000000..d28d63d6e0a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/sql/DataSource.java @@ -0,0 +1,20 @@ +// Generated automatically from javax.sql.DataSource for testing purposes + +package javax.sql; + +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.ConnectionBuilder; +import java.sql.Wrapper; +import javax.sql.CommonDataSource; + +public interface DataSource extends CommonDataSource, Wrapper +{ + Connection getConnection(); + Connection getConnection(String p0, String p1); + PrintWriter getLogWriter(); + default ConnectionBuilder createConnectionBuilder(){ return null; } + int getLoginTimeout(); + void setLogWriter(PrintWriter p0); + void setLoginTimeout(int p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/RuntimeType.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/RuntimeType.java new file mode 100644 index 00000000000..19198662cdb --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/RuntimeType.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.ws.rs.RuntimeType for testing purposes + +package javax.ws.rs; + + +public enum RuntimeType +{ + CLIENT, SERVER; + private RuntimeType() {} +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/AsyncInvoker.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/AsyncInvoker.java new file mode 100644 index 00000000000..8aaad1d06c7 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/AsyncInvoker.java @@ -0,0 +1,47 @@ +// Generated automatically from javax.ws.rs.client.AsyncInvoker for testing purposes + +package javax.ws.rs.client; + +import java.util.concurrent.Future; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.InvocationCallback; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; + +public interface AsyncInvoker +{ + java.util.concurrent.Future delete(java.lang.Class p0); + java.util.concurrent.Future delete(javax.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future delete(javax.ws.rs.core.GenericType p0); + java.util.concurrent.Future get(java.lang.Class p0); + java.util.concurrent.Future get(javax.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future get(javax.ws.rs.core.GenericType p0); + java.util.concurrent.Future method(String p0, Entity p1, java.lang.Class p2); + java.util.concurrent.Future method(String p0, Entity p1, javax.ws.rs.client.InvocationCallback p2); + java.util.concurrent.Future method(String p0, Entity p1, javax.ws.rs.core.GenericType p2); + java.util.concurrent.Future method(String p0, java.lang.Class p1); + java.util.concurrent.Future method(String p0, javax.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future method(String p0, javax.ws.rs.core.GenericType p1); + java.util.concurrent.Future options(java.lang.Class p0); + java.util.concurrent.Future options(javax.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future options(javax.ws.rs.core.GenericType p0); + java.util.concurrent.Future post(Entity p0, java.lang.Class p1); + java.util.concurrent.Future post(Entity p0, javax.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future post(Entity p0, javax.ws.rs.core.GenericType p1); + java.util.concurrent.Future put(Entity p0, java.lang.Class p1); + java.util.concurrent.Future put(Entity p0, javax.ws.rs.client.InvocationCallback p1); + java.util.concurrent.Future put(Entity p0, javax.ws.rs.core.GenericType p1); + java.util.concurrent.Future trace(java.lang.Class p0); + java.util.concurrent.Future trace(javax.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future trace(javax.ws.rs.core.GenericType p0); + java.util.concurrent.Future delete(); + java.util.concurrent.Future get(); + java.util.concurrent.Future head(); + java.util.concurrent.Future head(InvocationCallback p0); + java.util.concurrent.Future method(String p0); + java.util.concurrent.Future method(String p0, Entity p1); + java.util.concurrent.Future options(); + java.util.concurrent.Future post(Entity p0); + java.util.concurrent.Future put(Entity p0); + java.util.concurrent.Future trace(); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Client.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Client.java new file mode 100644 index 00000000000..7869fa65579 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Client.java @@ -0,0 +1,24 @@ +// Generated automatically from javax.ws.rs.client.Client for testing purposes + +package javax.ws.rs.client; + +import java.net.URI; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Configurable; +import javax.ws.rs.core.Link; +import javax.ws.rs.core.UriBuilder; + +public interface Client extends Configurable +{ + HostnameVerifier getHostnameVerifier(); + Invocation.Builder invocation(Link p0); + SSLContext getSslContext(); + WebTarget target(Link p0); + WebTarget target(String p0); + WebTarget target(URI p0); + WebTarget target(UriBuilder p0); + void close(); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/ClientBuilder.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/ClientBuilder.java new file mode 100644 index 00000000000..76954b19f23 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/ClientBuilder.java @@ -0,0 +1,26 @@ +// Generated automatically from javax.ws.rs.client.ClientBuilder for testing purposes + +package javax.ws.rs.client; + +import java.security.KeyStore; +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.ws.rs.client.Client; +import javax.ws.rs.core.Configurable; +import javax.ws.rs.core.Configuration; + +abstract public class ClientBuilder implements Configurable +{ + protected ClientBuilder(){} + public ClientBuilder keyStore(KeyStore p0, String p1){ return null; } + public abstract Client build(); + public abstract ClientBuilder hostnameVerifier(HostnameVerifier p0); + public abstract ClientBuilder keyStore(KeyStore p0, char[] p1); + public abstract ClientBuilder sslContext(SSLContext p0); + public abstract ClientBuilder trustStore(KeyStore p0); + public abstract ClientBuilder withConfig(Configuration p0); + public static Client newClient(){ return null; } + public static Client newClient(Configuration p0){ return null; } + public static ClientBuilder newBuilder(){ return null; } + public static String JAXRS_DEFAULT_CLIENT_BUILDER_PROPERTY = null; +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Entity.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Entity.java new file mode 100644 index 00000000000..498b1907d7e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Entity.java @@ -0,0 +1,36 @@ +// Generated automatically from javax.ws.rs.client.Entity for testing purposes + +package javax.ws.rs.client; + +import java.lang.annotation.Annotation; +import java.util.Locale; +import javax.ws.rs.core.Form; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Variant; + +public class Entity +{ + protected Entity() {} + public Annotation[] getAnnotations(){ return null; } + public Locale getLanguage(){ return null; } + public MediaType getMediaType(){ return null; } + public String getEncoding(){ return null; } + public String toString(){ return null; } + public T getEntity(){ return null; } + public Variant getVariant(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static javax.ws.rs.client.Entity entity(T p0, MediaType p1){ return null; } + public static javax.ws.rs.client.Entity entity(T p0, MediaType p1, Annotation[] p2){ return null; } + public static javax.ws.rs.client.Entity entity(T p0, String p1){ return null; } + public static javax.ws.rs.client.Entity entity(T p0, Variant p1){ return null; } + public static javax.ws.rs.client.Entity entity(T p0, Variant p1, Annotation[] p2){ return null; } + public static javax.ws.rs.client.Entity html(T p0){ return null; } + public static javax.ws.rs.client.Entity json(T p0){ return null; } + public static javax.ws.rs.client.Entity text(T p0){ return null; } + public static javax.ws.rs.client.Entity xhtml(T p0){ return null; } + public static javax.ws.rs.client.Entity xml(T p0){ return null; } + public static Entity form(Form p0){ return null; } + public static Entity form(MultivaluedMap p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Invocation.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Invocation.java new file mode 100644 index 00000000000..04ed5fb1a12 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/Invocation.java @@ -0,0 +1,49 @@ +// Generated automatically from javax.ws.rs.client.Invocation for testing purposes + +package javax.ws.rs.client; + +import java.util.Locale; +import java.util.concurrent.Future; +import javax.ws.rs.client.AsyncInvoker; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.InvocationCallback; +import javax.ws.rs.client.SyncInvoker; +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.Cookie; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; + +public interface Invocation +{ + T invoke(java.lang.Class p0); + T invoke(javax.ws.rs.core.GenericType p0); + java.util.concurrent.Future submit(java.lang.Class p0); + java.util.concurrent.Future submit(javax.ws.rs.client.InvocationCallback p0); + java.util.concurrent.Future submit(javax.ws.rs.core.GenericType p0); + Invocation property(String p0, Object p1); + Response invoke(); + java.util.concurrent.Future submit(); + static public interface Builder extends SyncInvoker + { + AsyncInvoker async(); + Invocation build(String p0); + Invocation build(String p0, Entity p1); + Invocation buildDelete(); + Invocation buildGet(); + Invocation buildPost(Entity p0); + Invocation buildPut(Entity p0); + Invocation.Builder accept(MediaType... p0); + Invocation.Builder accept(String... p0); + Invocation.Builder acceptEncoding(String... p0); + Invocation.Builder acceptLanguage(Locale... p0); + Invocation.Builder acceptLanguage(String... p0); + Invocation.Builder cacheControl(CacheControl p0); + Invocation.Builder cookie(Cookie p0); + Invocation.Builder cookie(String p0, String p1); + Invocation.Builder header(String p0, Object p1); + Invocation.Builder headers(MultivaluedMap p0); + Invocation.Builder property(String p0, Object p1); + } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/InvocationCallback.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/InvocationCallback.java new file mode 100644 index 00000000000..22420c4c5db --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/InvocationCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.ws.rs.client.InvocationCallback for testing purposes + +package javax.ws.rs.client; + + +public interface InvocationCallback +{ + void completed(RESPONSE p0); + void failed(Throwable p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/SyncInvoker.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/SyncInvoker.java new file mode 100644 index 00000000000..40294c4a12a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/SyncInvoker.java @@ -0,0 +1,36 @@ +// Generated automatically from javax.ws.rs.client.SyncInvoker for testing purposes + +package javax.ws.rs.client; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; + +public interface SyncInvoker +{ + T delete(java.lang.Class p0); + T delete(javax.ws.rs.core.GenericType p0); + T get(java.lang.Class p0); + T get(javax.ws.rs.core.GenericType p0); + T method(String p0, Entity p1, java.lang.Class p2); + T method(String p0, Entity p1, javax.ws.rs.core.GenericType p2); + T method(String p0, java.lang.Class p1); + T method(String p0, javax.ws.rs.core.GenericType p1); + T options(java.lang.Class p0); + T options(javax.ws.rs.core.GenericType p0); + T post(Entity p0, java.lang.Class p1); + T post(Entity p0, javax.ws.rs.core.GenericType p1); + T put(Entity p0, java.lang.Class p1); + T put(Entity p0, javax.ws.rs.core.GenericType p1); + T trace(java.lang.Class p0); + T trace(javax.ws.rs.core.GenericType p0); + Response delete(); + Response get(); + Response head(); + Response method(String p0); + Response method(String p0, Entity p1); + Response options(); + Response post(Entity p0); + Response put(Entity p0); + Response trace(); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/client/WebTarget.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/WebTarget.java new file mode 100644 index 00000000000..d91eb3875cd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/client/WebTarget.java @@ -0,0 +1,28 @@ +// Generated automatically from javax.ws.rs.client.WebTarget for testing purposes + +package javax.ws.rs.client; + +import java.net.URI; +import java.util.Map; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Configurable; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.UriBuilder; + +public interface WebTarget extends Configurable +{ + Invocation.Builder request(); + Invocation.Builder request(MediaType... p0); + Invocation.Builder request(String... p0); + URI getUri(); + UriBuilder getUriBuilder(); + WebTarget matrixParam(String p0, Object... p1); + WebTarget path(String p0); + WebTarget queryParam(String p0, Object... p1); + WebTarget resolveTemplate(String p0, Object p1); + WebTarget resolveTemplate(String p0, Object p1, boolean p2); + WebTarget resolveTemplateFromEncoded(String p0, Object p1); + WebTarget resolveTemplates(Map p0); + WebTarget resolveTemplates(Map p0, boolean p1); + WebTarget resolveTemplatesFromEncoded(Map p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/CacheControl.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/CacheControl.java new file mode 100644 index 00000000000..6096a15b91f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/CacheControl.java @@ -0,0 +1,34 @@ +// Generated automatically from javax.ws.rs.core.CacheControl for testing purposes + +package javax.ws.rs.core; + +import java.util.List; +import java.util.Map; + +public class CacheControl +{ + public CacheControl(){} + public List getNoCacheFields(){ return null; } + public List getPrivateFields(){ return null; } + public Map getCacheExtension(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isMustRevalidate(){ return false; } + public boolean isNoCache(){ return false; } + public boolean isNoStore(){ return false; } + public boolean isNoTransform(){ return false; } + public boolean isPrivate(){ return false; } + public boolean isProxyRevalidate(){ return false; } + public int getMaxAge(){ return 0; } + public int getSMaxAge(){ return 0; } + public int hashCode(){ return 0; } + public static CacheControl valueOf(String p0){ return null; } + public void setMaxAge(int p0){} + public void setMustRevalidate(boolean p0){} + public void setNoCache(boolean p0){} + public void setNoStore(boolean p0){} + public void setNoTransform(boolean p0){} + public void setPrivate(boolean p0){} + public void setProxyRevalidate(boolean p0){} + public void setSMaxAge(int p0){} +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configurable.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configurable.java new file mode 100644 index 00000000000..18fbafa13ce --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configurable.java @@ -0,0 +1,20 @@ +// Generated automatically from javax.ws.rs.core.Configurable for testing purposes + +package javax.ws.rs.core; + +import java.util.Map; +import javax.ws.rs.core.Configuration; + +public interface Configurable +{ + C property(String p0, Object p1); + C register(Class p0); + C register(Class p0, Class... p1); + C register(Class p0, Map, Integer> p1); + C register(Class p0, int p1); + C register(Object p0); + C register(Object p0, Class... p1); + C register(Object p0, Map, Integer> p1); + C register(Object p0, int p1); + Configuration getConfiguration(); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configuration.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configuration.java new file mode 100644 index 00000000000..b1b4fb6e50d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Configuration.java @@ -0,0 +1,24 @@ +// Generated automatically from javax.ws.rs.core.Configuration for testing purposes + +package javax.ws.rs.core; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.RuntimeType; +import javax.ws.rs.core.Feature; + +public interface Configuration +{ + Collection getPropertyNames(); + Map, Integer> getContracts(Class p0); + Map getProperties(); + Object getProperty(String p0); + RuntimeType getRuntimeType(); + Set> getClasses(); + Set getInstances(); + boolean isEnabled(Feature p0); + boolean isEnabled(java.lang.Class p0); + boolean isRegistered(Class p0); + boolean isRegistered(Object p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Cookie.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Cookie.java new file mode 100644 index 00000000000..52b83dae424 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Cookie.java @@ -0,0 +1,22 @@ +// Generated automatically from javax.ws.rs.core.Cookie for testing purposes + +package javax.ws.rs.core; + + +public class Cookie +{ + protected Cookie() {} + public Cookie(String p0, String p1){} + public Cookie(String p0, String p1, String p2, String p3){} + public Cookie(String p0, String p1, String p2, String p3, int p4){} + public String getDomain(){ return null; } + public String getName(){ return null; } + public String getPath(){ return null; } + public String getValue(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int getVersion(){ return 0; } + public int hashCode(){ return 0; } + public static Cookie valueOf(String p0){ return null; } + public static int DEFAULT_VERSION = 0; +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/EntityTag.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/EntityTag.java new file mode 100644 index 00000000000..00b4815a605 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/EntityTag.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.ws.rs.core.EntityTag for testing purposes + +package javax.ws.rs.core; + + +public class EntityTag +{ + protected EntityTag() {} + public EntityTag(String p0){} + public EntityTag(String p0, boolean p1){} + public String getValue(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isWeak(){ return false; } + public int hashCode(){ return 0; } + public static EntityTag valueOf(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Feature.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Feature.java new file mode 100644 index 00000000000..cac25873b52 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Feature.java @@ -0,0 +1,10 @@ +// Generated automatically from javax.ws.rs.core.Feature for testing purposes + +package javax.ws.rs.core; + +import javax.ws.rs.core.FeatureContext; + +public interface Feature +{ + boolean configure(FeatureContext p0); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/FeatureContext.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/FeatureContext.java new file mode 100644 index 00000000000..1827a1bf1a5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/FeatureContext.java @@ -0,0 +1,9 @@ +// Generated automatically from javax.ws.rs.core.FeatureContext for testing purposes + +package javax.ws.rs.core; + +import javax.ws.rs.core.Configurable; + +public interface FeatureContext extends Configurable +{ +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Form.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Form.java new file mode 100644 index 00000000000..71f3a826c50 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Form.java @@ -0,0 +1,14 @@ +// Generated automatically from javax.ws.rs.core.Form for testing purposes + +package javax.ws.rs.core; + +import javax.ws.rs.core.MultivaluedMap; + +public class Form +{ + public Form param(String p0, String p1){ return null; } + public Form(){} + public Form(MultivaluedMap p0){} + public Form(String p0, String p1){} + public MultivaluedMap asMap(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/GenericType.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/GenericType.java new file mode 100644 index 00000000000..22617da5fcc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/GenericType.java @@ -0,0 +1,16 @@ +// Generated automatically from javax.ws.rs.core.GenericType for testing purposes + +package javax.ws.rs.core; + +import java.lang.reflect.Type; + +public class GenericType +{ + protected GenericType(){} + public GenericType(Type p0){} + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public final Class getRawType(){ return null; } + public final Type getType(){ return null; } + public int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Link.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Link.java new file mode 100644 index 00000000000..9d2c1e10850 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Link.java @@ -0,0 +1,48 @@ +// Generated automatically from javax.ws.rs.core.Link for testing purposes + +package javax.ws.rs.core; + +import java.net.URI; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.UriBuilder; + +abstract public class Link +{ + public Link(){} + public abstract List getRels(); + public abstract Map getParams(); + public abstract String getRel(); + public abstract String getTitle(); + public abstract String getType(); + public abstract String toString(); + public abstract URI getUri(); + public abstract UriBuilder getUriBuilder(); + public static Link valueOf(String p0){ return null; } + public static Link.Builder fromLink(Link p0){ return null; } + public static Link.Builder fromMethod(Class p0, String p1){ return null; } + public static Link.Builder fromPath(String p0){ return null; } + public static Link.Builder fromResource(Class p0){ return null; } + public static Link.Builder fromUri(String p0){ return null; } + public static Link.Builder fromUri(URI p0){ return null; } + public static Link.Builder fromUriBuilder(UriBuilder p0){ return null; } + public static String REL = null; + public static String TITLE = null; + public static String TYPE = null; + static public interface Builder + { + Link build(Object... p0); + Link buildRelativized(URI p0, Object... p1); + Link.Builder baseUri(String p0); + Link.Builder baseUri(URI p0); + Link.Builder link(Link p0); + Link.Builder link(String p0); + Link.Builder param(String p0, String p1); + Link.Builder rel(String p0); + Link.Builder title(String p0); + Link.Builder type(String p0); + Link.Builder uri(String p0); + Link.Builder uri(URI p0); + Link.Builder uriBuilder(UriBuilder p0); + } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MediaType.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MediaType.java new file mode 100644 index 00000000000..2ef1caff505 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MediaType.java @@ -0,0 +1,50 @@ +// Generated automatically from javax.ws.rs.core.MediaType for testing purposes + +package javax.ws.rs.core; + +import java.util.Map; + +public class MediaType +{ + public Map getParameters(){ return null; } + public MediaType withCharset(String p0){ return null; } + public MediaType(){} + public MediaType(String p0, String p1){} + public MediaType(String p0, String p1, Map p2){} + public MediaType(String p0, String p1, String p2){} + public String getSubtype(){ return null; } + public String getType(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isCompatible(MediaType p0){ return false; } + public boolean isWildcardSubtype(){ return false; } + public boolean isWildcardType(){ return false; } + public int hashCode(){ return 0; } + public static MediaType APPLICATION_ATOM_XML_TYPE = null; + public static MediaType APPLICATION_FORM_URLENCODED_TYPE = null; + public static MediaType APPLICATION_JSON_TYPE = null; + public static MediaType APPLICATION_OCTET_STREAM_TYPE = null; + public static MediaType APPLICATION_SVG_XML_TYPE = null; + public static MediaType APPLICATION_XHTML_XML_TYPE = null; + public static MediaType APPLICATION_XML_TYPE = null; + public static MediaType MULTIPART_FORM_DATA_TYPE = null; + public static MediaType TEXT_HTML_TYPE = null; + public static MediaType TEXT_PLAIN_TYPE = null; + public static MediaType TEXT_XML_TYPE = null; + public static MediaType WILDCARD_TYPE = null; + public static MediaType valueOf(String p0){ return null; } + public static String APPLICATION_ATOM_XML = null; + public static String APPLICATION_FORM_URLENCODED = null; + public static String APPLICATION_JSON = null; + public static String APPLICATION_OCTET_STREAM = null; + public static String APPLICATION_SVG_XML = null; + public static String APPLICATION_XHTML_XML = null; + public static String APPLICATION_XML = null; + public static String CHARSET_PARAMETER = null; + public static String MEDIA_TYPE_WILDCARD = null; + public static String MULTIPART_FORM_DATA = null; + public static String TEXT_HTML = null; + public static String TEXT_PLAIN = null; + public static String TEXT_XML = null; + public static String WILDCARD = null; +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MultivaluedMap.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MultivaluedMap.java new file mode 100644 index 00000000000..7fb1e3d682d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/MultivaluedMap.java @@ -0,0 +1,17 @@ +// Generated automatically from javax.ws.rs.core.MultivaluedMap for testing purposes + +package javax.ws.rs.core; + +import java.util.List; +import java.util.Map; + +public interface MultivaluedMap extends java.util.Map> +{ + V getFirst(K p0); + boolean equalsIgnoreValueOrder(MultivaluedMap p0); + void add(K p0, V p1); + void addAll(K p0, V... p1); + void addAll(K p0, java.util.List p1); + void addFirst(K p0, V p1); + void putSingle(K p0, V p1); +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/NewCookie.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/NewCookie.java new file mode 100644 index 00000000000..03de30d6e77 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/NewCookie.java @@ -0,0 +1,29 @@ +// Generated automatically from javax.ws.rs.core.NewCookie for testing purposes + +package javax.ws.rs.core; + +import javax.ws.rs.core.Cookie; + +public class NewCookie extends Cookie +{ + protected NewCookie() {} + public Cookie toCookie(){ return null; } + public NewCookie(Cookie p0){} + public NewCookie(Cookie p0, String p1, int p2, boolean p3){} + public NewCookie(Cookie p0, String p1, int p2, java.util.Date p3, boolean p4, boolean p5){} + public NewCookie(String p0, String p1){} + public NewCookie(String p0, String p1, String p2, String p3, String p4, int p5, boolean p6){} + public NewCookie(String p0, String p1, String p2, String p3, String p4, int p5, boolean p6, boolean p7){} + public NewCookie(String p0, String p1, String p2, String p3, int p4, String p5, int p6, boolean p7){} + public NewCookie(String p0, String p1, String p2, String p3, int p4, String p5, int p6, java.util.Date p7, boolean p8, boolean p9){} + public String getComment(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isHttpOnly(){ return false; } + public boolean isSecure(){ return false; } + public int getMaxAge(){ return 0; } + public int hashCode(){ return 0; } + public java.util.Date getExpiry(){ return null; } + public static NewCookie valueOf(String p0){ return null; } + public static int DEFAULT_MAX_AGE = 0; +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Response.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Response.java new file mode 100644 index 00000000000..bc8364ff18f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Response.java @@ -0,0 +1,127 @@ +// Generated automatically from javax.ws.rs.core.Response for testing purposes + +package javax.ws.rs.core; + +import java.lang.annotation.Annotation; +import java.net.URI; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Link; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.NewCookie; +import javax.ws.rs.core.Variant; + +abstract public class Response +{ + abstract static public class ResponseBuilder + { + protected ResponseBuilder(){} + protected static Response.ResponseBuilder newInstance(){ return null; } + public Response.ResponseBuilder status(Response.Status p0){ return null; } + public Response.ResponseBuilder status(Response.StatusType p0){ return null; } + public abstract Response build(); + public abstract Response.ResponseBuilder allow(Set p0); + public abstract Response.ResponseBuilder allow(String... p0); + public abstract Response.ResponseBuilder cacheControl(CacheControl p0); + public abstract Response.ResponseBuilder clone(); + public abstract Response.ResponseBuilder contentLocation(URI p0); + public abstract Response.ResponseBuilder cookie(NewCookie... p0); + public abstract Response.ResponseBuilder encoding(String p0); + public abstract Response.ResponseBuilder entity(Object p0); + public abstract Response.ResponseBuilder entity(Object p0, Annotation[] p1); + public abstract Response.ResponseBuilder expires(java.util.Date p0); + public abstract Response.ResponseBuilder header(String p0, Object p1); + public abstract Response.ResponseBuilder language(Locale p0); + public abstract Response.ResponseBuilder language(String p0); + public abstract Response.ResponseBuilder lastModified(java.util.Date p0); + public abstract Response.ResponseBuilder link(String p0, String p1); + public abstract Response.ResponseBuilder link(URI p0, String p1); + public abstract Response.ResponseBuilder links(Link... p0); + public abstract Response.ResponseBuilder location(URI p0); + public abstract Response.ResponseBuilder replaceAll(MultivaluedMap p0); + public abstract Response.ResponseBuilder status(int p0); + public abstract Response.ResponseBuilder tag(EntityTag p0); + public abstract Response.ResponseBuilder tag(String p0); + public abstract Response.ResponseBuilder type(MediaType p0); + public abstract Response.ResponseBuilder type(String p0); + public abstract Response.ResponseBuilder variant(Variant p0); + public abstract Response.ResponseBuilder variants(Variant... p0); + public abstract Response.ResponseBuilder variants(java.util.List p0); + } + protected Response(){} + public MultivaluedMap getHeaders(){ return null; } + public abstract T readEntity(java.lang.Class p0); + public abstract T readEntity(java.lang.Class p0, Annotation[] p1); + public abstract T readEntity(javax.ws.rs.core.GenericType p0); + public abstract T readEntity(javax.ws.rs.core.GenericType p0, Annotation[] p1); + public abstract EntityTag getEntityTag(); + public abstract Link getLink(String p0); + public abstract Link.Builder getLinkBuilder(String p0); + public abstract Locale getLanguage(); + public abstract MediaType getMediaType(); + public abstract MultivaluedMap getMetadata(); + public abstract MultivaluedMap getStringHeaders(); + public abstract Object getEntity(); + public abstract Response.StatusType getStatusInfo(); + public abstract Set getAllowedMethods(); + public abstract String getHeaderString(String p0); + public abstract URI getLocation(); + public abstract boolean bufferEntity(); + public abstract boolean hasEntity(); + public abstract boolean hasLink(String p0); + public abstract int getLength(); + public abstract int getStatus(); + public abstract java.util.Date getDate(); + public abstract java.util.Date getLastModified(); + public abstract java.util.Map getCookies(); + public abstract java.util.Set getLinks(); + public abstract void close(); + public static Response.ResponseBuilder accepted(){ return null; } + public static Response.ResponseBuilder accepted(Object p0){ return null; } + public static Response.ResponseBuilder created(URI p0){ return null; } + public static Response.ResponseBuilder fromResponse(Response p0){ return null; } + public static Response.ResponseBuilder noContent(){ return null; } + public static Response.ResponseBuilder notAcceptable(java.util.List p0){ return null; } + public static Response.ResponseBuilder notModified(){ return null; } + public static Response.ResponseBuilder notModified(EntityTag p0){ return null; } + public static Response.ResponseBuilder notModified(String p0){ return null; } + public static Response.ResponseBuilder ok(){ return null; } + public static Response.ResponseBuilder ok(Object p0){ return null; } + public static Response.ResponseBuilder ok(Object p0, MediaType p1){ return null; } + public static Response.ResponseBuilder ok(Object p0, String p1){ return null; } + public static Response.ResponseBuilder ok(Object p0, Variant p1){ return null; } + public static Response.ResponseBuilder seeOther(URI p0){ return null; } + public static Response.ResponseBuilder serverError(){ return null; } + public static Response.ResponseBuilder status(Response.Status p0){ return null; } + public static Response.ResponseBuilder status(Response.StatusType p0){ return null; } + public static Response.ResponseBuilder status(int p0){ return null; } + public static Response.ResponseBuilder temporaryRedirect(URI p0){ return null; } + static public enum Status + { + ACCEPTED, BAD_GATEWAY, BAD_REQUEST, CONFLICT, CREATED, EXPECTATION_FAILED, FORBIDDEN, FOUND, GATEWAY_TIMEOUT, GONE, HTTP_VERSION_NOT_SUPPORTED, INTERNAL_SERVER_ERROR, LENGTH_REQUIRED, METHOD_NOT_ALLOWED, MOVED_PERMANENTLY, NOT_ACCEPTABLE, NOT_FOUND, NOT_IMPLEMENTED, NOT_MODIFIED, NO_CONTENT, OK, PARTIAL_CONTENT, PAYMENT_REQUIRED, PRECONDITION_FAILED, PROXY_AUTHENTICATION_REQUIRED, REQUESTED_RANGE_NOT_SATISFIABLE, REQUEST_ENTITY_TOO_LARGE, REQUEST_TIMEOUT, REQUEST_URI_TOO_LONG, RESET_CONTENT, SEE_OTHER, SERVICE_UNAVAILABLE, TEMPORARY_REDIRECT, UNAUTHORIZED, UNSUPPORTED_MEDIA_TYPE, USE_PROXY; + private Status() {} + public Response.Status.Family getFamily(){ return null; } + public String getReasonPhrase(){ return null; } + public String toString(){ return null; } + public int getStatusCode(){ return 0; } + public static Response.Status fromStatusCode(int p0){ return null; } + static public enum Family + { + CLIENT_ERROR, INFORMATIONAL, OTHER, REDIRECTION, SERVER_ERROR, SUCCESSFUL; + private Family() {} + public static Response.Status.Family familyOf(int p0){ return null; } + } + } + static public interface StatusType + { + Response.Status.Family getFamily(); + String getReasonPhrase(); + int getStatusCode(); + } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/UriBuilder.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/UriBuilder.java new file mode 100644 index 00000000000..52d051c1b14 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/UriBuilder.java @@ -0,0 +1,54 @@ +// Generated automatically from javax.ws.rs.core.UriBuilder for testing purposes + +package javax.ws.rs.core; + +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Map; +import javax.ws.rs.core.Link; + +abstract public class UriBuilder +{ + protected UriBuilder(){} + protected static UriBuilder newInstance(){ return null; } + public abstract String toTemplate(); + public abstract URI build(Object... p0); + public abstract URI build(Object[] p0, boolean p1); + public abstract URI buildFromEncoded(Object... p0); + public abstract URI buildFromEncodedMap(Map p0); + public abstract URI buildFromMap(Map p0); + public abstract URI buildFromMap(Map p0, boolean p1); + public abstract UriBuilder clone(); + public abstract UriBuilder fragment(String p0); + public abstract UriBuilder host(String p0); + public abstract UriBuilder matrixParam(String p0, Object... p1); + public abstract UriBuilder path(Class p0); + public abstract UriBuilder path(Class p0, String p1); + public abstract UriBuilder path(Method p0); + public abstract UriBuilder path(String p0); + public abstract UriBuilder port(int p0); + public abstract UriBuilder queryParam(String p0, Object... p1); + public abstract UriBuilder replaceMatrix(String p0); + public abstract UriBuilder replaceMatrixParam(String p0, Object... p1); + public abstract UriBuilder replacePath(String p0); + public abstract UriBuilder replaceQuery(String p0); + public abstract UriBuilder replaceQueryParam(String p0, Object... p1); + public abstract UriBuilder resolveTemplate(String p0, Object p1); + public abstract UriBuilder resolveTemplate(String p0, Object p1, boolean p2); + public abstract UriBuilder resolveTemplateFromEncoded(String p0, Object p1); + public abstract UriBuilder resolveTemplates(Map p0); + public abstract UriBuilder resolveTemplates(Map p0, boolean p1); + public abstract UriBuilder resolveTemplatesFromEncoded(Map p0); + public abstract UriBuilder scheme(String p0); + public abstract UriBuilder schemeSpecificPart(String p0); + public abstract UriBuilder segment(String... p0); + public abstract UriBuilder uri(String p0); + public abstract UriBuilder uri(URI p0); + public abstract UriBuilder userInfo(String p0); + public static UriBuilder fromLink(Link p0){ return null; } + public static UriBuilder fromMethod(Class p0, String p1){ return null; } + public static UriBuilder fromPath(String p0){ return null; } + public static UriBuilder fromResource(Class p0){ return null; } + public static UriBuilder fromUri(String p0){ return null; } + public static UriBuilder fromUri(URI p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Variant.java b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Variant.java new file mode 100644 index 00000000000..0c2ef6892af --- /dev/null +++ b/java/ql/test/stubs/javafx-web/javax/ws/rs/core/Variant.java @@ -0,0 +1,36 @@ +// Generated automatically from javax.ws.rs.core.Variant for testing purposes + +package javax.ws.rs.core; + +import java.util.List; +import java.util.Locale; +import javax.ws.rs.core.MediaType; + +public class Variant +{ + protected Variant() {} + abstract static public class VariantListBuilder + { + protected VariantListBuilder(){} + public abstract Variant.VariantListBuilder add(); + public abstract Variant.VariantListBuilder encodings(String... p0); + public abstract Variant.VariantListBuilder languages(Locale... p0); + public abstract Variant.VariantListBuilder mediaTypes(MediaType... p0); + public abstract java.util.List build(); + public static Variant.VariantListBuilder newInstance(){ return null; } + } + public Locale getLanguage(){ return null; } + public MediaType getMediaType(){ return null; } + public String getEncoding(){ return null; } + public String getLanguageString(){ return null; } + public String toString(){ return null; } + public Variant(MediaType p0, Locale p1, String p2){} + public Variant(MediaType p0, String p1, String p2){} + public Variant(MediaType p0, String p1, String p2, String p3){} + public Variant(MediaType p0, String p1, String p2, String p3, String p4){} + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static Variant.VariantListBuilder encodings(String... p0){ return null; } + public static Variant.VariantListBuilder languages(Locale... p0){ return null; } + public static Variant.VariantListBuilder mediaTypes(MediaType... p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/commons/logging/Log.java b/java/ql/test/stubs/javafx-web/org/apache/commons/logging/Log.java new file mode 100644 index 00000000000..0ff25bcb341 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/commons/logging/Log.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.commons.logging.Log for testing purposes + +package org.apache.commons.logging; + + +public interface Log +{ + boolean isDebugEnabled(); + boolean isErrorEnabled(); + boolean isFatalEnabled(); + boolean isInfoEnabled(); + boolean isTraceEnabled(); + boolean isWarnEnabled(); + void debug(Object p0); + void debug(Object p0, Throwable p1); + void error(Object p0); + void error(Object p0, Throwable p1); + void fatal(Object p0); + void fatal(Object p0, Throwable p1); + void info(Object p0); + void info(Object p0, Throwable p1); + void trace(Object p0); + void trace(Object p0, Throwable p1); + void warn(Object p0); + void warn(Object p0, Throwable p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/Header.java b/java/ql/test/stubs/javafx-web/org/apache/http/Header.java new file mode 100644 index 00000000000..7674e4c8b3e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/Header.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.http.Header for testing purposes + +package org.apache.http; + +import org.apache.http.HeaderElement; +import org.apache.http.NameValuePair; + +public interface Header extends NameValuePair +{ + HeaderElement[] getElements(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HeaderElement.java b/java/ql/test/stubs/javafx-web/org/apache/http/HeaderElement.java new file mode 100644 index 00000000000..6c362a9e216 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HeaderElement.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.HeaderElement for testing purposes + +package org.apache.http; + +import org.apache.http.NameValuePair; + +public interface HeaderElement +{ + NameValuePair getParameter(int p0); + NameValuePair getParameterByName(String p0); + NameValuePair[] getParameters(); + String getName(); + String getValue(); + int getParameterCount(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HeaderIterator.java b/java/ql/test/stubs/javafx-web/org/apache/http/HeaderIterator.java new file mode 100644 index 00000000000..284ea9c13d3 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HeaderIterator.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.http.HeaderIterator for testing purposes + +package org.apache.http; + +import java.util.Iterator; +import org.apache.http.Header; + +public interface HeaderIterator extends Iterator +{ + Header nextHeader(); + boolean hasNext(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpClientConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpClientConnection.java new file mode 100644 index 00000000000..6ea869be329 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpClientConnection.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.http.HttpClientConnection for testing purposes + +package org.apache.http; + +import org.apache.http.HttpConnection; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; + +public interface HttpClientConnection extends HttpConnection +{ + HttpResponse receiveResponseHeader(); + boolean isResponseAvailable(int p0); + void flush(); + void receiveResponseEntity(HttpResponse p0); + void sendRequestEntity(HttpEntityEnclosingRequest p0); + void sendRequestHeader(HttpRequest p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnection.java new file mode 100644 index 00000000000..221186c2187 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnection.java @@ -0,0 +1,17 @@ +// Generated automatically from org.apache.http.HttpConnection for testing purposes + +package org.apache.http; + +import java.io.Closeable; +import org.apache.http.HttpConnectionMetrics; + +public interface HttpConnection extends Closeable +{ + HttpConnectionMetrics getMetrics(); + boolean isOpen(); + boolean isStale(); + int getSocketTimeout(); + void close(); + void setSocketTimeout(int p0); + void shutdown(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnectionMetrics.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnectionMetrics.java new file mode 100644 index 00000000000..1a1b80b9255 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpConnectionMetrics.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.http.HttpConnectionMetrics for testing purposes + +package org.apache.http; + + +public interface HttpConnectionMetrics +{ + Object getMetric(String p0); + long getReceivedBytesCount(); + long getRequestCount(); + long getResponseCount(); + long getSentBytesCount(); + void reset(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntity.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntity.java new file mode 100644 index 00000000000..8dd6a607624 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntity.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.http.HttpEntity for testing purposes + +package org.apache.http; + +import java.io.InputStream; +import java.io.OutputStream; +import org.apache.http.Header; + +public interface HttpEntity +{ + Header getContentEncoding(); + Header getContentType(); + InputStream getContent(); + boolean isChunked(); + boolean isRepeatable(); + boolean isStreaming(); + long getContentLength(); + void consumeContent(); + void writeTo(OutputStream p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntityEnclosingRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntityEnclosingRequest.java new file mode 100644 index 00000000000..b2fc8b5579a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpEntityEnclosingRequest.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.http.HttpEntityEnclosingRequest for testing purposes + +package org.apache.http; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpRequest; + +public interface HttpEntityEnclosingRequest extends HttpRequest +{ + HttpEntity getEntity(); + boolean expectContinue(); + void setEntity(HttpEntity p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpHost.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpHost.java new file mode 100644 index 00000000000..e342402e069 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpHost.java @@ -0,0 +1,36 @@ +// Generated automatically from org.apache.http.HttpHost for testing purposes + +package org.apache.http; + +import java.io.Serializable; +import java.net.InetAddress; + +public class HttpHost implements Cloneable, Serializable +{ + protected HttpHost() {} + protected final InetAddress address = null; + protected final String hostname = null; + protected final String lcHostname = null; + protected final String schemeName = null; + protected final int port = 0; + public HttpHost(HttpHost p0){} + public HttpHost(InetAddress p0){} + public HttpHost(InetAddress p0, String p1, int p2, String p3){} + public HttpHost(InetAddress p0, int p1){} + public HttpHost(InetAddress p0, int p1, String p2){} + public HttpHost(String p0){} + public HttpHost(String p0, int p1){} + public HttpHost(String p0, int p1, String p2){} + public InetAddress getAddress(){ return null; } + public Object clone(){ return null; } + public String getHostName(){ return null; } + public String getSchemeName(){ return null; } + public String toHostString(){ return null; } + public String toString(){ return null; } + public String toURI(){ return null; } + public boolean equals(Object p0){ return false; } + public int getPort(){ return 0; } + public int hashCode(){ return 0; } + public static HttpHost create(String p0){ return null; } + public static String DEFAULT_SCHEME_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpInetConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpInetConnection.java new file mode 100644 index 00000000000..cb17abad3d0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpInetConnection.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.http.HttpInetConnection for testing purposes + +package org.apache.http; + +import java.net.InetAddress; +import org.apache.http.HttpConnection; + +public interface HttpInetConnection extends HttpConnection +{ + InetAddress getLocalAddress(); + InetAddress getRemoteAddress(); + int getLocalPort(); + int getRemotePort(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpMessage.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpMessage.java new file mode 100644 index 00000000000..3bd5bd5c1a9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpMessage.java @@ -0,0 +1,29 @@ +// Generated automatically from org.apache.http.HttpMessage for testing purposes + +package org.apache.http; + +import org.apache.http.Header; +import org.apache.http.HeaderIterator; +import org.apache.http.ProtocolVersion; +import org.apache.http.params.HttpParams; + +public interface HttpMessage +{ + Header getFirstHeader(String p0); + Header getLastHeader(String p0); + HeaderIterator headerIterator(); + HeaderIterator headerIterator(String p0); + Header[] getAllHeaders(); + Header[] getHeaders(String p0); + HttpParams getParams(); + ProtocolVersion getProtocolVersion(); + boolean containsHeader(String p0); + void addHeader(Header p0); + void addHeader(String p0, String p1); + void removeHeader(Header p0); + void removeHeaders(String p0); + void setHeader(Header p0); + void setHeader(String p0, String p1); + void setHeaders(Header[] p0); + void setParams(HttpParams p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpRequest.java new file mode 100644 index 00000000000..b603e3f9c73 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpRequest.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.http.HttpRequest for testing purposes + +package org.apache.http; + +import org.apache.http.HttpMessage; +import org.apache.http.RequestLine; + +public interface HttpRequest extends HttpMessage +{ + RequestLine getRequestLine(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/HttpResponse.java b/java/ql/test/stubs/javafx-web/org/apache/http/HttpResponse.java new file mode 100644 index 00000000000..66246f79ab2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/HttpResponse.java @@ -0,0 +1,23 @@ +// Generated automatically from org.apache.http.HttpResponse for testing purposes + +package org.apache.http; + +import java.util.Locale; +import org.apache.http.HttpEntity; +import org.apache.http.HttpMessage; +import org.apache.http.ProtocolVersion; +import org.apache.http.StatusLine; + +public interface HttpResponse extends HttpMessage +{ + HttpEntity getEntity(); + Locale getLocale(); + StatusLine getStatusLine(); + void setEntity(HttpEntity p0); + void setLocale(Locale p0); + void setReasonPhrase(String p0); + void setStatusCode(int p0); + void setStatusLine(ProtocolVersion p0, int p1); + void setStatusLine(ProtocolVersion p0, int p1, String p2); + void setStatusLine(StatusLine p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/NameValuePair.java b/java/ql/test/stubs/javafx-web/org/apache/http/NameValuePair.java new file mode 100644 index 00000000000..2219b56c811 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/NameValuePair.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.http.NameValuePair for testing purposes + +package org.apache.http; + + +public interface NameValuePair +{ + String getName(); + String getValue(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/ProtocolVersion.java b/java/ql/test/stubs/javafx-web/org/apache/http/ProtocolVersion.java new file mode 100644 index 00000000000..1464659108c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/ProtocolVersion.java @@ -0,0 +1,26 @@ +// Generated automatically from org.apache.http.ProtocolVersion for testing purposes + +package org.apache.http; + +import java.io.Serializable; + +public class ProtocolVersion implements Cloneable, Serializable +{ + protected ProtocolVersion() {} + protected final String protocol = null; + protected final int major = 0; + protected final int minor = 0; + public Object clone(){ return null; } + public ProtocolVersion forVersion(int p0, int p1){ return null; } + public ProtocolVersion(String p0, int p1, int p2){} + public String toString(){ return null; } + public boolean isComparable(ProtocolVersion p0){ return false; } + public final String getProtocol(){ return null; } + public final boolean equals(Object p0){ return false; } + public final boolean greaterEquals(ProtocolVersion p0){ return false; } + public final boolean lessEquals(ProtocolVersion p0){ return false; } + public final int getMajor(){ return 0; } + public final int getMinor(){ return 0; } + public final int hashCode(){ return 0; } + public int compareToVersion(ProtocolVersion p0){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/RequestLine.java b/java/ql/test/stubs/javafx-web/org/apache/http/RequestLine.java new file mode 100644 index 00000000000..d2f6d3bd0e5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/RequestLine.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.http.RequestLine for testing purposes + +package org.apache.http; + +import org.apache.http.ProtocolVersion; + +public interface RequestLine +{ + ProtocolVersion getProtocolVersion(); + String getMethod(); + String getUri(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/StatusLine.java b/java/ql/test/stubs/javafx-web/org/apache/http/StatusLine.java new file mode 100644 index 00000000000..84f39960ef1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/StatusLine.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.http.StatusLine for testing purposes + +package org.apache.http; + +import org.apache.http.ProtocolVersion; + +public interface StatusLine +{ + ProtocolVersion getProtocolVersion(); + String getReasonPhrase(); + int getStatusCode(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/config/RequestConfig.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/config/RequestConfig.java new file mode 100644 index 00000000000..78a6fa53928 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/config/RequestConfig.java @@ -0,0 +1,57 @@ +// Generated automatically from org.apache.http.client.config.RequestConfig for testing purposes + +package org.apache.http.client.config; + +import java.net.InetAddress; +import java.util.Collection; +import org.apache.http.HttpHost; + +public class RequestConfig implements Cloneable +{ + protected RequestConfig clone(){ return null; } + protected RequestConfig(){} + public Collection getProxyPreferredAuthSchemes(){ return null; } + public Collection getTargetPreferredAuthSchemes(){ return null; } + public HttpHost getProxy(){ return null; } + public InetAddress getLocalAddress(){ return null; } + public String getCookieSpec(){ return null; } + public String toString(){ return null; } + public boolean isAuthenticationEnabled(){ return false; } + public boolean isCircularRedirectsAllowed(){ return false; } + public boolean isContentCompressionEnabled(){ return false; } + public boolean isDecompressionEnabled(){ return false; } + public boolean isExpectContinueEnabled(){ return false; } + public boolean isNormalizeUri(){ return false; } + public boolean isRedirectsEnabled(){ return false; } + public boolean isRelativeRedirectsAllowed(){ return false; } + public boolean isStaleConnectionCheckEnabled(){ return false; } + public int getConnectTimeout(){ return 0; } + public int getConnectionRequestTimeout(){ return 0; } + public int getMaxRedirects(){ return 0; } + public int getSocketTimeout(){ return 0; } + public static RequestConfig DEFAULT = null; + public static RequestConfig.Builder copy(RequestConfig p0){ return null; } + public static RequestConfig.Builder custom(){ return null; } + static public class Builder + { + public RequestConfig build(){ return null; } + public RequestConfig.Builder setAuthenticationEnabled(boolean p0){ return null; } + public RequestConfig.Builder setCircularRedirectsAllowed(boolean p0){ return null; } + public RequestConfig.Builder setConnectTimeout(int p0){ return null; } + public RequestConfig.Builder setConnectionRequestTimeout(int p0){ return null; } + public RequestConfig.Builder setContentCompressionEnabled(boolean p0){ return null; } + public RequestConfig.Builder setCookieSpec(String p0){ return null; } + public RequestConfig.Builder setDecompressionEnabled(boolean p0){ return null; } + public RequestConfig.Builder setExpectContinueEnabled(boolean p0){ return null; } + public RequestConfig.Builder setLocalAddress(InetAddress p0){ return null; } + public RequestConfig.Builder setMaxRedirects(int p0){ return null; } + public RequestConfig.Builder setNormalizeUri(boolean p0){ return null; } + public RequestConfig.Builder setProxy(HttpHost p0){ return null; } + public RequestConfig.Builder setProxyPreferredAuthSchemes(Collection p0){ return null; } + public RequestConfig.Builder setRedirectsEnabled(boolean p0){ return null; } + public RequestConfig.Builder setRelativeRedirectsAllowed(boolean p0){ return null; } + public RequestConfig.Builder setSocketTimeout(int p0){ return null; } + public RequestConfig.Builder setStaleConnectionCheckEnabled(boolean p0){ return null; } + public RequestConfig.Builder setTargetPreferredAuthSchemes(Collection p0){ return null; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbortableHttpRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbortableHttpRequest.java new file mode 100644 index 00000000000..2c53f6d9cfa --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbortableHttpRequest.java @@ -0,0 +1,13 @@ +// Generated automatically from org.apache.http.client.methods.AbortableHttpRequest for testing purposes + +package org.apache.http.client.methods; + +import org.apache.http.conn.ClientConnectionRequest; +import org.apache.http.conn.ConnectionReleaseTrigger; + +public interface AbortableHttpRequest +{ + void abort(); + void setConnectionRequest(ClientConnectionRequest p0); + void setReleaseTrigger(ConnectionReleaseTrigger p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbstractExecutionAwareRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbstractExecutionAwareRequest.java new file mode 100644 index 00000000000..335d2ff7f77 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/AbstractExecutionAwareRequest.java @@ -0,0 +1,24 @@ +// Generated automatically from org.apache.http.client.methods.AbstractExecutionAwareRequest for testing purposes + +package org.apache.http.client.methods; + +import org.apache.http.HttpRequest; +import org.apache.http.client.methods.AbortableHttpRequest; +import org.apache.http.client.methods.HttpExecutionAware; +import org.apache.http.concurrent.Cancellable; +import org.apache.http.conn.ClientConnectionRequest; +import org.apache.http.conn.ConnectionReleaseTrigger; +import org.apache.http.message.AbstractHttpMessage; + +abstract public class AbstractExecutionAwareRequest extends AbstractHttpMessage implements AbortableHttpRequest, Cloneable, HttpExecutionAware, HttpRequest +{ + protected AbstractExecutionAwareRequest(){} + public Object clone(){ return null; } + public boolean isAborted(){ return false; } + public void abort(){} + public void completed(){} + public void reset(){} + public void setCancellable(Cancellable p0){} + public void setConnectionRequest(ClientConnectionRequest p0){} + public void setReleaseTrigger(ConnectionReleaseTrigger p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/Configurable.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/Configurable.java new file mode 100644 index 00000000000..a91c4628748 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/Configurable.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.http.client.methods.Configurable for testing purposes + +package org.apache.http.client.methods; + +import org.apache.http.client.config.RequestConfig; + +public interface Configurable +{ + RequestConfig getConfig(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpDelete.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpDelete.java new file mode 100644 index 00000000000..9d1dac980a8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpDelete.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpDelete for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpRequestBase; + +public class HttpDelete extends HttpRequestBase +{ + public HttpDelete(){} + public HttpDelete(String p0){} + public HttpDelete(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java new file mode 100644 index 00000000000..3765444c9b4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpEntityEnclosingRequestBase.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.http.client.methods.HttpEntityEnclosingRequestBase for testing purposes + +package org.apache.http.client.methods; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.client.methods.HttpRequestBase; + +abstract public class HttpEntityEnclosingRequestBase extends HttpRequestBase implements HttpEntityEnclosingRequest +{ + public HttpEntity getEntity(){ return null; } + public HttpEntityEnclosingRequestBase(){} + public Object clone(){ return null; } + public boolean expectContinue(){ return false; } + public void setEntity(HttpEntity p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpExecutionAware.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpExecutionAware.java new file mode 100644 index 00000000000..d7b9126dcac --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpExecutionAware.java @@ -0,0 +1,11 @@ +// Generated automatically from org.apache.http.client.methods.HttpExecutionAware for testing purposes + +package org.apache.http.client.methods; + +import org.apache.http.concurrent.Cancellable; + +public interface HttpExecutionAware +{ + boolean isAborted(); + void setCancellable(Cancellable p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpGet.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpGet.java new file mode 100644 index 00000000000..23f57c7ea13 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpGet.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpGet for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpRequestBase; + +public class HttpGet extends HttpRequestBase +{ + public HttpGet(){} + public HttpGet(String p0){} + public HttpGet(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpHead.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpHead.java new file mode 100644 index 00000000000..a054dc90f86 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpHead.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpHead for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpRequestBase; + +public class HttpHead extends HttpRequestBase +{ + public HttpHead(){} + public HttpHead(String p0){} + public HttpHead(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpOptions.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpOptions.java new file mode 100644 index 00000000000..a1f4f2f7ba1 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpOptions.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.http.client.methods.HttpOptions for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import java.util.Set; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpRequestBase; + +public class HttpOptions extends HttpRequestBase +{ + public HttpOptions(){} + public HttpOptions(String p0){} + public HttpOptions(URI p0){} + public Set getAllowedMethods(HttpResponse p0){ return null; } + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPatch.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPatch.java new file mode 100644 index 00000000000..9b4f315a524 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPatch.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpPatch for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +public class HttpPatch extends HttpEntityEnclosingRequestBase +{ + public HttpPatch(){} + public HttpPatch(String p0){} + public HttpPatch(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPost.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPost.java new file mode 100644 index 00000000000..cea85f34424 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPost.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpPost for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +public class HttpPost extends HttpEntityEnclosingRequestBase +{ + public HttpPost(){} + public HttpPost(String p0){} + public HttpPost(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPut.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPut.java new file mode 100644 index 00000000000..5ca471ca077 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpPut.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpPut for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpEntityEnclosingRequestBase; + +public class HttpPut extends HttpEntityEnclosingRequestBase +{ + public HttpPut(){} + public HttpPut(String p0){} + public HttpPut(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpRequestBase.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpRequestBase.java new file mode 100644 index 00000000000..45f64538929 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpRequestBase.java @@ -0,0 +1,27 @@ +// Generated automatically from org.apache.http.client.methods.HttpRequestBase for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.AbstractExecutionAwareRequest; +import org.apache.http.client.methods.Configurable; +import org.apache.http.client.methods.HttpUriRequest; + +abstract public class HttpRequestBase extends AbstractExecutionAwareRequest implements Configurable, HttpUriRequest +{ + public HttpRequestBase(){} + public ProtocolVersion getProtocolVersion(){ return null; } + public RequestConfig getConfig(){ return null; } + public RequestLine getRequestLine(){ return null; } + public String toString(){ return null; } + public URI getURI(){ return null; } + public abstract String getMethod(); + public void releaseConnection(){} + public void setConfig(RequestConfig p0){} + public void setProtocolVersion(ProtocolVersion p0){} + public void setURI(URI p0){} + public void started(){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpTrace.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpTrace.java new file mode 100644 index 00000000000..9809ca8e8c5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpTrace.java @@ -0,0 +1,15 @@ +// Generated automatically from org.apache.http.client.methods.HttpTrace for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.client.methods.HttpRequestBase; + +public class HttpTrace extends HttpRequestBase +{ + public HttpTrace(){} + public HttpTrace(String p0){} + public HttpTrace(URI p0){} + public String getMethod(){ return null; } + public static String METHOD_NAME = null; +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpUriRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpUriRequest.java new file mode 100644 index 00000000000..87e9ffd286b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/HttpUriRequest.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.http.client.methods.HttpUriRequest for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import org.apache.http.HttpRequest; + +public interface HttpUriRequest extends HttpRequest +{ + String getMethod(); + URI getURI(); + boolean isAborted(); + void abort(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/RequestBuilder.java b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/RequestBuilder.java new file mode 100644 index 00000000000..4773a1268e0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/client/methods/RequestBuilder.java @@ -0,0 +1,71 @@ +// Generated automatically from org.apache.http.client.methods.RequestBuilder for testing purposes + +package org.apache.http.client.methods; + +import java.net.URI; +import java.nio.charset.Charset; +import java.util.List; +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpRequest; +import org.apache.http.NameValuePair; +import org.apache.http.ProtocolVersion; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.HttpUriRequest; + +public class RequestBuilder +{ + public Charset getCharset(){ return null; } + public Header getFirstHeader(String p0){ return null; } + public Header getLastHeader(String p0){ return null; } + public Header[] getHeaders(String p0){ return null; } + public HttpEntity getEntity(){ return null; } + public HttpUriRequest build(){ return null; } + public List getParameters(){ return null; } + public ProtocolVersion getVersion(){ return null; } + public RequestBuilder addHeader(Header p0){ return null; } + public RequestBuilder addHeader(String p0, String p1){ return null; } + public RequestBuilder addParameter(NameValuePair p0){ return null; } + public RequestBuilder addParameter(String p0, String p1){ return null; } + public RequestBuilder addParameters(NameValuePair... p0){ return null; } + public RequestBuilder removeHeader(Header p0){ return null; } + public RequestBuilder removeHeaders(String p0){ return null; } + public RequestBuilder setCharset(Charset p0){ return null; } + public RequestBuilder setConfig(RequestConfig p0){ return null; } + public RequestBuilder setEntity(HttpEntity p0){ return null; } + public RequestBuilder setHeader(Header p0){ return null; } + public RequestBuilder setHeader(String p0, String p1){ return null; } + public RequestBuilder setUri(String p0){ return null; } + public RequestBuilder setUri(URI p0){ return null; } + public RequestBuilder setVersion(ProtocolVersion p0){ return null; } + public RequestConfig getConfig(){ return null; } + public String getMethod(){ return null; } + public String toString(){ return null; } + public URI getUri(){ return null; } + public static RequestBuilder copy(HttpRequest p0){ return null; } + public static RequestBuilder create(String p0){ return null; } + public static RequestBuilder delete(){ return null; } + public static RequestBuilder delete(String p0){ return null; } + public static RequestBuilder delete(URI p0){ return null; } + public static RequestBuilder get(){ return null; } + public static RequestBuilder get(String p0){ return null; } + public static RequestBuilder get(URI p0){ return null; } + public static RequestBuilder head(){ return null; } + public static RequestBuilder head(String p0){ return null; } + public static RequestBuilder head(URI p0){ return null; } + public static RequestBuilder options(){ return null; } + public static RequestBuilder options(String p0){ return null; } + public static RequestBuilder options(URI p0){ return null; } + public static RequestBuilder patch(){ return null; } + public static RequestBuilder patch(String p0){ return null; } + public static RequestBuilder patch(URI p0){ return null; } + public static RequestBuilder post(){ return null; } + public static RequestBuilder post(String p0){ return null; } + public static RequestBuilder post(URI p0){ return null; } + public static RequestBuilder put(){ return null; } + public static RequestBuilder put(String p0){ return null; } + public static RequestBuilder put(URI p0){ return null; } + public static RequestBuilder trace(){ return null; } + public static RequestBuilder trace(String p0){ return null; } + public static RequestBuilder trace(URI p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/concurrent/Cancellable.java b/java/ql/test/stubs/javafx-web/org/apache/http/concurrent/Cancellable.java new file mode 100644 index 00000000000..8ed9e80fb78 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/concurrent/Cancellable.java @@ -0,0 +1,9 @@ +// Generated automatically from org.apache.http.concurrent.Cancellable for testing purposes + +package org.apache.http.concurrent; + + +public interface Cancellable +{ + boolean cancel(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/ClientConnectionRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ClientConnectionRequest.java new file mode 100644 index 00000000000..ced43fa25bf --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ClientConnectionRequest.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.http.conn.ClientConnectionRequest for testing purposes + +package org.apache.http.conn; + +import java.util.concurrent.TimeUnit; +import org.apache.http.conn.ManagedClientConnection; + +public interface ClientConnectionRequest +{ + ManagedClientConnection getConnection(long p0, TimeUnit p1); + void abortRequest(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/ConnectionReleaseTrigger.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ConnectionReleaseTrigger.java new file mode 100644 index 00000000000..0a92d18bb5d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ConnectionReleaseTrigger.java @@ -0,0 +1,10 @@ +// Generated automatically from org.apache.http.conn.ConnectionReleaseTrigger for testing purposes + +package org.apache.http.conn; + + +public interface ConnectionReleaseTrigger +{ + void abortConnection(); + void releaseConnection(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/HttpRoutedConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/HttpRoutedConnection.java new file mode 100644 index 00000000000..173aaa413c9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/HttpRoutedConnection.java @@ -0,0 +1,14 @@ +// Generated automatically from org.apache.http.conn.HttpRoutedConnection for testing purposes + +package org.apache.http.conn; + +import javax.net.ssl.SSLSession; +import org.apache.http.HttpInetConnection; +import org.apache.http.conn.routing.HttpRoute; + +public interface HttpRoutedConnection extends HttpInetConnection +{ + HttpRoute getRoute(); + SSLSession getSSLSession(); + boolean isSecure(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedClientConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedClientConnection.java new file mode 100644 index 00000000000..5f023965e52 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedClientConnection.java @@ -0,0 +1,30 @@ +// Generated automatically from org.apache.http.conn.ManagedClientConnection for testing purposes + +package org.apache.http.conn; + +import java.util.concurrent.TimeUnit; +import javax.net.ssl.SSLSession; +import org.apache.http.HttpHost; +import org.apache.http.conn.ConnectionReleaseTrigger; +import org.apache.http.conn.HttpRoutedConnection; +import org.apache.http.conn.ManagedHttpClientConnection; +import org.apache.http.conn.routing.HttpRoute; +import org.apache.http.params.HttpParams; +import org.apache.http.protocol.HttpContext; + +public interface ManagedClientConnection extends ConnectionReleaseTrigger, HttpRoutedConnection, ManagedHttpClientConnection +{ + HttpRoute getRoute(); + Object getState(); + SSLSession getSSLSession(); + boolean isMarkedReusable(); + boolean isSecure(); + void layerProtocol(HttpContext p0, HttpParams p1); + void markReusable(); + void open(HttpRoute p0, HttpContext p1, HttpParams p2); + void setIdleDuration(long p0, TimeUnit p1); + void setState(Object p0); + void tunnelProxy(HttpHost p0, boolean p1, HttpParams p2); + void tunnelTarget(boolean p0, HttpParams p1); + void unmarkReusable(); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedHttpClientConnection.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedHttpClientConnection.java new file mode 100644 index 00000000000..12020570d8f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/ManagedHttpClientConnection.java @@ -0,0 +1,16 @@ +// Generated automatically from org.apache.http.conn.ManagedHttpClientConnection for testing purposes + +package org.apache.http.conn; + +import java.net.Socket; +import javax.net.ssl.SSLSession; +import org.apache.http.HttpClientConnection; +import org.apache.http.HttpInetConnection; + +public interface ManagedHttpClientConnection extends HttpClientConnection, HttpInetConnection +{ + SSLSession getSSLSession(); + Socket getSocket(); + String getId(); + void bind(Socket p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/HttpRoute.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/HttpRoute.java new file mode 100644 index 00000000000..bc1478278c0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/HttpRoute.java @@ -0,0 +1,34 @@ +// Generated automatically from org.apache.http.conn.routing.HttpRoute for testing purposes + +package org.apache.http.conn.routing; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import org.apache.http.HttpHost; +import org.apache.http.conn.routing.RouteInfo; + +public class HttpRoute implements Cloneable, RouteInfo +{ + protected HttpRoute() {} + public HttpRoute(HttpHost p0){} + public HttpRoute(HttpHost p0, HttpHost p1){} + public HttpRoute(HttpHost p0, InetAddress p1, HttpHost p2, boolean p3){} + public HttpRoute(HttpHost p0, InetAddress p1, HttpHost p2, boolean p3, RouteInfo.TunnelType p4, RouteInfo.LayerType p5){} + public HttpRoute(HttpHost p0, InetAddress p1, HttpHost[] p2, boolean p3, RouteInfo.TunnelType p4, RouteInfo.LayerType p5){} + public HttpRoute(HttpHost p0, InetAddress p1, boolean p2){} + public Object clone(){ return null; } + public final HttpHost getHopTarget(int p0){ return null; } + public final HttpHost getProxyHost(){ return null; } + public final HttpHost getTargetHost(){ return null; } + public final InetAddress getLocalAddress(){ return null; } + public final InetSocketAddress getLocalSocketAddress(){ return null; } + public final RouteInfo.LayerType getLayerType(){ return null; } + public final RouteInfo.TunnelType getTunnelType(){ return null; } + public final String toString(){ return null; } + public final boolean equals(Object p0){ return false; } + public final boolean isLayered(){ return false; } + public final boolean isSecure(){ return false; } + public final boolean isTunnelled(){ return false; } + public final int getHopCount(){ return 0; } + public final int hashCode(){ return 0; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/RouteInfo.java b/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/RouteInfo.java new file mode 100644 index 00000000000..41442212714 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/conn/routing/RouteInfo.java @@ -0,0 +1,30 @@ +// Generated automatically from org.apache.http.conn.routing.RouteInfo for testing purposes + +package org.apache.http.conn.routing; + +import java.net.InetAddress; +import org.apache.http.HttpHost; + +public interface RouteInfo +{ + HttpHost getHopTarget(int p0); + HttpHost getProxyHost(); + HttpHost getTargetHost(); + InetAddress getLocalAddress(); + RouteInfo.LayerType getLayerType(); + RouteInfo.TunnelType getTunnelType(); + boolean isLayered(); + boolean isSecure(); + boolean isTunnelled(); + int getHopCount(); + static public enum LayerType + { + LAYERED, PLAIN; + private LayerType() {} + } + static public enum TunnelType + { + PLAIN, TUNNELLED; + private TunnelType() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/message/AbstractHttpMessage.java b/java/ql/test/stubs/javafx-web/org/apache/http/message/AbstractHttpMessage.java new file mode 100644 index 00000000000..90aa1261896 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/message/AbstractHttpMessage.java @@ -0,0 +1,33 @@ +// Generated automatically from org.apache.http.message.AbstractHttpMessage for testing purposes + +package org.apache.http.message; + +import org.apache.http.Header; +import org.apache.http.HeaderIterator; +import org.apache.http.HttpMessage; +import org.apache.http.message.HeaderGroup; +import org.apache.http.params.HttpParams; + +abstract public class AbstractHttpMessage implements HttpMessage +{ + protected AbstractHttpMessage(){} + protected AbstractHttpMessage(HttpParams p0){} + protected HeaderGroup headergroup = null; + protected HttpParams params = null; + public Header getFirstHeader(String p0){ return null; } + public Header getLastHeader(String p0){ return null; } + public HeaderIterator headerIterator(){ return null; } + public HeaderIterator headerIterator(String p0){ return null; } + public Header[] getAllHeaders(){ return null; } + public Header[] getHeaders(String p0){ return null; } + public HttpParams getParams(){ return null; } + public boolean containsHeader(String p0){ return false; } + public void addHeader(Header p0){} + public void addHeader(String p0, String p1){} + public void removeHeader(Header p0){} + public void removeHeaders(String p0){} + public void setHeader(Header p0){} + public void setHeader(String p0, String p1){} + public void setHeaders(Header[] p0){} + public void setParams(HttpParams p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpEntityEnclosingRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpEntityEnclosingRequest.java new file mode 100644 index 00000000000..2d1de9d45fb --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpEntityEnclosingRequest.java @@ -0,0 +1,20 @@ +// Generated automatically from org.apache.http.message.BasicHttpEntityEnclosingRequest for testing purposes + +package org.apache.http.message; + +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.message.BasicHttpRequest; + +public class BasicHttpEntityEnclosingRequest extends BasicHttpRequest implements HttpEntityEnclosingRequest +{ + protected BasicHttpEntityEnclosingRequest() {} + public BasicHttpEntityEnclosingRequest(RequestLine p0){} + public BasicHttpEntityEnclosingRequest(String p0, String p1){} + public BasicHttpEntityEnclosingRequest(String p0, String p1, ProtocolVersion p2){} + public HttpEntity getEntity(){ return null; } + public boolean expectContinue(){ return false; } + public void setEntity(HttpEntity p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpRequest.java b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpRequest.java new file mode 100644 index 00000000000..455f0167a39 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicHttpRequest.java @@ -0,0 +1,19 @@ +// Generated automatically from org.apache.http.message.BasicHttpRequest for testing purposes + +package org.apache.http.message; + +import org.apache.http.HttpRequest; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; +import org.apache.http.message.AbstractHttpMessage; + +public class BasicHttpRequest extends AbstractHttpMessage implements HttpRequest +{ + protected BasicHttpRequest() {} + public BasicHttpRequest(RequestLine p0){} + public BasicHttpRequest(String p0, String p1){} + public BasicHttpRequest(String p0, String p1, ProtocolVersion p2){} + public ProtocolVersion getProtocolVersion(){ return null; } + public RequestLine getRequestLine(){ return null; } + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicRequestLine.java b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicRequestLine.java new file mode 100644 index 00000000000..50f3e1ceb6c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/message/BasicRequestLine.java @@ -0,0 +1,18 @@ +// Generated automatically from org.apache.http.message.BasicRequestLine for testing purposes + +package org.apache.http.message; + +import java.io.Serializable; +import org.apache.http.ProtocolVersion; +import org.apache.http.RequestLine; + +public class BasicRequestLine implements Cloneable, RequestLine, Serializable +{ + protected BasicRequestLine() {} + public BasicRequestLine(String p0, String p1, ProtocolVersion p2){} + public Object clone(){ return null; } + public ProtocolVersion getProtocolVersion(){ return null; } + public String getMethod(){ return null; } + public String getUri(){ return null; } + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/message/HeaderGroup.java b/java/ql/test/stubs/javafx-web/org/apache/http/message/HeaderGroup.java new file mode 100644 index 00000000000..ec6687ed789 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/message/HeaderGroup.java @@ -0,0 +1,28 @@ +// Generated automatically from org.apache.http.message.HeaderGroup for testing purposes + +package org.apache.http.message; + +import java.io.Serializable; +import org.apache.http.Header; +import org.apache.http.HeaderIterator; + +public class HeaderGroup implements Cloneable, Serializable +{ + public Header getCondensedHeader(String p0){ return null; } + public Header getFirstHeader(String p0){ return null; } + public Header getLastHeader(String p0){ return null; } + public HeaderGroup copy(){ return null; } + public HeaderGroup(){} + public HeaderIterator iterator(){ return null; } + public HeaderIterator iterator(String p0){ return null; } + public Header[] getAllHeaders(){ return null; } + public Header[] getHeaders(String p0){ return null; } + public Object clone(){ return null; } + public String toString(){ return null; } + public boolean containsHeader(String p0){ return false; } + public void addHeader(Header p0){} + public void clear(){} + public void removeHeader(Header p0){} + public void setHeaders(Header[] p0){} + public void updateHeader(Header p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/params/HttpParams.java b/java/ql/test/stubs/javafx-web/org/apache/http/params/HttpParams.java new file mode 100644 index 00000000000..13cede776d4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/params/HttpParams.java @@ -0,0 +1,22 @@ +// Generated automatically from org.apache.http.params.HttpParams for testing purposes + +package org.apache.http.params; + + +public interface HttpParams +{ + HttpParams copy(); + HttpParams setBooleanParameter(String p0, boolean p1); + HttpParams setDoubleParameter(String p0, double p1); + HttpParams setIntParameter(String p0, int p1); + HttpParams setLongParameter(String p0, long p1); + HttpParams setParameter(String p0, Object p1); + Object getParameter(String p0); + boolean getBooleanParameter(String p0, boolean p1); + boolean isParameterFalse(String p0); + boolean isParameterTrue(String p0); + boolean removeParameter(String p0); + double getDoubleParameter(String p0, double p1); + int getIntParameter(String p0, int p1); + long getLongParameter(String p0, long p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/apache/http/protocol/HttpContext.java b/java/ql/test/stubs/javafx-web/org/apache/http/protocol/HttpContext.java new file mode 100644 index 00000000000..d2e14c83858 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/apache/http/protocol/HttpContext.java @@ -0,0 +1,12 @@ +// Generated automatically from org.apache.http.protocol.HttpContext for testing purposes + +package org.apache.http.protocol; + + +public interface HttpContext +{ + Object getAttribute(String p0); + Object removeAttribute(String p0); + static String RESERVED_PREFIX = null; + void setAttribute(String p0, Object p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Installer.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Installer.java new file mode 100644 index 00000000000..02abcd95563 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Installer.java @@ -0,0 +1,11 @@ +// Generated automatically from org.codehaus.cargo.container.installer.Installer for testing purposes + +package org.codehaus.cargo.container.installer; + +import org.codehaus.cargo.util.log.Loggable; + +public interface Installer extends Loggable +{ + String getHome(); + void install(); +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Proxy.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Proxy.java new file mode 100644 index 00000000000..de5da1c1766 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/Proxy.java @@ -0,0 +1,23 @@ +// Generated automatically from org.codehaus.cargo.container.installer.Proxy for testing purposes + +package org.codehaus.cargo.container.installer; + +import java.util.Map; +import org.codehaus.cargo.util.log.LoggedObject; + +public class Proxy extends LoggedObject +{ + public Map configure(){ return null; } + public Proxy(){} + public String getExcludeHosts(){ return null; } + public String getHost(){ return null; } + public String getPassword(){ return null; } + public String getUser(){ return null; } + public int getPort(){ return 0; } + public void clear(Map p0){} + public void setExcludeHosts(String p0){} + public void setHost(String p0){} + public void setPassword(String p0){} + public void setPort(int p0){} + public void setUser(String p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/ZipURLInstaller.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/ZipURLInstaller.java new file mode 100644 index 00000000000..638a19d89fc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/container/installer/ZipURLInstaller.java @@ -0,0 +1,34 @@ +// Generated automatically from org.codehaus.cargo.container.installer.ZipURLInstaller for testing purposes + +package org.codehaus.cargo.container.installer; + +import java.net.URL; +import org.codehaus.cargo.container.installer.Installer; +import org.codehaus.cargo.container.installer.Proxy; +import org.codehaus.cargo.util.FileHandler; +import org.codehaus.cargo.util.log.LoggedObject; +import org.codehaus.cargo.util.log.Logger; + +public class ZipURLInstaller extends LoggedObject implements Installer +{ + protected ZipURLInstaller() {} + protected String getSourceFileName(){ return null; } + protected void doDownload(){} + public FileHandler getFileHandler(){ return null; } + public String getDownloadDir(){ return null; } + public String getDownloadFile(){ return null; } + public String getExtractDir(){ return null; } + public String getHome(){ return null; } + public ZipURLInstaller(URL p0){} + public ZipURLInstaller(URL p0, String p1, String p2){} + public boolean isAlreadyDownloaded(){ return false; } + public boolean isAlreadyExtracted(){ return false; } + public void download(){} + public void install(){} + public void registerInstallation(){} + public void setDownloadDir(String p0){} + public void setExtractDir(String p0){} + public void setFileHandler(FileHandler p0){} + public void setLogger(Logger p0){} + public void setProxy(Proxy p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/FileHandler.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/FileHandler.java new file mode 100644 index 00000000000..07579277d95 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/FileHandler.java @@ -0,0 +1,49 @@ +// Generated automatically from org.codehaus.cargo.util.FileHandler for testing purposes + +package org.codehaus.cargo.util; + +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; +import org.codehaus.cargo.util.XmlReplacement; +import org.codehaus.cargo.util.log.Loggable; + +public interface FileHandler extends Loggable +{ + InputStream getInputStream(String p0); + OutputStream getOutputStream(String p0); + String append(String p0, String p1); + String createDirectory(String p0, String p1); + String createUniqueTmpDirectory(); + String getAbsolutePath(String p0); + String getName(String p0); + String getParent(String p0); + String getTmpPath(String p0); + String getURL(String p0); + String readTextFile(String p0, Charset p1); + String[] getChildren(String p0); + String[] getChildren(String p0, List p1); + boolean exists(String p0); + boolean isDirectory(String p0); + boolean isDirectoryEmpty(String p0); + long getSize(String p0); + static String NEW_LINE = null; + void copy(InputStream p0, OutputStream p1); + void copy(InputStream p0, OutputStream p1, int p2); + void copyDirectory(String p0, String p1); + void copyDirectory(String p0, String p1, List p2); + void copyDirectory(String p0, String p1, Map p2, Charset p3); + void copyFile(String p0, String p1); + void copyFile(String p0, String p1, Map p2, Charset p3); + void copyFile(String p0, String p1, boolean p2); + void createFile(String p0); + void delete(String p0); + void explode(String p0, String p1); + void mkdirs(String p0); + void replaceInFile(String p0, Map p1, Charset p2); + void replaceInFile(String p0, Map p1, Charset p2, boolean p3); + void replaceInXmlFile(XmlReplacement... p0); + void writeTextFile(String p0, String p1, Charset p2); +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/XmlReplacement.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/XmlReplacement.java new file mode 100644 index 00000000000..16caa14f2b8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/XmlReplacement.java @@ -0,0 +1,28 @@ +// Generated automatically from org.codehaus.cargo.util.XmlReplacement for testing purposes + +package org.codehaus.cargo.util; + + +public class XmlReplacement +{ + public String getAttributeName(){ return null; } + public String getFile(){ return null; } + public String getValue(){ return null; } + public String getXpathExpression(){ return null; } + public String toString(){ return null; } + public XmlReplacement(){} + public XmlReplacement(String p0, String p1, String p2, XmlReplacement.ReplacementBehavior p3, String p4){} + public XmlReplacement.ReplacementBehavior getReplacementBehavior(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public void setAttributeName(String p0){} + public void setFile(String p0){} + public void setReplacementBehavior(XmlReplacement.ReplacementBehavior p0){} + public void setValue(String p0){} + public void setXpathExpression(String p0){} + static public enum ReplacementBehavior + { + ADD_MISSING_NODES, IGNORE_IF_NON_EXISTING, THROW_EXCEPTION; + private ReplacementBehavior() {} + } +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LogLevel.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LogLevel.java new file mode 100644 index 00000000000..b7b0d5a37d8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LogLevel.java @@ -0,0 +1,18 @@ +// Generated automatically from org.codehaus.cargo.util.log.LogLevel for testing purposes + +package org.codehaus.cargo.util.log; + + +public class LogLevel implements Comparable +{ + protected LogLevel() {} + public String getLevel(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int compareTo(LogLevel p0){ return 0; } + public int hashCode(){ return 0; } + public static LogLevel DEBUG = null; + public static LogLevel INFO = null; + public static LogLevel WARN = null; + public static LogLevel toLevel(String p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Loggable.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Loggable.java new file mode 100644 index 00000000000..3369fa27ef5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Loggable.java @@ -0,0 +1,11 @@ +// Generated automatically from org.codehaus.cargo.util.log.Loggable for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.Logger; + +public interface Loggable +{ + Logger getLogger(); + void setLogger(Logger p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LoggedObject.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LoggedObject.java new file mode 100644 index 00000000000..421da028778 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/LoggedObject.java @@ -0,0 +1,13 @@ +// Generated automatically from org.codehaus.cargo.util.log.LoggedObject for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.Loggable; +import org.codehaus.cargo.util.log.Logger; + +public class LoggedObject implements Loggable +{ + public LoggedObject(){} + public Logger getLogger(){ return null; } + public void setLogger(Logger p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Logger.java b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Logger.java new file mode 100644 index 00000000000..965e4bc1ccd --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/codehaus/cargo/util/log/Logger.java @@ -0,0 +1,14 @@ +// Generated automatically from org.codehaus.cargo.util.log.Logger for testing purposes + +package org.codehaus.cargo.util.log; + +import org.codehaus.cargo.util.log.LogLevel; + +public interface Logger +{ + LogLevel getLevel(); + void debug(String p0, String p1); + void info(String p0, String p1); + void setLevel(LogLevel p0); + void warn(String p0, String p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/ConnectionFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/ConnectionFactory.java new file mode 100644 index 00000000000..b833b0d8b99 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/ConnectionFactory.java @@ -0,0 +1,13 @@ +// Generated automatically from org.jdbi.v3.core.ConnectionFactory for testing purposes + +package org.jdbi.v3.core; + +import java.sql.Connection; +import org.jdbi.v3.core.statement.Cleanable; + +public interface ConnectionFactory +{ + Connection openConnection(); + default Cleanable getCleanableFor(Connection p0){ return null; } + default void closeConnection(Connection p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Handle.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Handle.java new file mode 100644 index 00000000000..585d7fda6db --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Handle.java @@ -0,0 +1,84 @@ +// Generated automatically from org.jdbi.v3.core.Handle for testing purposes + +package org.jdbi.v3.core; + +import java.io.Closeable; +import java.sql.Connection; +import org.jdbi.v3.core.HandleCallback; +import org.jdbi.v3.core.HandleConsumer; +import org.jdbi.v3.core.HandleListener; +import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.config.Configurable; +import org.jdbi.v3.core.extension.ExtensionMethod; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.statement.Batch; +import org.jdbi.v3.core.statement.Call; +import org.jdbi.v3.core.statement.Cleanable; +import org.jdbi.v3.core.statement.MetaData; +import org.jdbi.v3.core.statement.PreparedBatch; +import org.jdbi.v3.core.statement.Query; +import org.jdbi.v3.core.statement.Script; +import org.jdbi.v3.core.statement.StatementBuilder; +import org.jdbi.v3.core.statement.Update; +import org.jdbi.v3.core.transaction.TransactionIsolationLevel; + +public class Handle implements Closeable, Configurable +{ + protected Handle() {} + public R inTransaction(TransactionIsolationLevel p0, org.jdbi.v3.core.HandleCallback p1){ return null; } + public R inTransaction(org.jdbi.v3.core.HandleCallback p0){ return null; } + public T attach(java.lang.Class p0){ return null; } + public T queryMetadata(MetaData.MetaDataValueProvider p0){ return null; } + public void useTransaction(TransactionIsolationLevel p0, org.jdbi.v3.core.HandleConsumer p1){} + public void useTransaction(org.jdbi.v3.core.HandleConsumer p0){} + public Batch createBatch(){ return null; } + public Call createCall(CharSequence p0){ return null; } + public Call createCall(String p0){ return null; } + public ConfigRegistry getConfig(){ return null; } + public Connection getConnection(){ return null; } + public ExtensionMethod getExtensionMethod(){ return null; } + public Handle addHandleListener(HandleListener p0){ return null; } + public Handle afterCommit(Runnable p0){ return null; } + public Handle afterRollback(Runnable p0){ return null; } + public Handle begin(){ return null; } + public Handle commit(){ return null; } + public Handle release(String p0){ return null; } + public Handle releaseSavepoint(String p0){ return null; } + public Handle removeHandleListener(HandleListener p0){ return null; } + public Handle rollback(){ return null; } + public Handle rollbackToSavepoint(String p0){ return null; } + public Handle savepoint(String p0){ return null; } + public Handle setReadOnly(boolean p0){ return null; } + public Handle setStatementBuilder(StatementBuilder p0){ return null; } + public Jdbi getJdbi(){ return null; } + public PreparedBatch prepareBatch(CharSequence p0){ return null; } + public PreparedBatch prepareBatch(String p0){ return null; } + public Query createQuery(CharSequence p0){ return null; } + public Query createQuery(String p0){ return null; } + public Query select(CharSequence p0, Object... p1){ return null; } + public Query select(String p0, Object... p1){ return null; } + public ResultBearing queryMetadata(MetaData.MetaDataResultSetProvider p0){ return null; } + public Script createScript(CharSequence p0){ return null; } + public Script createScript(String p0){ return null; } + public StatementBuilder getStatementBuilder(){ return null; } + public TransactionIsolationLevel getTransactionIsolationLevel(){ return null; } + public Update createUpdate(CharSequence p0){ return null; } + public Update createUpdate(String p0){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isClean(){ return false; } + public boolean isClosed(){ return false; } + public boolean isInTransaction(){ return false; } + public boolean isReadOnly(){ return false; } + public final void addCleanable(Cleanable p0){} + public final void removeCleanable(Cleanable p0){} + public int execute(CharSequence p0, Object... p1){ return 0; } + public int execute(String p0, Object... p1){ return 0; } + public int hashCode(){ return 0; } + public void clean(){} + public void close(){} + public void setTransactionIsolation(TransactionIsolationLevel p0){} + public void setTransactionIsolation(int p0){} + public void setTransactionIsolationLevel(TransactionIsolationLevel p0){} + public void setTransactionIsolationLevel(int p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleCallback.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleCallback.java new file mode 100644 index 00000000000..c6d09df1cea --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.HandleCallback for testing purposes + +package org.jdbi.v3.core; + +import org.jdbi.v3.core.Handle; + +public interface HandleCallback +{ + T withHandle(Handle p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleConsumer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleConsumer.java new file mode 100644 index 00000000000..1345b45a659 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleConsumer.java @@ -0,0 +1,12 @@ +// Generated automatically from org.jdbi.v3.core.HandleConsumer for testing purposes + +package org.jdbi.v3.core; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.HandleCallback; + +public interface HandleConsumer +{ + default HandleCallback asCallback(){ return null; } + void useHandle(Handle p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleListener.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleListener.java new file mode 100644 index 00000000000..5b1f14b9d7d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/HandleListener.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.HandleListener for testing purposes + +package org.jdbi.v3.core; + +import org.jdbi.v3.core.Handle; + +public interface HandleListener +{ + default void handleClosed(Handle p0){} + default void handleCreated(Handle p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Jdbi.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Jdbi.java new file mode 100644 index 00000000000..7e2a1de7c77 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/Jdbi.java @@ -0,0 +1,53 @@ +// Generated automatically from org.jdbi.v3.core.Jdbi for testing purposes + +package org.jdbi.v3.core; + +import java.sql.Connection; +import java.util.Properties; +import javax.sql.DataSource; +import org.jdbi.v3.core.ConnectionFactory; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.HandleCallback; +import org.jdbi.v3.core.HandleConsumer; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.config.Configurable; +import org.jdbi.v3.core.extension.ExtensionCallback; +import org.jdbi.v3.core.extension.ExtensionConsumer; +import org.jdbi.v3.core.spi.JdbiPlugin; +import org.jdbi.v3.core.statement.StatementBuilderFactory; +import org.jdbi.v3.core.transaction.TransactionHandler; +import org.jdbi.v3.core.transaction.TransactionIsolationLevel; + +public class Jdbi implements Configurable +{ + protected Jdbi() {} + public void useExtension(java.lang.Class p0, ExtensionConsumer p1){} + public E onDemand(java.lang.Class p0){ return null; } + public R withExtension(java.lang.Class p0, ExtensionCallback p1){ return null; } + public R inTransaction(TransactionIsolationLevel p0, org.jdbi.v3.core.HandleCallback p1){ return null; } + public R inTransaction(org.jdbi.v3.core.HandleCallback p0){ return null; } + public R withHandle(org.jdbi.v3.core.HandleCallback p0){ return null; } + public void useHandle(org.jdbi.v3.core.HandleConsumer p0){} + public void useTransaction(TransactionIsolationLevel p0, org.jdbi.v3.core.HandleConsumer p1){} + public void useTransaction(org.jdbi.v3.core.HandleConsumer p0){} + public ConfigRegistry getConfig(){ return null; } + public Handle open(){ return null; } + public Jdbi installPlugin(JdbiPlugin p0){ return null; } + public Jdbi installPlugins(){ return null; } + public Jdbi setStatementBuilderFactory(StatementBuilderFactory p0){ return null; } + public Jdbi setTransactionHandler(TransactionHandler p0){ return null; } + public StatementBuilderFactory getStatementBuilderFactory(){ return null; } + public TransactionHandler getTransactionHandler(){ return null; } + public static Handle open(Connection p0){ return null; } + public static Handle open(ConnectionFactory p0){ return null; } + public static Handle open(DataSource p0){ return null; } + public static Handle open(String p0){ return null; } + public static Handle open(String p0, Properties p1){ return null; } + public static Handle open(String p0, String p1, String p2){ return null; } + public static Jdbi create(Connection p0){ return null; } + public static Jdbi create(ConnectionFactory p0){ return null; } + public static Jdbi create(DataSource p0){ return null; } + public static Jdbi create(String p0){ return null; } + public static Jdbi create(String p0, Properties p1){ return null; } + public static Jdbi create(String p0, String p1, String p2){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/Argument.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/Argument.java new file mode 100644 index 00000000000..97cd7042772 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/Argument.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.argument.Argument for testing purposes + +package org.jdbi.v3.core.argument; + +import java.sql.PreparedStatement; +import org.jdbi.v3.core.statement.StatementContext; + +public interface Argument +{ + void apply(int p0, PreparedStatement p1, StatementContext p2); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/ArgumentFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/ArgumentFactory.java new file mode 100644 index 00000000000..4f197c3e50e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/ArgumentFactory.java @@ -0,0 +1,21 @@ +// Generated automatically from org.jdbi.v3.core.argument.ArgumentFactory for testing purposes + +package org.jdbi.v3.core.argument; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Optional; +import java.util.function.Function; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.config.ConfigRegistry; + +public interface ArgumentFactory +{ + Optional build(Type p0, Object p1, ConfigRegistry p2); + static public interface Preparable extends ArgumentFactory + { + Optional> prepare(Type p0, ConfigRegistry p1); + default Collection prePreparedTypes(){ return null; } + default Optional build(Type p0, Object p1, ConfigRegistry p2){ return null; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/NamedArgumentFinder.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/NamedArgumentFinder.java new file mode 100644 index 00000000000..730b7f025e5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/NamedArgumentFinder.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.argument.NamedArgumentFinder for testing purposes + +package org.jdbi.v3.core.argument; + +import java.util.Collection; +import java.util.Optional; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.statement.StatementContext; + +public interface NamedArgumentFinder +{ + Optional find(String p0, StatementContext p1); + default Collection getNames(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/QualifiedArgumentFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/QualifiedArgumentFactory.java new file mode 100644 index 00000000000..3329c56bce8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/QualifiedArgumentFactory.java @@ -0,0 +1,24 @@ +// Generated automatically from org.jdbi.v3.core.argument.QualifiedArgumentFactory for testing purposes + +package org.jdbi.v3.core.argument; + +import java.util.Collection; +import java.util.Optional; +import java.util.function.Function; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.argument.ArgumentFactory; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.qualifier.QualifiedType; + +public interface QualifiedArgumentFactory +{ + Optional build(QualifiedType p0, Object p1, ConfigRegistry p2); + static QualifiedArgumentFactory adapt(ConfigRegistry p0, ArgumentFactory p1){ return null; } + static QualifiedArgumentFactory.Preparable adapt(ConfigRegistry p0, ArgumentFactory.Preparable p1){ return null; } + static public interface Preparable extends QualifiedArgumentFactory + { + Optional> prepare(QualifiedType p0, ConfigRegistry p1); + default Collection> prePreparedTypes(){ return null; } + static QualifiedArgumentFactory.Preparable adapt(ConfigRegistry p0, ArgumentFactory.Preparable p1){ return null; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/internal/NamedArgumentFinderFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/internal/NamedArgumentFinderFactory.java new file mode 100644 index 00000000000..a9d39d2b658 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/argument/internal/NamedArgumentFinderFactory.java @@ -0,0 +1,26 @@ +// Generated automatically from org.jdbi.v3.core.argument.internal.NamedArgumentFinderFactory for testing purposes + +package org.jdbi.v3.core.argument.internal; + +import java.lang.reflect.Type; +import java.util.Optional; +import java.util.function.Function; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.qualifier.QualifiedType; + +public interface NamedArgumentFinderFactory +{ + Function>> prepareFor(ConfigRegistry p0, Function, Function> p1, String p2, Object p3, Type p4); + NamedArgumentFinderFactory.PrepareKey keyFor(String p0, Object p1); + static NamedArgumentFinderFactory BEAN = null; + static NamedArgumentFinderFactory FIELDS = null; + static NamedArgumentFinderFactory METHODS = null; + static NamedArgumentFinderFactory POJO = null; + static public class PrepareKey + { + protected PrepareKey() {} + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayArgumentStrategy.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayArgumentStrategy.java new file mode 100644 index 00000000000..c7ace164c41 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayArgumentStrategy.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.array.SqlArrayArgumentStrategy for testing purposes + +package org.jdbi.v3.core.array; + + +public enum SqlArrayArgumentStrategy +{ + OBJECT_ARRAY, SQL_ARRAY; + private SqlArrayArgumentStrategy() {} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayType.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayType.java new file mode 100644 index 00000000000..d4febf40f4e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayType.java @@ -0,0 +1,13 @@ +// Generated automatically from org.jdbi.v3.core.array.SqlArrayType for testing purposes + +package org.jdbi.v3.core.array; + +import java.util.function.Function; + +public interface SqlArrayType +{ + Object convertArrayElement(T p0); + String getTypeName(); + default Class getArrayElementClass(){ return null; } + static SqlArrayType of(String p0, java.util.function.Function p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayTypeFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayTypeFactory.java new file mode 100644 index 00000000000..30fa19bab35 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/array/SqlArrayTypeFactory.java @@ -0,0 +1,15 @@ +// Generated automatically from org.jdbi.v3.core.array.SqlArrayTypeFactory for testing purposes + +package org.jdbi.v3.core.array; + +import java.lang.reflect.Type; +import java.util.Optional; +import java.util.function.Function; +import org.jdbi.v3.core.array.SqlArrayType; +import org.jdbi.v3.core.config.ConfigRegistry; + +public interface SqlArrayTypeFactory +{ + Optional> build(Type p0, ConfigRegistry p1); + static SqlArrayTypeFactory of(java.lang.Class p0, String p1, java.util.function.Function p2){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/Codec.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/Codec.java new file mode 100644 index 00000000000..d8bc947b036 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/Codec.java @@ -0,0 +1,16 @@ +// Generated automatically from org.jdbi.v3.core.codec.Codec for testing purposes + +package org.jdbi.v3.core.codec; + +import java.util.function.Function; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.mapper.ColumnMapper; + +public interface Codec +{ + default Function getArgumentFunction(){ return null; } + default Function getArgumentFunction(ConfigRegistry p0){ return null; } + default org.jdbi.v3.core.mapper.ColumnMapper getColumnMapper(){ return null; } + default org.jdbi.v3.core.mapper.ColumnMapper getColumnMapper(ConfigRegistry p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/CodecFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/CodecFactory.java new file mode 100644 index 00000000000..0e704cd90e8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/codec/CodecFactory.java @@ -0,0 +1,41 @@ +// Generated automatically from org.jdbi.v3.core.codec.CodecFactory for testing purposes + +package org.jdbi.v3.core.codec; + +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Function; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.argument.QualifiedArgumentFactory; +import org.jdbi.v3.core.codec.Codec; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.generic.GenericType; +import org.jdbi.v3.core.mapper.ColumnMapper; +import org.jdbi.v3.core.mapper.QualifiedColumnMapperFactory; +import org.jdbi.v3.core.qualifier.QualifiedType; + +public class CodecFactory implements QualifiedArgumentFactory.Preparable, QualifiedColumnMapperFactory +{ + protected CodecFactory() {} + protected Codec resolveType(QualifiedType p0){ return null; } + protected final ConcurrentMap, Codec> codecMap = null; + public CodecFactory(Map, Codec> p0){} + public final Collection> prePreparedTypes(){ return null; } + public final Optional build(QualifiedType p0, Object p1, ConfigRegistry p2){ return null; } + public final Optional> build(QualifiedType p0, ConfigRegistry p1){ return null; } + public final Optional> prepare(QualifiedType p0, ConfigRegistry p1){ return null; } + public static CodecFactory forSingleCodec(QualifiedType p0, Codec p1){ return null; } + public static CodecFactory.Builder builder(){ return null; } + static public class Builder + { + protected Builder() {} + public Builder(Function, Codec>, CodecFactory> p0){} + public CodecFactory build(){ return null; } + public CodecFactory.Builder addCodec(GenericType p0, Codec p1){ return null; } + public CodecFactory.Builder addCodec(QualifiedType p0, Codec p1){ return null; } + public CodecFactory.Builder addCodec(Type p0, Codec p1){ return null; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/collector/CollectorFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/collector/CollectorFactory.java new file mode 100644 index 00000000000..1e528c775e8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/collector/CollectorFactory.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.collector.CollectorFactory for testing purposes + +package org.jdbi.v3.core.collector; + +import java.lang.reflect.Type; +import java.util.Optional; +import java.util.stream.Collector; + +public interface CollectorFactory +{ + Collector build(Type p0); + Optional elementType(Type p0); + boolean accepts(Type p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/ConfigRegistry.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/ConfigRegistry.java new file mode 100644 index 00000000000..9cf7e64624a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/ConfigRegistry.java @@ -0,0 +1,12 @@ +// Generated automatically from org.jdbi.v3.core.config.ConfigRegistry for testing purposes + +package org.jdbi.v3.core.config; + +import org.jdbi.v3.core.config.JdbiConfig; + +public class ConfigRegistry +{ + public > C get(java.lang.Class p0){ return null; } + public ConfigRegistry createCopy(){ return null; } + public ConfigRegistry(){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/Configurable.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/Configurable.java new file mode 100644 index 00000000000..0095f59b849 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/Configurable.java @@ -0,0 +1,64 @@ +// Generated automatically from org.jdbi.v3.core.config.Configurable for testing purposes + +package org.jdbi.v3.core.config; + +import java.lang.reflect.Type; +import java.util.function.Consumer; +import java.util.function.Function; +import org.jdbi.v3.core.argument.ArgumentFactory; +import org.jdbi.v3.core.argument.QualifiedArgumentFactory; +import org.jdbi.v3.core.array.SqlArrayArgumentStrategy; +import org.jdbi.v3.core.array.SqlArrayType; +import org.jdbi.v3.core.array.SqlArrayTypeFactory; +import org.jdbi.v3.core.codec.CodecFactory; +import org.jdbi.v3.core.collector.CollectorFactory; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.config.JdbiConfig; +import org.jdbi.v3.core.extension.ExtensionFactory; +import org.jdbi.v3.core.generic.GenericType; +import org.jdbi.v3.core.mapper.ColumnMapper; +import org.jdbi.v3.core.mapper.ColumnMapperFactory; +import org.jdbi.v3.core.mapper.QualifiedColumnMapperFactory; +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.mapper.RowMapperFactory; +import org.jdbi.v3.core.qualifier.QualifiedType; +import org.jdbi.v3.core.statement.SqlLogger; +import org.jdbi.v3.core.statement.SqlParser; +import org.jdbi.v3.core.statement.StatementCustomizer; +import org.jdbi.v3.core.statement.TemplateEngine; +import org.jdbi.v3.core.statement.TimingCollector; + +public interface Configurable +{ + ConfigRegistry getConfig(); + default > C getConfig(java.lang.Class p0){ return null; } + default > This configure(java.lang.Class p0, java.util.function.Consumer p1){ return null; } + default This registerArrayType(java.lang.Class p0, String p1, java.util.function.Function p2){ return null; } + default This registerColumnMapper(org.jdbi.v3.core.generic.GenericType p0, org.jdbi.v3.core.mapper.ColumnMapper p1){ return null; } + default This registerColumnMapper(org.jdbi.v3.core.qualifier.QualifiedType p0, org.jdbi.v3.core.mapper.ColumnMapper p1){ return null; } + default This registerRowMapper(org.jdbi.v3.core.generic.GenericType p0, org.jdbi.v3.core.mapper.RowMapper p1){ return null; } + default This addCustomizer(StatementCustomizer p0){ return null; } + default This define(String p0, Object p1){ return null; } + default This registerArgument(ArgumentFactory p0){ return null; } + default This registerArgument(QualifiedArgumentFactory p0){ return null; } + default This registerArrayType(Class p0, String p1){ return null; } + default This registerArrayType(SqlArrayType p0){ return null; } + default This registerArrayType(SqlArrayTypeFactory p0){ return null; } + default This registerCodecFactory(CodecFactory p0){ return null; } + default This registerCollector(CollectorFactory p0){ return null; } + default This registerColumnMapper(ColumnMapper p0){ return null; } + default This registerColumnMapper(ColumnMapperFactory p0){ return null; } + default This registerColumnMapper(QualifiedColumnMapperFactory p0){ return null; } + default This registerColumnMapper(Type p0, ColumnMapper p1){ return null; } + default This registerExtension(ExtensionFactory p0){ return null; } + default This registerRowMapper(RowMapper p0){ return null; } + default This registerRowMapper(RowMapperFactory p0){ return null; } + default This registerRowMapper(Type p0, RowMapper p1){ return null; } + default This setMapKeyColumn(String p0){ return null; } + default This setMapValueColumn(String p0){ return null; } + default This setSqlArrayArgumentStrategy(SqlArrayArgumentStrategy p0){ return null; } + default This setSqlLogger(SqlLogger p0){ return null; } + default This setSqlParser(SqlParser p0){ return null; } + default This setTemplateEngine(TemplateEngine p0){ return null; } + default This setTimingCollector(TimingCollector p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/JdbiConfig.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/JdbiConfig.java new file mode 100644 index 00000000000..fe64fb2c370 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/config/JdbiConfig.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.config.JdbiConfig for testing purposes + +package org.jdbi.v3.core.config; + +import org.jdbi.v3.core.config.ConfigRegistry; + +public interface JdbiConfig> +{ + This createCopy(); + default void setRegistry(ConfigRegistry p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionCallback.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionCallback.java new file mode 100644 index 00000000000..ba52cd12f4b --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionCallback.java @@ -0,0 +1,9 @@ +// Generated automatically from org.jdbi.v3.core.extension.ExtensionCallback for testing purposes + +package org.jdbi.v3.core.extension; + + +public interface ExtensionCallback +{ + R withExtension(E p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionConsumer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionConsumer.java new file mode 100644 index 00000000000..a1fbc338e51 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionConsumer.java @@ -0,0 +1,9 @@ +// Generated automatically from org.jdbi.v3.core.extension.ExtensionConsumer for testing purposes + +package org.jdbi.v3.core.extension; + + +public interface ExtensionConsumer +{ + void useExtension(E p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionContext.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionContext.java new file mode 100644 index 00000000000..0788bc0b337 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionContext.java @@ -0,0 +1,15 @@ +// Generated automatically from org.jdbi.v3.core.extension.ExtensionContext for testing purposes + +package org.jdbi.v3.core.extension; + +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.extension.ExtensionMethod; + +public class ExtensionContext +{ + protected ExtensionContext() {} + public ConfigRegistry getConfig(){ return null; } + public ExtensionContext(ConfigRegistry p0, ExtensionMethod p1){} + public ExtensionMethod getExtensionMethod(){ return null; } + public static ExtensionContext forConfig(ConfigRegistry p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionFactory.java new file mode 100644 index 00000000000..920b0fce8dc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionFactory.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.extension.ExtensionFactory for testing purposes + +package org.jdbi.v3.core.extension; + +import org.jdbi.v3.core.extension.HandleSupplier; + +public interface ExtensionFactory +{ + E attach(java.lang.Class p0, HandleSupplier p1); + boolean accepts(Class p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionMethod.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionMethod.java new file mode 100644 index 00000000000..42792f09578 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/ExtensionMethod.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.extension.ExtensionMethod for testing purposes + +package org.jdbi.v3.core.extension; + +import java.lang.reflect.Method; + +public class ExtensionMethod +{ + protected ExtensionMethod() {} + public Class getType(){ return null; } + public ExtensionMethod(Class p0, Method p1){} + public Method getMethod(){ return null; } + public String toString(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/HandleSupplier.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/HandleSupplier.java new file mode 100644 index 00000000000..1fbac152c49 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/extension/HandleSupplier.java @@ -0,0 +1,20 @@ +// Generated automatically from org.jdbi.v3.core.extension.HandleSupplier for testing purposes + +package org.jdbi.v3.core.extension; + +import java.util.concurrent.Callable; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.config.Configurable; +import org.jdbi.v3.core.extension.ExtensionContext; +import org.jdbi.v3.core.extension.ExtensionMethod; + +public interface HandleSupplier extends AutoCloseable, Configurable +{ + V invokeInContext(ExtensionMethod p0, ConfigRegistry p1, java.util.concurrent.Callable p2); + Handle getHandle(); + Jdbi getJdbi(); + default V invokeInContext(ExtensionContext p0, java.util.concurrent.Callable p1){ return null; } + default void close(){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/generic/GenericType.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/generic/GenericType.java new file mode 100644 index 00000000000..9de35ccd9df --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/generic/GenericType.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.generic.GenericType for testing purposes + +package org.jdbi.v3.core.generic; + +import java.lang.reflect.Type; + +abstract public class GenericType +{ + protected GenericType(){} + public final Type getType(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapper.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapper.java new file mode 100644 index 00000000000..c35ffb6e968 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapper.java @@ -0,0 +1,15 @@ +// Generated automatically from org.jdbi.v3.core.mapper.ColumnMapper for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.sql.ResultSet; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ColumnMapper +{ + T map(ResultSet p0, int p1, StatementContext p2); + default T map(ResultSet p0, String p1, StatementContext p2){ return null; } + default void init(ConfigRegistry p0){} + static ColumnMapper getDefaultColumnMapper(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapperFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapperFactory.java new file mode 100644 index 00000000000..6993098aaec --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/ColumnMapperFactory.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.mapper.ColumnMapperFactory for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.lang.reflect.Type; +import java.util.Optional; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.mapper.ColumnMapper; + +public interface ColumnMapperFactory +{ + Optional> build(Type p0, ConfigRegistry p1); + static ColumnMapperFactory of(Type p0, ColumnMapper p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/QualifiedColumnMapperFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/QualifiedColumnMapperFactory.java new file mode 100644 index 00000000000..e4e9a3c1c53 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/QualifiedColumnMapperFactory.java @@ -0,0 +1,16 @@ +// Generated automatically from org.jdbi.v3.core.mapper.QualifiedColumnMapperFactory for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.util.Optional; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.mapper.ColumnMapper; +import org.jdbi.v3.core.mapper.ColumnMapperFactory; +import org.jdbi.v3.core.qualifier.QualifiedType; + +public interface QualifiedColumnMapperFactory +{ + Optional> build(QualifiedType p0, ConfigRegistry p1); + static QualifiedColumnMapperFactory of(org.jdbi.v3.core.qualifier.QualifiedType p0, org.jdbi.v3.core.mapper.ColumnMapper p1){ return null; } + static QualifiedColumnMapperFactory adapt(ColumnMapperFactory p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapper.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapper.java new file mode 100644 index 00000000000..f0a802777c6 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapper.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.mapper.RowMapper for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.sql.ResultSet; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.statement.StatementContext; + +public interface RowMapper +{ + T map(ResultSet p0, StatementContext p1); + default RowMapper specialize(ResultSet p0, StatementContext p1){ return null; } + default void init(ConfigRegistry p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapperFactory.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapperFactory.java new file mode 100644 index 00000000000..41bcf489c69 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowMapperFactory.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.mapper.RowMapperFactory for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.lang.reflect.Type; +import java.util.Optional; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.mapper.RowMapper; + +public interface RowMapperFactory +{ + Optional> build(Type p0, ConfigRegistry p1); + static RowMapperFactory of(Type p0, RowMapper p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowViewMapper.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowViewMapper.java new file mode 100644 index 00000000000..39bb8ba57c9 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/mapper/RowViewMapper.java @@ -0,0 +1,15 @@ +// Generated automatically from org.jdbi.v3.core.mapper.RowViewMapper for testing purposes + +package org.jdbi.v3.core.mapper; + +import java.sql.ResultSet; +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.result.RowView; +import org.jdbi.v3.core.statement.StatementContext; + +public interface RowViewMapper extends org.jdbi.v3.core.mapper.RowMapper +{ + T map(RowView p0); + default T map(ResultSet p0, StatementContext p1){ return null; } + default org.jdbi.v3.core.mapper.RowMapper specialize(ResultSet p0, StatementContext p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/qualifier/QualifiedType.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/qualifier/QualifiedType.java new file mode 100644 index 00000000000..2df261c613d --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/qualifier/QualifiedType.java @@ -0,0 +1,30 @@ +// Generated automatically from org.jdbi.v3.core.qualifier.QualifiedType for testing purposes + +package org.jdbi.v3.core.qualifier; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Optional; +import java.util.Set; +import java.util.function.Function; +import org.jdbi.v3.core.generic.GenericType; + +public class QualifiedType +{ + protected QualifiedType() {} + public Optional> flatMapType(Function> p0){ return null; } + public QualifiedType mapType(Function p0){ return null; } + public QualifiedType with(Annotation... p0){ return null; } + public QualifiedType withAnnotationClasses(Iterable> p0){ return null; } + public QualifiedType withAnnotations(Iterable p0){ return null; } + public Set getQualifiers(){ return null; } + public String toString(){ return null; } + public Type getType(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean hasQualifier(Class p0){ return false; } + public final QualifiedType with(Class... p0){ return null; } + public int hashCode(){ return 0; } + public static org.jdbi.v3.core.qualifier.QualifiedType of(java.lang.Class p0){ return null; } + public static org.jdbi.v3.core.qualifier.QualifiedType of(org.jdbi.v3.core.generic.GenericType p0){ return null; } + public static QualifiedType of(Type p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultBearing.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultBearing.java new file mode 100644 index 00000000000..abd2df035f8 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultBearing.java @@ -0,0 +1,49 @@ +// Generated automatically from org.jdbi.v3.core.result.BatchResultBearing for testing purposes + +package org.jdbi.v3.core.result; + +import java.lang.reflect.Type; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Stream; +import org.jdbi.v3.core.generic.GenericType; +import org.jdbi.v3.core.mapper.ColumnMapper; +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.mapper.RowViewMapper; +import org.jdbi.v3.core.qualifier.QualifiedType; +import org.jdbi.v3.core.result.BatchResultIterable; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.result.ResultSetAccumulator; +import org.jdbi.v3.core.result.ResultSetScanner; +import org.jdbi.v3.core.result.RowReducer; +import org.jdbi.v3.core.result.RowView; + +public class BatchResultBearing implements ResultBearing +{ + protected BatchResultBearing() {} + public R collectRows(java.util.stream.Collector p0){ return null; } + public java.util.stream.Stream reduceRows(org.jdbi.v3.core.result.RowReducer p0){ return null; } + public java.util.stream.Stream reduceRows(java.util.function.BiConsumer, RowView> p0){ return null; } + public R collectInto(java.lang.Class p0){ return null; } + public R collectInto(org.jdbi.v3.core.generic.GenericType p0){ return null; } + public R scanResultSet(org.jdbi.v3.core.result.ResultSetScanner p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable map(org.jdbi.v3.core.mapper.ColumnMapper p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable map(org.jdbi.v3.core.mapper.RowMapper p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable map(org.jdbi.v3.core.mapper.RowViewMapper p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable mapTo(java.lang.Class p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable mapTo(org.jdbi.v3.core.generic.GenericType p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable mapTo(org.jdbi.v3.core.qualifier.QualifiedType p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable mapToBean(java.lang.Class p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable> mapToMap(java.lang.Class p0){ return null; } + public org.jdbi.v3.core.result.BatchResultIterable> mapToMap(org.jdbi.v3.core.generic.GenericType p0){ return null; } + public U reduceResultSet(U p0, org.jdbi.v3.core.result.ResultSetAccumulator p1){ return null; } + public U reduceRows(U p0, java.util.function.BiFunction p1){ return null; } + public BatchResultBearing(ResultBearing p0, Supplier p1){} + public BatchResultIterable mapTo(Type p0){ return null; } + public BatchResultIterable> mapToMap(){ return null; } + public Object collectInto(Type p0){ return null; } + public int[] modifiedRowCounts(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultIterable.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultIterable.java new file mode 100644 index 00000000000..355bbc6912a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/BatchResultIterable.java @@ -0,0 +1,13 @@ +// Generated automatically from org.jdbi.v3.core.result.BatchResultIterable for testing purposes + +package org.jdbi.v3.core.result; + +import java.util.List; +import java.util.function.Supplier; +import org.jdbi.v3.core.result.ResultIterable; + +public interface BatchResultIterable extends org.jdbi.v3.core.result.ResultIterable +{ + List> listPerBatch(); + static BatchResultIterable of(ResultIterable p0, Supplier p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorCallback.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorCallback.java new file mode 100644 index 00000000000..d1f6cb5bbb4 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.result.IteratorCallback for testing purposes + +package org.jdbi.v3.core.result; + +import org.jdbi.v3.core.result.ResultIterator; + +public interface IteratorCallback +{ + R withIterator(org.jdbi.v3.core.result.ResultIterator p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorConsumer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorConsumer.java new file mode 100644 index 00000000000..63f621c1acb --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/IteratorConsumer.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.result.IteratorConsumer for testing purposes + +package org.jdbi.v3.core.result; + +import org.jdbi.v3.core.result.ResultIterator; + +public interface IteratorConsumer +{ + void useIterator(org.jdbi.v3.core.result.ResultIterator p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultBearing.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultBearing.java new file mode 100644 index 00000000000..e4ab825e581 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultBearing.java @@ -0,0 +1,48 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultBearing for testing purposes + +package org.jdbi.v3.core.result; + +import java.lang.reflect.Type; +import java.sql.ResultSet; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Stream; +import org.jdbi.v3.core.generic.GenericType; +import org.jdbi.v3.core.mapper.ColumnMapper; +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.mapper.RowViewMapper; +import org.jdbi.v3.core.qualifier.QualifiedType; +import org.jdbi.v3.core.result.ResultIterable; +import org.jdbi.v3.core.result.ResultSetAccumulator; +import org.jdbi.v3.core.result.ResultSetScanner; +import org.jdbi.v3.core.result.RowReducer; +import org.jdbi.v3.core.result.RowView; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultBearing +{ + R scanResultSet(org.jdbi.v3.core.result.ResultSetScanner p0); + default R collectRows(java.util.stream.Collector p0){ return null; } + default java.util.stream.Stream reduceRows(org.jdbi.v3.core.result.RowReducer p0){ return null; } + default java.util.stream.Stream reduceRows(java.util.function.BiConsumer, RowView> p0){ return null; } + default R collectInto(java.lang.Class p0){ return null; } + default R collectInto(org.jdbi.v3.core.generic.GenericType p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable map(org.jdbi.v3.core.mapper.ColumnMapper p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable map(org.jdbi.v3.core.mapper.RowMapper p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable map(org.jdbi.v3.core.mapper.RowViewMapper p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable mapTo(java.lang.Class p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable mapTo(org.jdbi.v3.core.generic.GenericType p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable mapTo(org.jdbi.v3.core.qualifier.QualifiedType p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable mapToBean(java.lang.Class p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable> mapToMap(java.lang.Class p0){ return null; } + default org.jdbi.v3.core.result.ResultIterable> mapToMap(org.jdbi.v3.core.generic.GenericType p0){ return null; } + default U reduceResultSet(U p0, org.jdbi.v3.core.result.ResultSetAccumulator p1){ return null; } + default U reduceRows(U p0, java.util.function.BiFunction p1){ return null; } + default Object collectInto(Type p0){ return null; } + default ResultIterable mapTo(Type p0){ return null; } + default ResultIterable> mapToMap(){ return null; } + static ResultBearing of(Supplier p0, StatementContext p1){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterable.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterable.java new file mode 100644 index 00000000000..3a4bb976b57 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterable.java @@ -0,0 +1,45 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultIterable for testing purposes + +package org.jdbi.v3.core.result; + +import java.sql.ResultSet; +import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.Supplier; +import java.util.stream.Collector; +import java.util.stream.Stream; +import org.jdbi.v3.core.mapper.RowMapper; +import org.jdbi.v3.core.result.IteratorCallback; +import org.jdbi.v3.core.result.IteratorConsumer; +import org.jdbi.v3.core.result.ResultIterator; +import org.jdbi.v3.core.result.StreamCallback; +import org.jdbi.v3.core.result.StreamConsumer; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultIterable extends java.lang.Iterable +{ + default R withIterator(org.jdbi.v3.core.result.IteratorCallback p0){ return null; } + default R withStream(org.jdbi.v3.core.result.StreamCallback p0){ return null; } + default R collect(java.util.stream.Collector p0){ return null; } + default ResultIterable map(java.util.function.Function p0){ return null; } + default U reduce(U p0, java.util.function.BiFunction p1){ return null; } + default void useIterator(org.jdbi.v3.core.result.IteratorConsumer p0){} + default void useStream(org.jdbi.v3.core.result.StreamConsumer p0){} + default ResultIterable filter(java.util.function.Predicate p0){ return null; } + default T findOnly(){ return null; } + default T first(){ return null; } + default T one(){ return null; } + default int forEachWithCount(java.util.function.Consumer p0){ return 0; } + default java.util.List list(){ return null; } + default java.util.Optional findFirst(){ return null; } + default java.util.Optional findOne(){ return null; } + default java.util.stream.Stream stream(){ return null; } + default void forEach(java.util.function.Consumer p0){} + org.jdbi.v3.core.result.ResultIterator iterator(); + static org.jdbi.v3.core.result.ResultIterable of(Supplier p0, org.jdbi.v3.core.mapper.RowMapper p1, StatementContext p2){ return null; } + static org.jdbi.v3.core.result.ResultIterable of(org.jdbi.v3.core.result.ResultIterator p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterator.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterator.java new file mode 100644 index 00000000000..1efb74ff8a2 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultIterator.java @@ -0,0 +1,15 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultIterator for testing purposes + +package org.jdbi.v3.core.result; + +import java.io.Closeable; +import java.util.Iterator; +import java.util.function.Consumer; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultIterator extends Closeable, java.util.Iterator +{ + StatementContext getContext(); + default void forEachRemaining(java.util.function.Consumer p0){} + void close(); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultProducer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultProducer.java new file mode 100644 index 00000000000..b3abe5bd54f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultProducer.java @@ -0,0 +1,12 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultProducer for testing purposes + +package org.jdbi.v3.core.result; + +import java.sql.PreparedStatement; +import java.util.function.Supplier; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultProducer +{ + R produce(Supplier p0, StatementContext p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetAccumulator.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetAccumulator.java new file mode 100644 index 00000000000..0b85ffce1e0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetAccumulator.java @@ -0,0 +1,11 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultSetAccumulator for testing purposes + +package org.jdbi.v3.core.result; + +import java.sql.ResultSet; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultSetAccumulator +{ + T apply(T p0, ResultSet p1, StatementContext p2); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetScanner.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetScanner.java new file mode 100644 index 00000000000..0634bb27a14 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/ResultSetScanner.java @@ -0,0 +1,12 @@ +// Generated automatically from org.jdbi.v3.core.result.ResultSetScanner for testing purposes + +package org.jdbi.v3.core.result; + +import java.sql.ResultSet; +import java.util.function.Supplier; +import org.jdbi.v3.core.statement.StatementContext; + +public interface ResultSetScanner +{ + T scanResultSet(Supplier p0, StatementContext p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowReducer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowReducer.java new file mode 100644 index 00000000000..39d5d403f3f --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowReducer.java @@ -0,0 +1,13 @@ +// Generated automatically from org.jdbi.v3.core.result.RowReducer for testing purposes + +package org.jdbi.v3.core.result; + +import java.util.stream.Stream; +import org.jdbi.v3.core.result.RowView; + +public interface RowReducer +{ + C container(); + java.util.stream.Stream stream(C p0); + void accumulate(C p0, RowView p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowView.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowView.java new file mode 100644 index 00000000000..68e85d9fdcc --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/RowView.java @@ -0,0 +1,23 @@ +// Generated automatically from org.jdbi.v3.core.result.RowView for testing purposes + +package org.jdbi.v3.core.result; + +import java.lang.reflect.Type; +import org.jdbi.v3.core.generic.GenericType; +import org.jdbi.v3.core.qualifier.QualifiedType; + +abstract public class RowView +{ + public T getColumn(String p0, java.lang.Class p1){ return null; } + public T getColumn(String p0, org.jdbi.v3.core.generic.GenericType p1){ return null; } + public T getColumn(int p0, java.lang.Class p1){ return null; } + public T getColumn(int p0, org.jdbi.v3.core.generic.GenericType p1){ return null; } + public T getRow(java.lang.Class p0){ return null; } + public T getRow(org.jdbi.v3.core.generic.GenericType p0){ return null; } + public Object getColumn(String p0, Type p1){ return null; } + public Object getColumn(int p0, Type p1){ return null; } + public RowView(){} + public abstract T getColumn(String p0, org.jdbi.v3.core.qualifier.QualifiedType p1); + public abstract T getColumn(int p0, org.jdbi.v3.core.qualifier.QualifiedType p1); + public abstract Object getRow(Type p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamCallback.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamCallback.java new file mode 100644 index 00000000000..fda0f043f81 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamCallback.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.result.StreamCallback for testing purposes + +package org.jdbi.v3.core.result; + +import java.util.stream.Stream; + +public interface StreamCallback +{ + R withStream(java.util.stream.Stream p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamConsumer.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamConsumer.java new file mode 100644 index 00000000000..d836b0aa885 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/result/StreamConsumer.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.result.StreamConsumer for testing purposes + +package org.jdbi.v3.core.result; + +import java.util.stream.Stream; + +public interface StreamConsumer +{ + void useStream(java.util.stream.Stream p0); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/spi/JdbiPlugin.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/spi/JdbiPlugin.java new file mode 100644 index 00000000000..79fd2339032 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/spi/JdbiPlugin.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.spi.JdbiPlugin for testing purposes + +package org.jdbi.v3.core.spi; + +import java.sql.Connection; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.Jdbi; + +public interface JdbiPlugin +{ + default Connection customizeConnection(Connection p0){ return null; } + default Handle customizeHandle(Handle p0){ return null; } + default void customizeJdbi(Jdbi p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/BaseStatement.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/BaseStatement.java new file mode 100644 index 00000000000..2b7e48eb630 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/BaseStatement.java @@ -0,0 +1,24 @@ +// Generated automatically from org.jdbi.v3.core.statement.BaseStatement for testing purposes + +package org.jdbi.v3.core.statement; + +import java.io.Closeable; +import java.sql.SQLException; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.config.ConfigRegistry; +import org.jdbi.v3.core.config.Configurable; +import org.jdbi.v3.core.statement.StatementContext; +import org.jdbi.v3.core.statement.StatementCustomizer; + +abstract class BaseStatement implements Closeable, org.jdbi.v3.core.config.Configurable +{ + protected BaseStatement() {} + protected final void cleanUpForException(SQLException p0){} + public ConfigRegistry getConfig(){ return null; } + public final Handle getHandle(){ return null; } + public final StatementContext getContext(){ return null; } + public final This attachToHandleForCleanup(){ return null; } + public final boolean equals(Object p0){ return false; } + public final int hashCode(){ return 0; } + public void close(){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Batch.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Batch.java new file mode 100644 index 00000000000..b8c4029a370 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Batch.java @@ -0,0 +1,14 @@ +// Generated automatically from org.jdbi.v3.core.statement.Batch for testing purposes + +package org.jdbi.v3.core.statement; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.statement.BaseStatement; + +public class Batch extends BaseStatement +{ + protected Batch() {} + public Batch add(String p0){ return null; } + public Batch(Handle p0){} + public int[] execute(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Binding.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Binding.java new file mode 100644 index 00000000000..4e610983029 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Binding.java @@ -0,0 +1,34 @@ +// Generated automatically from org.jdbi.v3.core.statement.Binding for testing purposes + +package org.jdbi.v3.core.statement; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import org.jdbi.v3.core.argument.Argument; +import org.jdbi.v3.core.argument.NamedArgumentFinder; +import org.jdbi.v3.core.qualifier.QualifiedType; +import org.jdbi.v3.core.statement.StatementContext; + +public class Binding +{ + protected Binding() {} + protected Binding(StatementContext p0){} + protected final List namedArgumentFinder = null; + protected final Map positionals = null; + protected final Map named = null; + public Collection getNames(){ return null; } + public Optional findForName(String p0, StatementContext p1){ return null; } + public Optional findForPosition(int p0){ return null; } + public String toString(){ return null; } + public boolean isEmpty(){ return false; } + public void addNamed(String p0, Argument p1){} + public void addNamed(String p0, Object p1){} + public void addNamed(String p0, Object p1, QualifiedType p2){} + public void addNamedArgumentFinder(NamedArgumentFinder p0){} + public void addPositional(int p0, Argument p1){} + public void addPositional(int p0, Object p1){} + public void addPositional(int p0, Object p1, QualifiedType p2){} + public void clear(){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Call.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Call.java new file mode 100644 index 00000000000..6b389ce2f33 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Call.java @@ -0,0 +1,24 @@ +// Generated automatically from org.jdbi.v3.core.statement.Call for testing purposes + +package org.jdbi.v3.core.statement; + +import java.util.function.Consumer; +import java.util.function.Function; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.statement.CallableStatementMapper; +import org.jdbi.v3.core.statement.OutParameters; +import org.jdbi.v3.core.statement.SqlStatement; + +public class Call extends SqlStatement +{ + protected Call() {} + public T invoke(Function p0){ return null; } + public Call registerOutParameter(String p0, int p1){ return null; } + public Call registerOutParameter(String p0, int p1, CallableStatementMapper p2){ return null; } + public Call registerOutParameter(int p0, int p1){ return null; } + public Call registerOutParameter(int p0, int p1, CallableStatementMapper p2){ return null; } + public Call(Handle p0, CharSequence p1){} + public Call(Handle p0, String p1){} + public OutParameters invoke(){ return null; } + public void invoke(Consumer p0){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/CallableStatementMapper.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/CallableStatementMapper.java new file mode 100644 index 00000000000..e299f1c3fb0 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/CallableStatementMapper.java @@ -0,0 +1,10 @@ +// Generated automatically from org.jdbi.v3.core.statement.CallableStatementMapper for testing purposes + +package org.jdbi.v3.core.statement; + +import java.sql.CallableStatement; + +public interface CallableStatementMapper +{ + Object map(int p0, CallableStatement p1); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Cleanable.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Cleanable.java new file mode 100644 index 00000000000..baa2f06a6ec --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Cleanable.java @@ -0,0 +1,9 @@ +// Generated automatically from org.jdbi.v3.core.statement.Cleanable for testing purposes + +package org.jdbi.v3.core.statement; + + +public interface Cleanable extends AutoCloseable +{ + void close(); +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/MetaData.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/MetaData.java new file mode 100644 index 00000000000..5772b047558 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/MetaData.java @@ -0,0 +1,26 @@ +// Generated automatically from org.jdbi.v3.core.statement.MetaData for testing purposes + +package org.jdbi.v3.core.statement; + +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.result.ResultSetScanner; +import org.jdbi.v3.core.statement.BaseStatement; + +public class MetaData extends BaseStatement implements ResultBearing +{ + protected MetaData() {} + public R execute(){ return null; } + public R scanResultSet(org.jdbi.v3.core.result.ResultSetScanner p0){ return null; } + public MetaData(Handle p0, MetaData.MetaDataValueProvider p1){} + static public interface MetaDataResultSetProvider extends MetaData.MetaDataValueProvider + { + ResultSet provideValue(DatabaseMetaData p0); + } + static public interface MetaDataValueProvider + { + T provideValue(DatabaseMetaData p0); + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/OutParameters.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/OutParameters.java new file mode 100644 index 00000000000..c0126aed19e --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/OutParameters.java @@ -0,0 +1,35 @@ +// Generated automatically from org.jdbi.v3.core.statement.OutParameters for testing purposes + +package org.jdbi.v3.core.statement; + +import java.sql.Timestamp; +import org.jdbi.v3.core.result.ResultBearing; + +public class OutParameters +{ + protected OutParameters() {} + public T getObject(String p0, java.lang.Class p1){ return null; } + public T getObject(int p0, java.lang.Class p1){ return null; } + public Double getDouble(String p0){ return null; } + public Double getDouble(int p0){ return null; } + public Float getFloat(String p0){ return null; } + public Float getFloat(int p0){ return null; } + public Integer getInt(String p0){ return null; } + public Integer getInt(int p0){ return null; } + public Long getLong(String p0){ return null; } + public Long getLong(int p0){ return null; } + public Object getObject(String p0){ return null; } + public Object getObject(int p0){ return null; } + public ResultBearing getRowSet(String p0){ return null; } + public ResultBearing getRowSet(int p0){ return null; } + public Short getShort(String p0){ return null; } + public Short getShort(int p0){ return null; } + public String getString(String p0){ return null; } + public String getString(int p0){ return null; } + public Timestamp getTimestamp(String p0){ return null; } + public Timestamp getTimestamp(int p0){ return null; } + public byte[] getBytes(String p0){ return null; } + public byte[] getBytes(int p0){ return null; } + public java.sql.Date getDate(String p0){ return null; } + public java.sql.Date getDate(int p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedParameters.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedParameters.java new file mode 100644 index 00000000000..b6b7d07e4d5 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedParameters.java @@ -0,0 +1,18 @@ +// Generated automatically from org.jdbi.v3.core.statement.ParsedParameters for testing purposes + +package org.jdbi.v3.core.statement; + +import java.util.List; + +public class ParsedParameters +{ + protected ParsedParameters() {} + public List getParameterNames(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public boolean isPositional(){ return false; } + public int getParameterCount(){ return 0; } + public int hashCode(){ return 0; } + public static ParsedParameters named(List p0){ return null; } + public static ParsedParameters positional(int p0){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedSql.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedSql.java new file mode 100644 index 00000000000..a6c71c8915a --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/ParsedSql.java @@ -0,0 +1,25 @@ +// Generated automatically from org.jdbi.v3.core.statement.ParsedSql for testing purposes + +package org.jdbi.v3.core.statement; + +import org.jdbi.v3.core.statement.ParsedParameters; + +public class ParsedSql +{ + protected ParsedSql() {} + public ParsedParameters getParameters(){ return null; } + public String getSql(){ return null; } + public String toString(){ return null; } + public boolean equals(Object p0){ return false; } + public int hashCode(){ return 0; } + public static ParsedSql of(String p0, ParsedParameters p1){ return null; } + public static ParsedSql.Builder builder(){ return null; } + static public class Builder + { + protected Builder() {} + public ParsedSql build(){ return null; } + public ParsedSql.Builder append(String p0){ return null; } + public ParsedSql.Builder appendNamedParameter(String p0){ return null; } + public ParsedSql.Builder appendPositionalParameter(){ return null; } + } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/PreparedBatch.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/PreparedBatch.java new file mode 100644 index 00000000000..f6544021e48 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/PreparedBatch.java @@ -0,0 +1,31 @@ +// Generated automatically from org.jdbi.v3.core.statement.PreparedBatch for testing purposes + +package org.jdbi.v3.core.statement; + +import java.util.Map; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.result.BatchResultBearing; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.result.ResultIterator; +import org.jdbi.v3.core.result.ResultProducer; +import org.jdbi.v3.core.result.ResultSetScanner; +import org.jdbi.v3.core.statement.SqlStatement; +import org.jdbi.v3.core.statement.internal.PreparedBinding; + +public class PreparedBatch extends SqlStatement implements ResultBearing +{ + protected PreparedBatch() {} + protected PreparedBinding getBinding(){ return null; } + public R execute(org.jdbi.v3.core.result.ResultProducer p0){ return null; } + public R scanResultSet(org.jdbi.v3.core.result.ResultSetScanner p0){ return null; } + public BatchResultBearing executePreparedBatch(String... p0){ return null; } + public PreparedBatch add(){ return null; } + public PreparedBatch add(Map p0){ return null; } + public PreparedBatch add(Object... p0){ return null; } + public PreparedBatch(Handle p0, CharSequence p1){} + public PreparedBatch(Handle p0, String p1){} + public ResultBearing executeAndReturnGeneratedKeys(String... p0){ return null; } + public ResultIterator executeAndGetModCount(){ return null; } + public int size(){ return 0; } + public int[] execute(){ return null; } +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Query.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Query.java new file mode 100644 index 00000000000..841bb3be797 --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Query.java @@ -0,0 +1,22 @@ +// Generated automatically from org.jdbi.v3.core.statement.Query for testing purposes + +package org.jdbi.v3.core.statement; + +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.result.ResultBearing; +import org.jdbi.v3.core.result.ResultProducer; +import org.jdbi.v3.core.result.ResultSetScanner; +import org.jdbi.v3.core.statement.SqlStatement; + +public class Query extends SqlStatement implements ResultBearing +{ + protected Query() {} + public R execute(org.jdbi.v3.core.result.ResultProducer p0){ return null; } + public R scanResultSet(org.jdbi.v3.core.result.ResultSetScanner p0){ return null; } + public Query concurrentUpdatable(){ return null; } + public Query setFetchSize(int p0){ return null; } + public Query setMaxFieldSize(int p0){ return null; } + public Query setMaxRows(int p0){ return null; } + public Query(Handle p0, CharSequence p1){} + public Query(Handle p0, String p1){} +} diff --git a/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Script.java b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Script.java new file mode 100644 index 00000000000..9da3e966e4c --- /dev/null +++ b/java/ql/test/stubs/javafx-web/org/jdbi/v3/core/statement/Script.java @@ -0,0 +1,17 @@ +// Generated automatically from org.jdbi.v3.core.statement.Script for testing purposes + +package org.jdbi.v3.core.statement; + +import java.util.List; +import org.jdbi.v3.core.Handle; +import org.jdbi.v3.core.statement.SqlStatement; + +public class Script extends SqlStatement